diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/astmanproxy.c | 15 | ||||
-rw-r--r-- | src/common.c | 54 | ||||
-rw-r--r-- | src/config.c | 16 | ||||
-rw-r--r-- | src/include/astmanproxy.h | 1 | ||||
-rw-r--r-- | src/ssl.c | 81 |
5 files changed, 95 insertions, 72 deletions
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); @@ -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; +} + |