c - OpenSSL and Network namespace - Closed -
i developing application using openssl library. new openssl library. application working correctly until tested within network namespace. application hangs @ ssl_connect. using sockets in blocking mode. read somewhere should use non-blocking mode instead solve issue. switched blocking sockets non-blocking sockets code still gets stuck @ ssl_connect method in client.
i have simple client-server program nothing fancy stuff. have added ssl methods inside them make them secure. works when run them inside terminal when switch network namespace , run inside virtual network, client code hangs @ ssl_connect. not able understand may causing problem. appreciated!
here code server.c file:
#include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/time.h> #include <netinet/in.h> #include <errno.h> #include <sys/select.h> #include <sys/types.h> #include <unistd.h> #include <string.h> #include <openssl/ssl.h> #include <openssl/err.h> #define server_port 12345 #define true 1 #define false 0 main (int argc, char *argv[]) { int i, len, rc, on = 1; int listen_sd, max_sd, new_sd; int desc_ready, end_server = false; int close_conn; char buffer[80]; struct sockaddr_in addr; struct timeval timeout; fd_set master_set, working_set; char ch='a'; //ssl initiation ssl_load_error_strings(); err_load_bio_strings(); err_load_ssl_strings(); ssl_library_init(); openssl_add_all_algorithms(); ssl_method *meth = sslv3_server_method(); ssl_ctx *ctx = ssl_ctx_new(meth); ssl_ctx_use_certificate_file(ctx, "truststore.pem", ssl_filetype_pem); ssl_ctx_use_privatekey_file(ctx, "privatekey.key", ssl_filetype_pem); /*************************************************************/ /* create af_inet stream socket receive incoming */ /* connections on */ /*************************************************************/ listen_sd = socket(af_inet, sock_stream, 0); if (listen_sd < 0) { perror("socket() failed"); exit(-1); } /*************************************************************/ /* allow socket descriptor reuseable */ /*************************************************************/ rc = setsockopt(listen_sd, sol_socket, so_reuseaddr, (char *)&on, sizeof(on)); if (rc < 0) { perror("setsockopt() failed"); close(listen_sd); exit(-1); } /*************************************************************/ /* set socket non-blocking. of sockets */ /* incoming connections non-blocking since */ /* inherit state listening socket. */ /*************************************************************/ rc = ioctl(listen_sd, fionbio, (char *)&on); if (rc < 0) { perror("ioctl() failed"); close(listen_sd); exit(-1); } /*************************************************************/ /* bind socket */ /*************************************************************/ memset(&addr, 0, sizeof(addr)); addr.sin_family = af_inet; addr.sin_addr.s_addr = htonl(inaddr_any); addr.sin_port = htons(server_port); rc = bind(listen_sd, (struct sockaddr *)&addr, sizeof(addr)); if (rc < 0) { perror("bind() failed"); close(listen_sd); exit(-1); } /*************************************************************/ /* set listen log */ /*************************************************************/ rc = listen(listen_sd, 32); if (rc < 0) { perror("listen() failed"); close(listen_sd); exit(-1); } /*************************************************************/ /* initialize master fd_set */ /*************************************************************/ fd_zero(&master_set); max_sd = listen_sd; fd_set(listen_sd, &master_set); /*************************************************************/ /* initialize timeval struct 3 minutes. if no */ /* activity after 3 minutes program end. */ /*************************************************************/ timeout.tv_sec = 3 * 60; timeout.tv_usec = 0; /*************************************************************/ /* loop waiting incoming connects or incoming data */ /* on of connected sockets. */ /*************************************************************/ { /**********************************************************/ /* copy master fd_set on working fd_set. */ /**********************************************************/ memcpy(&working_set, &master_set, sizeof(master_set)); /**********************************************************/ /* call select() , wait 5 minutes complete. */ /**********************************************************/ printf("waiting on select()...\n"); rc = select(max_sd + 1, &working_set, null, null, &timeout); /**********************************************************/ /* check see if select call failed. */ /**********************************************************/ if (rc < 0) { perror(" select() failed"); break; } /**********************************************************/ /* check see if 5 minute time out expired. */ /**********************************************************/ if (rc == 0) { printf(" select() timed out. end program.\n"); break; } /**********************************************************/ /* 1 or more descriptors readable. need */ /* determine ones are. */ /**********************************************************/ desc_ready = rc; (i=0; <= max_sd && desc_ready > 0; ++i) { /*******************************************************/ /* check see if descriptor ready */ /*******************************************************/ if (fd_isset(i, &working_set)) { /****************************************************/ /* descriptor found readable - 1 */ /* less has looked for. being done */ /* can stop looking @ working set */ /* once have found of descriptors */ /* ready. */ /****************************************************/ desc_ready -= 1; /****************************************************/ /* check see if listening socket */ /****************************************************/ if (i == listen_sd) { printf(" listening socket readable\n"); /*************************************************/ /* accept incoming connections */ /* queued on listening socket before */ /* loop , call select again. */ /*************************************************/ { /**********************************************/ /* accept each incoming connection. if */ /* accept fails ewouldblock, */ /* have accepted of them. other */ /* failure on accept cause end */ /* server. */ /**********************************************/ new_sd = accept(listen_sd, null, null); if (new_sd < 0) { if (errno != ewouldblock) { perror(" accept() failed"); end_server = true; } break; } /**********************************************/ /* add new incoming connection */ /* master read set */ /**********************************************/ printf(" new incoming connection - %d\n", new_sd); fd_set(new_sd, &master_set); if (new_sd > max_sd) max_sd = new_sd; /**********************************************/ /* loop , accept incoming */ /* connection */ /**********************************************/ } while (new_sd != -1); } /****************************************************/ /* not listening socket, therefore */ /* existing connection must readable */ /****************************************************/ else { printf(" descriptor %d readable\n", i); close_conn = false; ssl* ssl; ssl = ssl_new(ctx); ssl_set_fd(ssl, i); //handshake ssl_accept(ssl); printf("\nhandshake done\n"); int result = ssl_read(ssl, &ch, sizeof(ch)); if(result<0) { printf("\nreading error"); } ++ch; result = ssl_write(ssl, &ch, sizeof(ch)); if(result<0) { printf("\nwriting error"); } /*************************************************/ /* if close_conn flag turned on, need */ /* clean active connection. */ /* clean process includes removing */ /* descriptor master set , */ /* determining new maximum descriptor value */ /* based on bits still turned on in */ /* master set. */ /*************************************************/ if (close_conn) { close(i); fd_clr(i, &master_set); if (i == max_sd) { while (fd_isset(max_sd, &master_set) == false) max_sd -= 1; } } } /* end of existing connection readable */ } /* end of if (fd_isset(i, &working_set)) */ } /* end of loop through selectable descriptors */ } while (end_server == false); /*************************************************************/ /* cleanup of sockets open */ /*************************************************************/ (i=0; <= max_sd; ++i) { if (fd_isset(i, &master_set)) close(i); } }
here code client.c file:
/**************************************************************************/ /* generic client example used connection-oriented server designs */ /**************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h> #include <openssl/ssl.h> #include <openssl/err.h> #define server_port 12345 main (int argc, char *argv[]) { int len, rc; int sockfd; char send_buf[80]; char recv_buf[80]; struct sockaddr_in addr; char ch = 'a'; int result; //ssl initiation ssl_load_error_strings(); err_load_bio_strings(); err_load_ssl_strings(); ssl_library_init(); openssl_add_all_algorithms(); ssl_method *meth; meth = sslv3_client_method(); ssl_ctx *ctx; ssl* ssl; ctx = ssl_ctx_new(meth); result = ssl_ctx_load_verify_locations(ctx, "truststore1.pem", 0); printf("\nca load result = %d\n", result); printf("\nssl initialized"); /*************************************************/ /* create af_inet stream socket */ /*************************************************/ sockfd = socket(af_inet, sock_stream, 0); if (sockfd < 0) { perror("socket"); exit(-1); } /*************************************************/ /* initialize socket address structure */ /*************************************************/ memset(&addr, 0, sizeof(addr)); addr.sin_family = af_inet; addr.sin_addr.s_addr = inet_addr("10.0.0.1"); addr.sin_port = htons(server_port); /*************************************************/ /* connect server */ /*************************************************/ rc = connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)); if (rc < 0) { perror("connect"); close(sockfd); exit(-1); } printf("connect completed.\n"); //ssl-ing connection ssl = ssl_new(ctx); bio *sbio; sbio = bio_new(bio_s_socket()); bio_set_fd(sbio, sockfd, bio_close); ssl_set_bio(ssl, sbio, sbio); //ssl_ctx_set_verify_depth(ctx, 1); //ssl_set_fd(ssl, sockfd); printf("before ssl_connect: %d\n", result); result = ssl_connect(ssl); printf("ssl_connect: %d\n", result); if(ssl_get_peer_certificate(ssl)!=null) { //check cert //check_cert(ssl); //getting ca certificate //_ssl = ssl_new(ctx); ssl_ctx_set_verify(ctx, ssl_verify_peer, null); int result_long = ssl_get_verify_result(ssl); printf("\ncertificate check result: %d", result_long); if (ssl_get_verify_result(ssl) != x509_v_ok) { printf("\ncertiticate verification failed\n"); return 0; //exit(1); } else { printf("\ncertiticate verification succeeded"); } } ssl_write(ssl, &ch, 1); ssl_read(ssl, &ch, 1); printf("char server = %c\n", ch); ssl_shutdown(ssl); /*************************************************/ /* close down socket */ /*************************************************/ close(sockfd); }
Comments
Post a Comment