From 5220cd10af10a645f7e17a230bb6dbfd796b573d Mon Sep 17 00:00:00 2001 From: nils-ohlmeier Date: Sun, 16 Jul 2006 03:20:40 +0000 Subject: [PATCH] fixed if -r was porvided before -p with IP address; thanks to Hendrik Scholz git-svn-id: http://svn.berlios.de/svnroot/repos/sipsak/trunk@409 75b5f7c7-cfd4-0310-b54c-e118b2c5249a (cherry picked from commit ff39298c8d00df5c6d6c40c18aa71338c08daf43) --- configure | 3 + header_f.c | 2 +- shoot.c | 1 + sipsak.c | 9 ++- sipsak.h | 11 ++++ transport.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 189 insertions(+), 7 deletions(-) diff --git a/configure b/configure index b481bfd..d0f5825 100755 --- a/configure +++ b/configure @@ -8282,6 +8282,9 @@ done fi +# FIXME: this has to replaced with a real check +LIBS="$LIBS -lssl" + # Check for T1 timer value def_timeout=500 diff --git a/header_f.c b/header_f.c index 0234919..622478f 100644 --- a/header_f.c +++ b/header_f.c @@ -71,7 +71,7 @@ void add_via(char *mes) strlen(fqdn)+15+30+1); snprintf(via_line, VIA_SIP_STR_LEN+TRANSPORT_STR_LEN+1+strlen(fqdn)+15+30, - "%s%s %s:%i;branch=z9hG4bK.%08x;rport;alias\r\n", + "%s%s %s:%i;branch=z9hG4bK.%08x\r\n", VIA_SIP_STR, transport_str, fqdn, lport, rand()); if (verbose > 2) printf("our Via-Line: %s\n", via_line); diff --git a/shoot.c b/shoot.c index 563306d..92c6f38 100644 --- a/shoot.c +++ b/shoot.c @@ -1035,6 +1035,7 @@ void shoot(char *buf, int buff_size) } /* redirect, auth, and modes */ } /* ret > 0 */ else if (ret == -1) { // we did not got anything back, send again + /* no re-transmission on reliable transports */ if (transport != SIP_UDP_TRANSPORT) { cdata.dontsend = 1; } diff --git a/sipsak.c b/sipsak.c index 6707245..b85c6d1 100644 --- a/sipsak.c +++ b/sipsak.c @@ -283,7 +283,7 @@ int main(int argc, char *argv[]) {0, 0, 0, 0} }; #endif - /* some initialisation to be shure */ + /* some initialisation to be safe */ file_b=uri_b=trace=lport=usrloc=flood=verbose=randtrash=trashchar = 0; warning_ext=rand_rem=nonce_count=replace_b=invite=message = 0; sleep_ms=empty_contact=nagios_warn=timing=outbound_proxy=symmetric = 0; @@ -511,7 +511,7 @@ int main(int argc, char *argv[]) strncpy(con_dis, optarg, strlen(optarg)); break; case 'p': - parse_uri(optarg, &scheme, &user, &host, &rport); + parse_uri(optarg, &scheme, &user, &host, &port); if (host == NULL) { fprintf(stderr, "error: missing in host in outbound proxy\n"); exit_code(2); @@ -522,7 +522,7 @@ int main(int argc, char *argv[]) transport = SIP_UDP_TRANSPORT; } else { - if (!rport) { + if (!port) { address = getsrvadr(host, &rport, &tsp); if (tsp != 0) transport = tsp; @@ -538,6 +538,9 @@ int main(int argc, char *argv[]) exit_code(2); } } + if (port && !rport) { + rport = port; + } outbound_proxy=1; break; case 'P': diff --git a/sipsak.h b/sipsak.h index e685715..a369cde 100644 --- a/sipsak.h +++ b/sipsak.h @@ -49,6 +49,8 @@ # include #endif +#include + #ifdef HAVE_LIMITS_H # include #endif @@ -294,6 +296,15 @@ #endif #define SIPSAK_HASHHEXLEN 2 * SIPSAK_HASHLEN +// FIXME: this has to replaced with a real evaluation +#define WITH_TLS_TRANSP 1 + +#ifdef WITH_TLS_TRANSP +SSL_CTX* ctx; +SSL* ssl; +char *cert_file, *ca_file; +#endif + /* lots of global variables. ugly but makes life easier. */ unsigned long address; unsigned int nonce_count, transport; diff --git a/transport.c b/transport.c index 359ad3b..592f164 100644 --- a/transport.c +++ b/transport.c @@ -62,6 +62,27 @@ # endif #endif /* RAW_SUPPORT */ +#ifdef WITH_TLS_TRANSP +#define _BSD_SOURCE 1 +#include +#include +#include +#include +#include +#include +#include +#include +# include +# include +# include +# include +# include +# include +# include +# include +# include +#endif /* WITH_TLS_TRANSP */ + #include "exit_code.h" #include "helper.h" #include "header_f.h" @@ -70,6 +91,49 @@ int rawsock; #endif +#ifdef WITH_TLS_TRANSP +void set_tls_options() { +#if OPENSSL_VERSION_NUMBER >= 0x0009070000 /* 0.9.7 */ + SSL_CTX_set_options(ctx, SSL_OP_ALL | + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION | + SSL_OP_CIPHER_SERVER_PREFERENCE); +#else + SSL_CTX_set_options(ctx, SSL_OP_ALL); +#endif +} + +void create_tls_ctx() { + SSL_METHOD *method = NULL; + + method = TLSv1_method(); + ctx = SSL_CTX_new(method); + if (ctx == NULL) { + ERR_print_errors_fp(stderr); + perror("create_tls_ctx: failed to create TLS ctx"); + exit_code(2); + } + /*if (!SSL_CTX_use_certificate_chain_file(ctx, cert_file)) { + perror("create_tls_ctx: failed to load certificate file"); + exit_code(2); + } + if (SSL_CTX_load_verify_locations(ctx, ca_file, 0) != 1) { + perror("create_tls_ctx: failed to load CA cert"); + exit_code(2); + } + SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(ca_file)); + if (SSL_CTX_get_client_CA_list(ctx) == 0) { + perror("create_tls_ctx: failed to set client CA list"); + exit_code(2); + }*/ + SSL_CTX_set_cipher_list(ctx, 0); + SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, 0); + SSL_CTX_set_verify_depth(ctx, 5); + set_tls_options(); + SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); + SSL_CTX_set_session_id_context(ctx, 0, 0); +} +#endif /* WITH_TLS_TRANSP */ + void create_sockets(struct sipsak_con_data *cd) { socklen_t slen; @@ -139,6 +203,20 @@ void create_sockets(struct sipsak_con_data *cd) { perror("TCP socket binding failed"); exit_code(2); } +#ifdef WITH_TLS_TRANSP + if (transport == SIP_TLS_TRANSPORT) { + create_tls_ctx(); + ssl = SSL_new(ctx); + if (ssl == NULL) { + perror("TLS failed to create SSL object"); + exit_code(2); + } + if (SSL_set_fd(ssl, cd->csock) != 1) { + perror("TLS failed to add socket to SSL object"); + exit_code(2); + } + } +#endif /* WITH_TLS_TRANSP */ } /* for the via line we need our listening port number */ @@ -559,9 +637,28 @@ int recv_message(char *buf, int size, int inv_trans, return ret; } +#ifdef WITH_TLS_TRANSP +void tls_dump_cert_info(char* s, X509* cert) { + char *subj, *issuer; + + subj = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); + issuer = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); + + printf("%s subject: '%s'\n", s ? s: "", subj); + printf("%s issuer: '%s'\n", s ? s : "", issuer); + OPENSSL_free(subj); + OPENSSL_free(issuer); +} +#endif /*WITH_TLS_TRANSP*/ + /* clears the given sockaddr, fills it with the given data and if a * socket is given connects the socket to the new target */ int set_target(struct sockaddr_in *adr, unsigned long target, int port, int socket, int connected) { +#ifdef WITH_TLS_TRANSP + int ret, err; + X509* cert; +#endif /* WITH_TLS_TRANSP */ + if (socket != -1 && transport != SIP_UDP_TRANSPORT && connected) { if (shutdown(socket, SHUT_RDWR) != 0) { perror("error while shutting down socket"); @@ -578,10 +675,77 @@ int set_target(struct sockaddr_in *adr, unsigned long target, int port, int sock #endif if (socket != -1) { - if (connect(socket, (struct sockaddr *)adr, sizeof(struct sockaddr_in)) == -1) { - perror("connecting socket failed"); - exit_code(2); +#ifdef WITH_TLS_TRANSP + if (transport == SIP_TLS_TRANSPORT) { + ret = SSL_connect(ssl); + if (ret == 1) { + printf("TLS connect successful\n"); + printf("TLS connect: new connection using %s %s %d\n", + SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl), + SSL_get_cipher_bits(ssl, 0)); + cert = SSL_get_peer_certificate(ssl); + if (cert != 0) { + tls_dump_cert_info("TLS connect: server certificate", cert); + if (SSL_get_verify_result(ssl) != X509_V_OK) { + perror("TLS connect: server certifcate verification failed!!!\n"); + exit_code(3); + } + X509_free(cert); + } + else { + perror("TLS connect: server did not present a certificate\n"); + exit_code(3); + } + } + else { + err = SSL_get_error(ssl, ret); + switch (err) { + case SSL_ERROR_ZERO_RETURN: + perror("TLS handshakre failed cleanly'n"); + break; + case SSL_ERROR_WANT_READ: + perror("Need to get more data to finish TLS connect\n"); + break; + case SSL_ERROR_WANT_WRITE: + perror("Need to send more data to finish TLS connect\n"); + break; +#if OPENSSL_VERSION_NUMBER >= 0x00907000L /* 0.9.7 */ + case SSL_ERROR_WANT_CONNECT: + perror("Need to retry connect\n"); + break; + case SSL_ERROR_WANT_ACCEPT: + perror("Need to retry accept'n"); + break; +#endif /* 0.9.7 */ + case SSL_ERROR_WANT_X509_LOOKUP: + perror("Application callback asked to be called again\n"); + break; + case SSL_ERROR_SYSCALL: + printf("TLS connect: %d\n", err); + if (!err) { + if (ret == 0) { + perror("Unexpected EOF occured while performing TLS connect\n"); + } + else { + printf("IO error: (%d) %s\n", errno, strerror(errno)); + } + } + break; + default: + printf("TLS error: %d\n", err); + } + exit_code(2); + } } + else { +#endif /* WITH_TLS_TRANSP */ + if (connect(socket, (struct sockaddr *)adr, sizeof(struct sockaddr_in)) == -1) { + perror("connecting socket failed"); + exit_code(2); + } +#ifdef WITH_TLS_TRANSP + } +#endif } return 1; }