James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one |
| 3 | * or more contributor license agreements. See the NOTICE file |
| 4 | * distributed with this work for additional information |
| 5 | * regarding copyright ownership. The ASF licenses this file |
| 6 | * to you under the Apache License, Version 2.0 (the |
| 7 | * "License"); you may not use this file except in compliance |
| 8 | * with the License. You may obtain a copy of the License at |
| 9 | * |
| 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 11 | * |
| 12 | * Unless required by applicable law or agreed to in writing, |
| 13 | * software distributed under the License is distributed on an |
| 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 15 | * KIND, either express or implied. See the License for the |
| 16 | * specific language governing permissions and limitations |
| 17 | * under the License. |
| 18 | */ |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 19 | #define _POSIX_C_SOURCE 200112L /* https://stackoverflow.com/questions/37541985/storage-size-of-addrinfo-isnt-known */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 20 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 21 | |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 22 | #include <sys/wait.h> |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 23 | #include <arpa/inet.h> |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 24 | #include <sys/types.h> |
| 25 | #include <sys/socket.h> |
| 26 | #include <netdb.h> |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 27 | |
| 28 | #include <thrift/c_glib/transport/thrift_transport.h> |
| 29 | #include <thrift/c_glib/transport/thrift_buffered_transport.h> |
| 30 | #include <thrift/c_glib/transport/thrift_server_transport.h> |
| 31 | #include <thrift/c_glib/transport/thrift_server_socket.h> |
| 32 | #include <thrift/c_glib/transport/thrift_ssl_socket.h> |
| 33 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 34 | /* #define TEST_DATA { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' } */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 35 | #define TEST_DATA { "GET / HTTP/1.1\n\n" } |
| 36 | |
| 37 | |
| 38 | /* substituted functions to test failures of system and library calls */ |
| 39 | static int socket_error = 0; |
| 40 | int |
| 41 | my_socket(int domain, int type, int protocol) |
| 42 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 43 | if (socket_error == 0) |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 44 | { |
| 45 | return socket (domain, type, protocol); |
| 46 | } |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 47 | return -1; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 48 | } |
| 49 | |
| 50 | static int recv_error = 0; |
| 51 | ssize_t |
| 52 | my_recv(int socket, void *buffer, size_t length, int flags) |
| 53 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 54 | if (recv_error == 0) |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 55 | { |
| 56 | return recv (socket, buffer, length, flags); |
| 57 | } |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 58 | return -1; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | static int send_error = 0; |
| 62 | ssize_t |
| 63 | my_send(int socket, const void *buffer, size_t length, int flags) |
| 64 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 65 | if (send_error == 0) |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 66 | { |
| 67 | return send (socket, buffer, length, flags); |
| 68 | } |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 69 | return -1; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 70 | } |
| 71 | |
| 72 | #define socket my_socket |
| 73 | #define recv my_recv |
| 74 | #define send my_send |
| 75 | #include "../src/thrift/c_glib/transport/thrift_ssl_socket.c" |
| 76 | #undef socket |
| 77 | #undef recv |
| 78 | #undef send |
| 79 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 80 | static void thrift_socket_server (const int port); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 81 | |
| 82 | /* test object creation and destruction */ |
| 83 | static void |
| 84 | test_ssl_create_and_destroy(void) |
| 85 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 86 | gchar *hostname = NULL; |
| 87 | guint port = 0; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 88 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 89 | GObject *object = NULL; |
| 90 | object = g_object_new (THRIFT_TYPE_SSL_SOCKET, NULL); |
| 91 | g_assert (object != NULL); |
| 92 | g_object_get (G_OBJECT(object), "hostname", &hostname, "port", &port, NULL); |
| 93 | g_free (hostname); |
| 94 | g_object_unref (object); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 95 | } |
| 96 | |
| 97 | static void |
| 98 | test_ssl_create_and_set_properties(void) |
| 99 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 100 | gchar *hostname = NULL; |
| 101 | guint port = 0; |
| 102 | SSL_CTX* ssl_ctx= NULL; |
| 103 | GError *error=NULL; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 104 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 105 | GObject *object = NULL; |
| 106 | object = thrift_ssl_socket_new(SSLTLS, &error); |
| 107 | g_object_get (G_OBJECT(object), "hostname", &hostname, "port", &port, "ssl_context", &ssl_ctx, NULL); |
| 108 | g_assert (ssl_ctx!=NULL); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 109 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 110 | g_free (hostname); |
| 111 | g_object_unref (object); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | static void |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 115 | test_ssl_open_and_close_non_ssl_server(void) |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 116 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 117 | ThriftSSLSocket *tSSLSocket = NULL; |
| 118 | ThriftTransport *transport = NULL; |
| 119 | GError *error=NULL; |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 120 | pid_t pid; |
| 121 | int non_ssl_port = 51198; |
| 122 | char errormsg[255]; |
| 123 | |
| 124 | |
| 125 | pid = fork (); |
| 126 | g_assert ( pid >= 0 ); |
| 127 | |
| 128 | if ( pid == 0 ) |
| 129 | { |
| 130 | /* child listens */ |
| 131 | /* This is a non SSL server */ |
| 132 | thrift_socket_server (non_ssl_port); |
| 133 | exit (0); |
| 134 | } else { |
| 135 | /* parent connects, wait a bit for the socket to be created */ |
| 136 | sleep (1); |
| 137 | |
| 138 | /* open a connection and close it */ |
| 139 | tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", non_ssl_port, &error); |
| 140 | |
| 141 | transport = THRIFT_TRANSPORT (tSSLSocket); |
| 142 | g_assert (thrift_ssl_socket_open (transport, &error) == FALSE); |
| 143 | g_assert_cmpstr(error->message, == ,"Error while connect/bind: 68 -> Connection reset by peer"); |
| 144 | g_clear_error (&error); |
| 145 | g_assert (thrift_ssl_socket_is_open (transport) == FALSE); |
| 146 | thrift_ssl_socket_close (transport, NULL); |
| 147 | g_assert (thrift_ssl_socket_is_open (transport) == FALSE); |
| 148 | |
| 149 | /* test close failure */ |
| 150 | THRIFT_SOCKET(tSSLSocket)->sd = -1; |
| 151 | thrift_ssl_socket_close (transport, NULL); |
| 152 | g_object_unref (tSSLSocket); |
| 153 | |
| 154 | /* try a hostname lookup failure */ |
| 155 | tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost.broken", non_ssl_port, &error); |
| 156 | transport = THRIFT_TRANSPORT (tSSLSocket); |
| 157 | g_assert (thrift_ssl_socket_open (transport, &error) == FALSE); |
| 158 | snprintf(errormsg, 255, "host lookup failed for localhost.broken:%d - Unknown host", non_ssl_port); |
| 159 | g_assert_cmpstr(error->message, ==, errormsg); |
| 160 | g_clear_error (&error); |
| 161 | g_object_unref (tSSLSocket); |
| 162 | error = NULL; |
| 163 | |
| 164 | /* try an error call to socket() */ |
| 165 | /* |
| 166 | tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", port, &error); |
| 167 | transport = THRIFT_TRANSPORT (tSSLSocket); |
| 168 | socket_error = 1; |
| 169 | assert (thrift_ssl_socket_open (transport, &error) == FALSE); |
| 170 | socket_error = 0; |
| 171 | g_object_unref (tSSLSocket); |
| 172 | g_error_free (error); |
| 173 | */ |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | static void |
| 178 | test_ssl_write_invalid_socket(void) |
| 179 | { |
| 180 | ThriftSSLSocket *tSSLSocket = NULL; |
| 181 | ThriftTransport *transport = NULL; |
| 182 | GError *error=NULL; |
| 183 | char buffer[] = "this must not break"; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 184 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 185 | /* open a connection and close it */ |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 186 | tSSLSocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", 51188+1, &error); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 187 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 188 | transport = THRIFT_TRANSPORT (tSSLSocket); |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 189 | g_assert (thrift_ssl_socket_open (transport, NULL) == FALSE); |
| 190 | g_assert (thrift_ssl_socket_is_open (transport) == FALSE); |
| 191 | |
| 192 | /* FIXME This must be tested but since the assertion inside thrift_ssl_socket_write breaks the test unit |
| 193 | it's disabled. They idea is to disable trap/coredump during this test |
| 194 | g_assert (thrift_ssl_socket_write(transport, buffer, sizeof(buffer), &error) == FALSE); |
| 195 | g_message ("write_failed_with_error: %s", |
| 196 | error != NULL ? error->message : "No"); |
| 197 | g_clear_error (&error); |
| 198 | */ |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 199 | thrift_ssl_socket_close (transport, NULL); |
| 200 | g_assert (thrift_ssl_socket_is_open (transport) == FALSE); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 201 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 202 | /* test close failure */ |
| 203 | THRIFT_SOCKET(tSSLSocket)->sd = -1; |
| 204 | thrift_ssl_socket_close (transport, NULL); |
| 205 | g_object_unref (tSSLSocket); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 206 | } |
| 207 | |
| 208 | |
| 209 | |
| 210 | /** |
| 211 | * Print the common name of certificate |
| 212 | */ |
| 213 | unsigned char * get_cn_name(X509_NAME* const name) |
| 214 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 215 | int idx = -1; |
| 216 | unsigned char *utf8 = NULL; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 217 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 218 | do |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 219 | { |
| 220 | if(!name) break; /* failed */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 221 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 222 | idx = X509_NAME_get_index_by_NID(name, NID_commonName, -1); |
| 223 | if(!(idx > -1)) break; /* failed */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 224 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 225 | X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, idx); |
| 226 | if(!entry) break; /* failed */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 227 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 228 | ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry); |
| 229 | if(!data) break; /* failed */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 230 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 231 | int length = ASN1_STRING_to_UTF8(&utf8, data); |
| 232 | if(!utf8 || !(length > 0)) break; /* failed */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 233 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 234 | } while (0); |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 235 | return utf8; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 236 | } |
| 237 | |
| 238 | /* |
| 239 | * Handle IPV4 and IPV6 addr |
| 240 | */ |
| 241 | void *get_in_addr(struct sockaddr *sa) |
| 242 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 243 | if (sa->sa_family == AF_INET) |
| 244 | return &(((struct sockaddr_in*)sa)->sin_addr); |
| 245 | return &(((struct sockaddr_in6*)sa)->sin6_addr); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | int verify_ip(char * hostname, struct sockaddr_storage *addr) |
| 249 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 250 | struct addrinfo *addr_info,*p; |
| 251 | struct addrinfo hints; |
| 252 | int res; |
| 253 | int retval = 0; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 254 | |
| 255 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 256 | memset(&hints, 0, sizeof (struct addrinfo)); |
| 257 | hints.ai_family = AF_UNSPEC; /* use AF_INET6 to force IPv6 */ |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 258 | hints.ai_socktype = SOCK_STREAM; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 259 | |
| 260 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 261 | if ( (res = getaddrinfo(hostname, NULL, &hints, &addr_info) ) != 0) |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 262 | { |
| 263 | /* get the host info */ |
| 264 | g_error("Cannot get the host address"); |
| 265 | return retval; |
| 266 | } |
| 267 | /* loop through all the results and connect to the first we can */ |
| 268 | char dnshost[INET6_ADDRSTRLEN]; /* bigger addr supported IPV6 */ |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 269 | char socket_ip[INET6_ADDRSTRLEN]; |
| 270 | if(inet_ntop(addr->ss_family, get_in_addr(addr), socket_ip, INET6_ADDRSTRLEN)==socket_ip){ |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 271 | g_debug("We are connected to host %s checking against certificate...", socket_ip); |
| 272 | int sizeip = socket_ip!=NULL ? strlen(socket_ip) : 0; |
| 273 | for(p = addr_info; p != NULL; p = p->ai_next) { |
| 274 | if(inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr), dnshost, INET6_ADDRSTRLEN)==dnshost){ |
| 275 | if(dnshost!=NULL){ |
| 276 | g_info("DNS address [%i -> %s]", p->ai_addr, dnshost); |
| 277 | if(!strncmp(dnshost, socket_ip, sizeip)){ |
| 278 | retval=1; |
| 279 | break; /* if we get here, we must have connected successfully */ |
| 280 | } |
| 281 | } |
| 282 | } |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 283 | } |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 284 | } |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 285 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 286 | if(addr_info) |
| 287 | freeaddrinfo(addr_info); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 288 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 289 | return retval; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 290 | } |
| 291 | |
| 292 | static void |
| 293 | read_from_file(char *buffer, long size, const char *file_name) |
| 294 | { |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 295 | char ch; |
| 296 | long index=0; |
| 297 | FILE *fp; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 298 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 299 | fp = fopen(file_name,"r"); /* read mode */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 300 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 301 | if( fp == NULL ) |
| 302 | { |
| 303 | perror("Error while opening the file.\n"); |
| 304 | exit(EXIT_FAILURE); |
| 305 | } |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 306 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 307 | printf("The contents of %s file are :\n", file_name); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 308 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 309 | while(index<size && ( ch = fgetc(fp) ) != EOF ){ |
| 310 | buffer[index++] = ch; |
| 311 | } |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 312 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 313 | fclose(fp); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 314 | } |
| 315 | |
| 316 | #define ISSUER_CN_PINNING "The Apache Software Foundation" |
| 317 | #define SUBJECT_CN_PINNING "localhost" |
| 318 | #define CERT_SERIAL_NUMBER "1" |
| 319 | |
| 320 | gboolean verify_certificate_sn(X509 *cert, const unsigned char *serial_number) |
| 321 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 322 | gboolean retval = FALSE; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 323 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 324 | ASN1_INTEGER *serial = X509_get_serialNumber(cert); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 325 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 326 | BIGNUM *bn = ASN1_INTEGER_to_BN(serial, NULL); |
| 327 | if (!bn) { |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 328 | fprintf(stderr, "unable to convert ASN1INTEGER to BN\n"); |
| 329 | return EXIT_FAILURE; |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 330 | } |
| 331 | char *tmp = BN_bn2dec(bn); |
| 332 | if (!tmp) { |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 333 | g_warning(stderr, "unable to convert BN to decimal string.\n"); |
| 334 | BN_free(bn); |
| 335 | return EXIT_FAILURE; |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 336 | } |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 337 | /* |
| 338 | if (strlen(tmp) >= len) { |
| 339 | g_warn(stderr, "buffer length shorter than serial number\n"); |
| 340 | BN_free(bn); |
| 341 | OPENSSL_free(tmp); |
| 342 | return EXIT_FAILURE; |
| 343 | } |
| 344 | */ |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 345 | if(!strncmp(serial_number, tmp, strlen(serial_number))){ |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 346 | retval=TRUE; |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 347 | }else{ |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 348 | g_warning("Serial number is not valid"); |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 349 | } |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 350 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 351 | BN_free(bn); |
| 352 | OPENSSL_free(tmp); |
| 353 | return retval; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 354 | } |
| 355 | |
| 356 | gboolean my_access_manager(ThriftTransport * transport, X509 *cert, struct sockaddr_storage *addr, GError **error) |
| 357 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 358 | ThriftSSLSocket *sslSocket = THRIFT_SSL_SOCKET (transport); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 359 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 360 | g_info("Processing access to the server"); |
| 361 | X509_NAME* iname = cert ? X509_get_issuer_name(cert) : NULL; |
| 362 | X509_NAME* sname = cert ? X509_get_subject_name(cert) : NULL; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 363 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 364 | /* Issuer is the authority we trust that warrants nothing useful */ |
| 365 | const unsigned char * issuer = get_cn_name(iname); |
| 366 | if(issuer){ |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 367 | gboolean valid = TRUE; |
| 368 | g_info("Issuer (cn) %s", issuer); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 369 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 370 | /* Issuer pinning */ |
| 371 | if(strncmp(ISSUER_CN_PINNING, issuer, strlen(ISSUER_CN_PINNING))){ |
| 372 | g_warning("The Issuer of the certificate is not valid"); |
| 373 | valid=FALSE; |
| 374 | } |
| 375 | OPENSSL_free(issuer); |
| 376 | if(!valid) |
| 377 | return valid; |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 378 | } |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 379 | |
| 380 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 381 | /* Subject is who the certificate is issued to by the authority */ |
| 382 | const unsigned char * subject = get_cn_name(sname); |
| 383 | if(subject){ |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 384 | g_info("Subject (cn) %s", subject); |
| 385 | gboolean valid = TRUE; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 386 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 387 | /* Subject pinning */ |
| 388 | if(strncmp(SUBJECT_CN_PINNING, subject, strlen(SUBJECT_CN_PINNING))){ |
| 389 | g_warning("The subject of the certificate is not valid"); |
| 390 | valid=FALSE; |
| 391 | } |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 392 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 393 | if(!valid) |
| 394 | return valid; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 395 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 396 | /* Host pinning */ |
| 397 | if(verify_ip(subject, addr)){ |
| 398 | g_info("Verified subject"); |
| 399 | }else{ |
| 400 | g_info("Cannot verify subject"); |
| 401 | valid=FALSE; |
| 402 | } |
| 403 | OPENSSL_free(subject); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 404 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 405 | if(!valid) |
| 406 | return valid; |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 407 | } |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 408 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 409 | if(!verify_certificate_sn(cert, CERT_SERIAL_NUMBER)){ |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 410 | return FALSE; |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 411 | }else{ |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 412 | g_info("Verified serial number"); |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 413 | } |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 414 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 415 | return TRUE; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 416 | |
| 417 | } |
| 418 | |
| 419 | |
| 420 | |
| 421 | |
| 422 | #ifdef BUILD_SERVER |
| 423 | static void |
| 424 | test_ssl_authorization_manager(void) |
| 425 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 426 | int status=0; |
| 427 | pid_t pid; |
| 428 | ThriftSSLSocket *tSSLsocket = NULL; |
| 429 | ThriftTransport *transport = NULL; |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 430 | /* int port = 51199; */ |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 431 | int port = 443; |
| 432 | GError *error=NULL; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 433 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 434 | guchar buf[17] = TEST_DATA; /* a buffer */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 435 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 436 | /* |
| 437 | pid = fork (); |
| 438 | g_assert ( pid >= 0 ); |
| 439 | |
| 440 | if ( pid == 0 ) |
| 441 | { |
| 442 | thrift_ssl_socket_server (port); |
| 443 | exit (0); |
| 444 | } else { |
| 445 | */ |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 446 | /* parent connects, wait a bit for the socket to be created */ |
| 447 | sleep (1); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 448 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 449 | /* Test against level2 owncloud certificate */ |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 450 | tSSLsocket = thrift_ssl_socket_new_with_host(SSLTLS, "localhost", port, &error); |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 451 | thrift_ssl_socket_set_manager(tSSLsocket, my_access_manager); /* Install pinning manager */ |
| 452 | /* thrift_ssl_load_cert_from_file(tSSLsocket, "./owncloud.level2crm.pem"); */ |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 453 | unsigned char cert_buffer[65534]; |
| 454 | read_from_file(cert_buffer, 65534, "../../keys/client.pem"); |
| 455 | if(!thrift_ssl_load_cert_from_buffer(tSSLsocket, cert_buffer)){ |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 456 | g_warning("Certificates cannot be loaded!"); |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 457 | } |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 458 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 459 | transport = THRIFT_TRANSPORT (tSSLsocket); |
| 460 | g_assert (thrift_ssl_socket_open (transport, NULL) == TRUE); |
| 461 | g_assert (thrift_ssl_socket_is_open (transport)); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 462 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 463 | thrift_ssl_socket_write (transport, buf, 17, NULL); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 464 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 465 | /* write fail */ |
| 466 | send_error = 1; |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 467 | /* |
| 468 | thrift_ssl_socket_write (transport, buf, 1, NULL); |
| 469 | send_error = 0; |
| 470 | thrift_ssl_socket_write_end (transport, NULL); |
| 471 | thrift_ssl_socket_flush (transport, NULL); |
| 472 | */ |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 473 | thrift_ssl_socket_close (transport, NULL); |
| 474 | g_object_unref (tSSLsocket); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 475 | |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 476 | /* g_assert ( wait (&status) == pid ); */ |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 477 | g_assert ( status == 0 ); |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 478 | /* } */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 479 | } |
| 480 | #endif |
| 481 | |
| 482 | |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 483 | static void |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 484 | thrift_socket_server (const int port) |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 485 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 486 | int bytes = 0; |
| 487 | ThriftServerTransport *transport = NULL; |
| 488 | ThriftTransport *client = NULL; |
| 489 | guchar buf[10]; /* a buffer */ |
| 490 | guchar match[10] = TEST_DATA; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 491 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 492 | ThriftServerSocket *tsocket = g_object_new (THRIFT_TYPE_SERVER_SOCKET, |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 493 | "port", port, NULL); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 494 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 495 | transport = THRIFT_SERVER_TRANSPORT (tsocket); |
| 496 | thrift_server_transport_listen (transport, NULL); |
| 497 | client = thrift_server_transport_accept (transport, NULL); |
| 498 | g_assert (client != NULL); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 499 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 500 | /* read 10 bytes */ |
| 501 | bytes = thrift_ssl_socket_read (client, buf, 10, NULL); |
| 502 | g_assert (bytes == 10); /* make sure we've read 10 bytes */ |
| 503 | g_assert ( memcmp(buf, match, 10) == 0 ); /* make sure what we got matches */ |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 504 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 505 | /* failed read */ |
| 506 | recv_error = 1; |
| 507 | thrift_ssl_socket_read (client, buf, 1, NULL); |
| 508 | recv_error = 0; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 509 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 510 | thrift_ssl_socket_read_end (client, NULL); |
| 511 | thrift_ssl_socket_close (client, NULL); |
| 512 | g_object_unref (tsocket); |
| 513 | g_object_unref (client); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 514 | } |
| 515 | |
| 516 | int |
| 517 | main(int argc, char *argv[]) |
| 518 | { |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 519 | int retval; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 520 | #if (!GLIB_CHECK_VERSION (2, 36, 0)) |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 521 | g_type_init(); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 522 | #endif |
| 523 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 524 | g_test_init (&argc, &argv, NULL); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 525 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 526 | thrift_ssl_socket_initialize_openssl(); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 527 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 528 | g_test_add_func ("/testtransportsslsocket/CreateAndDestroy", test_ssl_create_and_destroy); |
| 529 | g_test_add_func ("/testtransportsslsocket/CreateAndSetProperties", test_ssl_create_and_set_properties); |
Gonzalo Aguilar Delgado | 87ad2bc | 2017-09-15 12:26:02 +0200 | [diff] [blame^] | 530 | g_test_add_func ("/testtransportsslsocket/OpenAndCloseNonSSLServer", test_ssl_open_and_close_non_ssl_server); |
| 531 | g_test_add_func ("/testtransportsslsocket/OpenAndWriteInvalidSocket", test_ssl_write_invalid_socket); |
| 532 | |
| 533 | |
| 534 | |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 535 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 536 | retval = g_test_run (); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 537 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 538 | thrift_ssl_socket_finalize_openssl(); |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 539 | |
James E. King, III | 43f4bf2 | 2017-10-28 12:54:02 -0400 | [diff] [blame] | 540 | return retval; |
James E. King, III | 36628a2 | 2017-02-13 15:25:41 -0500 | [diff] [blame] | 541 | } |
| 542 | |