summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--src/astmanproxy.c15
-rw-r--r--src/common.c54
-rw-r--r--src/config.c16
-rw-r--r--src/include/astmanproxy.h1
-rw-r--r--src/ssl.c81
6 files changed, 96 insertions, 73 deletions
diff --git a/Makefile b/Makefile
index 4f7e50c..b9b4f92 100644
--- a/Makefile
+++ b/Makefile
@@ -53,7 +53,7 @@ OBJS += $(MODS:%=%.o)
MODDIR := $(LIBDIR)/modules
CONF_TARGET:= $(CONFDIR_REAL)/$(CONFFILE)
PERM_TARGET:= $(PERMDIR_REAL)/$(PERMFILE)
-DEFINES:=-DAMI_WITH_SSL '-DPROXY_VERSION="$(VERSION)"' '-DCDIR="$(CONFDIR)"' '-DCFILE="$(CONFFILE)"'
+DEFINES:='-DPROXY_VERSION="$(VERSION)"' '-DCDIR="$(CONFDIR)"' '-DCFILE="$(CONFFILE)"'
DEFINES+='-DMDIR="$(MODDIR)"' '-DPDIR="$(PERMDIR)"' '-DPFILE="$(PERMFILE)"'
VPATH = src
diff --git a/src/astmanproxy.c b/src/astmanproxy.c
index 25aab23..ac30b1b 100644
--- a/src/astmanproxy.c
+++ b/src/astmanproxy.c
@@ -374,8 +374,8 @@ int ConnectAsterisk(struct mansession *s) {
s->connected = 0;
if (debug)
- debugmsg("asterisk@%s: Connecting (u=%s, p=%s)", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr),
- s->server->ast_user, s->server->ast_pass);
+ debugmsg("asterisk@%s: Connecting (u=%s, p=%s, ssl=%s)", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr),
+ s->server->ast_user, s->server->ast_pass, s->server->use_ssl ? "on" : "off");
/* Construct auth message just once */
memset( &m, 0, sizeof(struct message) );
@@ -385,12 +385,7 @@ int ConnectAsterisk(struct mansession *s) {
AddHeader(&m, "Events: %s", s->server->ast_events);
for ( ;; ) {
- if ( connect_nonb(s->fd, (struct sockaddr *) &s->sin, sizeof(s->sin), 2) < 0 ) {
- if (errno == EISCONN) {
- pthread_mutex_lock(&s->lock);
- s->fd = socket(AF_INET, SOCK_STREAM, 0);
- pthread_mutex_unlock(&s->lock);
- }
+ if ( ast_connect(s) == -1 ) {
if (debug)
debugmsg("asterisk@%s: Connect failed, Retrying (%d) %s",
ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), r, strerror(errno) );
@@ -457,7 +452,6 @@ int StartServer(struct ast_server *srv) {
debugmsg("Set %s output format to %s", ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr), s->output->formatname);
}
-
if (pthread_create(&s->t, &attr, (void *)HandleAsterisk, s))
destroy_session(s);
else
@@ -673,6 +667,9 @@ int main(int argc, char *argv[])
sessions = NULL;
LaunchAsteriskThreads();
+ /* Initialize SSL Client-Side Context */
+ client_init_secure();
+
/* Setup listener socket to setup new sessions... */
if ((asock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr,"Cannot create listener socket!\n");
diff --git a/src/common.c b/src/common.c
index f4b370e..d6bea7a 100644
--- a/src/common.c
+++ b/src/common.c
@@ -102,60 +102,6 @@ const char *ast_inet_ntoa(char *buf, int bufsiz, struct in_addr ia)
}
-int connect_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen, int nsec)
-{
- int flags, n, error;
- socklen_t len;
- fd_set rset, wset;
- struct timeval tval;
-
- flags = fcntl(sockfd, F_GETFL, 0);
- fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
-
- error = 0;
- if ( (n = connect(sockfd, (struct sockaddr *) saptr, salen)) < 0)
- if (errno != EINPROGRESS)
- return(-1);
-
- /* Do whatever we want while the connect is taking place. */
-
- if (n == 0)
- goto done; /* connect completed immediately */
-
- FD_ZERO(&rset);
- FD_SET(sockfd, &rset);
- wset = rset;
- tval.tv_sec = nsec;
- tval.tv_usec = 0;
-
- if ( (n = select(sockfd+1, &rset, &wset, NULL,
- nsec ? &tval : NULL)) == 0) {
- /*close(sockfd);*/ /* we want to retry */
- errno = ETIMEDOUT;
- return(-1);
- }
-
- if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
- len = sizeof(error);
- if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
- return(-1); /* Solaris pending error */
- } else {
- /*err_quit("select error: sockfd not set");*/
- logmsg("select error: sockfd not set");
- return(-1);
- }
-
-done:
- fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
-
- if (error) {
- /* close(sockfd); */ /* we want to retry... */
- errno = error;
- return(-1);
- }
- return(0);
-}
-
/*! If you are calling ast_carefulwrite, it is assumed that you are calling
it on a file descriptor that _DOES_ have NONBLOCK set. This way,
there is only one system call made to do a write, unless we actually
diff --git a/src/config.c b/src/config.c
index 02d76ec..bc1d2cb 100644
--- a/src/config.c
+++ b/src/config.c
@@ -9,6 +9,7 @@ void *add_server(char *srvspec) {
int ccount = 0;
struct ast_server *srv;
char *s;
+ char usessl[10];
/* malloc ourselves a server credentials structure */
srv = malloc(sizeof(struct ast_server));
@@ -17,6 +18,7 @@ void *add_server(char *srvspec) {
exit(1);
}
memset(srv, 0, sizeof (struct ast_server) );
+ memset(usessl, 0, sizeof (usessl) );
s = srvspec;
do {
@@ -42,20 +44,22 @@ void *add_server(char *srvspec) {
strncat(srv->ast_events, s, 1);
break;
case 5:
- srv->use_ssl = strcmp(s,"yes") ? 0 : 1;
+ strncat(usessl, s, 1);
break;
}
} while (*(s++));
- if (!srv->ast_host || !srv->ast_port || !srv->ast_user || !srv->ast_pass || !srv->ast_events || !srv->use_ssl) {
- fprintf(stderr, "Aborting! Server spec incomplete: %s!\n", srvspec);
+
+ if (!*srv->ast_host || !*srv->ast_port || !*srv->ast_user || !*srv->ast_pass || !*srv->ast_events || !*usessl) {
+ fprintf(stderr, "Aborting: server spec incomplete: %s\n", srvspec);
free(srv);
exit(1);
- } else {
- srv->next = pc.serverlist;
- pc.serverlist = srv;
}
+ srv->use_ssl = (!strcmp(usessl,"on"));
+ srv->next = pc.serverlist;
+ pc.serverlist = srv;
+
return 0;
/* TODO: make sure server credentials are freed at leave */
}
diff --git a/src/include/astmanproxy.h b/src/include/astmanproxy.h
index 1d7ec47..fa57126 100644
--- a/src/include/astmanproxy.h
+++ b/src/include/astmanproxy.h
@@ -134,6 +134,5 @@ int proxyerror_do(struct mansession *s, char *err);
int get_input(struct mansession *s, char *output);
int SetIOHandlers(struct mansession *s, char *ifmt, char *ofmt);
void destroy_session(struct mansession *s);
-int connect_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen, int nsec);
int ast_carefulwrite(int fd, char *s, int len, int timeoutms);
extern void *SendError(struct mansession *s, char *errmsg);
diff --git a/src/ssl.c b/src/ssl.c
index 265c961..ce38814 100644
--- a/src/ssl.c
+++ b/src/ssl.c
@@ -39,7 +39,6 @@
You must check for (value==-1) instead, since all other negative fd's now
are valid fd's.
*/
-#ifdef AMI_WITH_SSL
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
@@ -58,6 +57,7 @@
#include "ssl.h"
SSL_CTX *sctx;
+SSL_CTX *cctx;
static long rec_bytes;
static long sent_bytes;
static int ssl_initialized;
@@ -95,6 +95,25 @@ int init_secure(char *certfile)
return 0;
}
+
+/* Initializes all the client-side ssl related stuff here.
+*/
+int client_init_secure(void)
+{
+ SSL_METHOD *meth;
+
+ /* client init */
+ SSLeay_add_ssl_algorithms();
+ meth = SSLv23_client_method();
+ SSL_load_error_strings();
+ cctx = SSL_CTX_new (meth);
+
+ if (!cctx) {
+ fprintf(stderr, "Failed to create a client ssl context!\n");
+ }
+ return 0;
+}
+
/*! \brief Takes the negative ssl fd and returns the positive fd recieved from the os.
* It goes through arrray of fixed maximum number of secured channels.
*/
@@ -307,4 +326,62 @@ int is_encrypt_request(int sslclhellotimeout, int fd)
}
return 0;
}
-#endif
+
+
+/* Connects to an asterisk server either plain or SSL as appropriate
+*/
+int ast_connect(struct mansession *a) {
+ int s, err=-1, fd;
+ SSL* ssl;
+
+ fd = connect_nonb(a);
+ if ( fd < 0 )
+ return -1;
+
+ if (a->server->use_ssl) {
+ if ((s=sec_getslot())!=-1) { /* find a slot for the ssl handle */
+ sec_channel[s].fd = fd; /* remember the real fd */
+
+ if((ssl=SSL_new(cctx))) { /* get a new ssl */
+ sec_channel[s].ssl = ssl;
+ SSL_set_fd(ssl, fd); /* and attach the real fd */
+ err = SSL_connect(ssl); /* now try and connect */
+ }
+ fd = -(s+2); /* offset by two and negate */
+ /* this tells us it is a ssl fd */
+ }
+
+ if (err==-1) {
+ close_sock(fd); /* that frees the ssl too */
+ fd = -1;
+ }
+ }
+
+ pthread_mutex_lock(&a->lock);
+ a->fd = fd;
+ pthread_mutex_unlock(&a->lock);
+
+ return fd;
+}
+
+int connect_nonb(struct mansession *a)
+{
+ int s, flags, one=1;
+
+ s = get_real_fd(a->fd);
+
+ flags = fcntl(s, F_GETFL, 0);
+ fcntl(s, F_SETFL, flags | O_NONBLOCK);
+
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one))==-1) {
+ (void)close(s);
+ return -1;
+ }
+
+ if (connect(s, (struct sockaddr *) &a->sin, sizeof(a->sin)) < 0) {
+ if (errno != EINPROGRESS)
+ return -1;
+ }
+ return s;
+}
+