diff -Naur ami_ssl.orig/cli.c ami_ssl/cli.c --- ami_ssl.orig/cli.c 2006-05-16 13:28:47.000000000 -0700 +++ ami_ssl/cli.c 2006-05-16 13:27:43.000000000 -0700 @@ -65,7 +65,7 @@ if (res == -1) { ast_log(LOG_ERROR, "Memory allocation failure\n"); } else { - ast_carefulwrite(fd, stuff, strlen(stuff), 100); + ast_carefulwrite(fd, stuff, strlen(stuff), 100, NULL); free(stuff); } } diff -Naur ami_ssl.orig/include/asterisk/manager.h ami_ssl/include/asterisk/manager.h --- ami_ssl.orig/include/asterisk/manager.h 2006-05-16 13:29:02.000000000 -0700 +++ ami_ssl/include/asterisk/manager.h 2006-05-16 13:34:11.000000000 -0700 @@ -27,6 +27,10 @@ #include "asterisk/lock.h" +#if AMI_WITH_SSL +#include "asterisk/ssl_addon.h" +#endif + /*! \file \brief The AMI - Asterisk Manager Interface - is a TCP protocol created to @@ -59,7 +63,56 @@ #define AST_MAX_MANHEADERS 80 #define AST_MAX_MANHEADER_LEN 256 -struct mansession; +struct mansession { + /*! Execution thread */ + pthread_t t; + /*! Thread lock -- don't use in action callbacks, it's already taken care of */ + ast_mutex_t __lock; + /*! socket address */ + struct sockaddr_in sin; + /*! TCP socket */ + int fd; +#if AMI_WITH_SSL + /*! Whether or not we use SSL (ssl context *, or NULL) */ + SSL *ssl; +#endif + /*! Whether or not we're busy doing an action */ + int busy; + /*! Whether or not we're "dead" */ + int dead; + /*! Whether an HTTP manager is in use */ + int inuse; + /*! Whether an HTTP session should be destroyed */ + int needdestroy; + /*! Whether an HTTP session has someone waiting on events */ + pthread_t waiting_thread; + /*! Unique manager identifer */ + unsigned long managerid; + /*! Session timeout if HTTP */ + time_t sessiontimeout; + /*! Output from manager interface */ + char *outputstr; + /*! Logged in username */ + char username[80]; + /*! Authentication challenge */ + char challenge[10]; + /*! Authentication status */ + int authenticated; + /*! Authorization for reading */ + int readperm; + /*! Authorization for writing */ + int writeperm; + /*! Buffer */ + char inbuf[AST_MAX_MANHEADER_LEN]; + int inlen; + int send_events; + int displaysystemname; /*!< Add system name to manager responses and events */ + /* Queued events that we've not had the ability to send yet */ + struct eventqent *eventq; + /* Timeout for ast_carefulwrite() */ + int writetimeout; + struct mansession *next; +}; struct message { int hdrcount; diff -Naur ami_ssl.orig/include/asterisk/ssl_addon.h ami_ssl/include/asterisk/ssl_addon.h --- ami_ssl.orig/include/asterisk/ssl_addon.h 2006-05-16 13:29:02.000000000 -0700 +++ ami_ssl/include/asterisk/ssl_addon.h 2006-05-16 13:34:11.000000000 -0700 @@ -59,7 +59,7 @@ Accepts the connection, if the security is enabled it returns the negative fd. -1 is flase, -2, -3 etc are ssl connections. */ -int saccept(int s); +int saccept(void *s); /*! \brief Sends the data over secured or unsecured connections. @@ -70,7 +70,7 @@ /*! \brief Receives the connection from either ssl or fd. */ -int m_recv(int s, void *buf, size_t len, int flags); +int m_recv(void *s, void *buf, size_t len, int flags); /*! \brief @@ -78,7 +78,7 @@ It also closes the ssl meta connection. */ -int close_sock(int socket); +int close_sock(void *s); int errexit(char s[]); diff -Naur ami_ssl.orig/include/asterisk/utils.h ami_ssl/include/asterisk/utils.h --- ami_ssl.orig/include/asterisk/utils.h 2006-05-16 13:29:03.000000000 -0700 +++ ami_ssl/include/asterisk/utils.h 2006-05-16 13:34:11.000000000 -0700 @@ -233,8 +233,10 @@ 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 have a need to wait. This way, we get better performance. + The file descriptor is taken from the struct mansession pointer, if it is + non NULL, otherwise the parameter fd is used. */ -int ast_carefulwrite(int fd, char *s, int len, int timeoutms); +int ast_carefulwrite(int fd, char *s, int len, int timeoutms, void *vs); /*! Compares the source address and port of two sockaddr_in */ static force_inline int inaddrcmp(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2) diff -Naur ami_ssl.orig/manager.c ami_ssl/manager.c --- ami_ssl.orig/manager.c 2006-05-16 13:28:47.000000000 -0700 +++ ami_ssl/manager.c 2006-05-16 13:27:43.000000000 -0700 @@ -53,6 +53,9 @@ #include "asterisk/channel.h" #include "asterisk/file.h" +#ifdef AMI_WITH_SSL +#include "asterisk/ssl_addon.h" +#endif #include "asterisk/manager.h" #include "asterisk/config.h" #include "asterisk/callerid.h" @@ -65,9 +68,6 @@ #include "asterisk/md5.h" #include "asterisk/acl.h" #include "asterisk/utils.h" -#ifdef AMI_WITH_SSL -#include "asterisk/ssl_addon.h" -#endif #include "asterisk/http.h" struct fast_originate_helper { @@ -128,52 +128,7 @@ { 0, "none" }, }; -static struct mansession { - /*! Execution thread */ - pthread_t t; - /*! Thread lock -- don't use in action callbacks, it's already taken care of */ - ast_mutex_t __lock; - /*! socket address */ - struct sockaddr_in sin; - /*! TCP socket */ - int fd; - /*! Whether or not we're busy doing an action */ - int busy; - /*! Whether or not we're "dead" */ - int dead; - /*! Whether an HTTP manager is in use */ - int inuse; - /*! Whether an HTTP session should be destroyed */ - int needdestroy; - /*! Whether an HTTP session has someone waiting on events */ - pthread_t waiting_thread; - /*! Unique manager identifer */ - unsigned long managerid; - /*! Session timeout if HTTP */ - time_t sessiontimeout; - /*! Output from manager interface */ - char *outputstr; - /*! Logged in username */ - char username[80]; - /*! Authentication challenge */ - char challenge[10]; - /*! Authentication status */ - int authenticated; - /*! Authorization for reading */ - int readperm; - /*! Authorization for writing */ - int writeperm; - /*! Buffer */ - char inbuf[AST_MAX_MANHEADER_LEN]; - int inlen; - int send_events; - int displaysystemname; /*!< Add system name to manager responses and events */ - /* Queued events that we've not had the ability to send yet */ - struct eventqent *eventq; - /* Timeout for ast_carefulwrite() */ - int writetimeout; - struct mansession *next; -} *sessions = NULL; +static struct mansession *sessions = NULL; static struct manager_action *first_action = NULL; AST_MUTEX_DEFINE_STATIC(actionlock); @@ -392,7 +347,7 @@ return; } if (s->fd > -1) - ast_carefulwrite(s->fd, stuff, strlen(stuff), s->writetimeout); + ast_carefulwrite(0, stuff, strlen(stuff), s->writetimeout, s); else { tmp = realloc(s->outputstr, (s->outputstr ? strlen(s->outputstr) : 0) + strlen(stuff) + 1); if (tmp) { @@ -535,7 +490,7 @@ { struct eventqent *eqe; #ifdef AMI_WITH_SSL - close_sock(s->fd); + close_sock(s); #else if (s->fd > -1) close(s->fd); @@ -1633,7 +1588,7 @@ eqe = s->eventq->next; if ((s->authenticated && (s->readperm & eqe->category) == eqe->category) && ((s->send_events & eqe->category) == eqe->category)) { - if (!ret && ast_carefulwrite(s->fd, eqe->eventdata, strlen(eqe->eventdata), s->writetimeout) < 0) + if (!ret && ast_carefulwrite(0, eqe->eventdata, strlen(eqe->eventdata), s->writetimeout, s) < 0) ret = -1; } unuse_eventqent(s->eventq); @@ -1749,9 +1704,6 @@ s->inlen = 0; } fds[0].fd = s->fd; -#ifdef AMI_WITH_SSL - fds[0].fd = get_real_fd(s->fd); -#endif fds[0].events = POLLIN; do { @@ -1775,7 +1727,14 @@ } else if (res > 0) { ast_mutex_lock(&s->__lock); #ifdef AMI_WITH_SSL - res = m_recv(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen, 0); + if (s->ssl) { + res = SSL_read (s->ssl, s->inbuf + s->inlen, + sizeof(s->inbuf) - 1 - s->inlen); + } + else { + res = read(s->fd, s->inbuf + s->inlen, + sizeof(s->inbuf) - 1 - s->inlen); + } #else res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen); #endif @@ -1907,53 +1866,55 @@ ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\n", strerror(errno)); } } + + s = malloc(sizeof(struct mansession)); + if (!s) { + ast_log(LOG_WARNING, "Failed to allocate management session: %s\n", strerror(errno)); + continue; + } + + memset(s, 0, sizeof(struct mansession)); + memcpy(&s->sin, &sin, sizeof(sin)); + s->writetimeout = 100; + s->waiting_thread = AST_PTHREADT_NULL; + + s->fd = as; + #ifdef AMI_WITH_SSL is_encrypted = is_encrypt_request(sslclhellotimeout, as); if (is_encrypted > 0) { if (!acceptencryptedconnection) { ast_log(LOG_WARNING, "Accepting encrypted connection disabled, closing the connection \n"); - close_sock(as); + close_sock(s); + free(s); continue; } else { - if((as = saccept(as)) >= 0 ) { + if(saccept(s) == -1 ) { ast_log(LOG_WARNING, "Can't accept the ssl connection, since SSL init has failed for certificate reason\n"); - close_sock(as); + close_sock(s); + free(s); continue; } } } else if (is_encrypted == -1) { ast_log(LOG_ERROR, "SSL version 2 is unsecure, we don't support it\n"); - close_sock(as); + close_sock(s); + free(s); continue; } if ( (! acceptunencryptedconnection) && (as >= 0)) { ast_log(LOG_NOTICE, "Unencrypted connections are not accepted and we received an unencrypted connection request\n"); - close_sock(as); + close_sock(s); + free(s); continue; } #endif - s = malloc(sizeof(struct mansession)); - if (!s) { - ast_log(LOG_WARNING, "Failed to allocate management session: %s\n", strerror(errno)); - continue; - } - memset(s, 0, sizeof(struct mansession)); - memcpy(&s->sin, &sin, sizeof(sin)); - s->writetimeout = 100; - s->waiting_thread = AST_PTHREADT_NULL; - if (!block_sockets) { /* For safety, make sure socket is non-blocking */ -#ifdef AMI_WITH_SSL - flags = fcntl(get_real_fd(as), F_GETFL); - fcntl(get_real_fd(as), F_SETFL, flags | O_NONBLOCK); -#else flags = fcntl(as, F_GETFL); fcntl(as, F_SETFL, flags | O_NONBLOCK); -#endif } ast_mutex_init(&s->__lock); - s->fd = as; s->send_events = -1; ast_mutex_lock(&sessionlock); num_sessions++; diff -Naur ami_ssl.orig/ssl_addon.c ami_ssl/ssl_addon.c --- ami_ssl.orig/ssl_addon.c 2006-05-16 13:28:47.000000000 -0700 +++ ami_ssl/ssl_addon.c 2006-05-16 13:27:43.000000000 -0700 @@ -61,10 +61,9 @@ #include "asterisk/options.h" #include "asterisk/config.h" #include "asterisk/ssl_addon.h" +#include "asterisk/manager.h" SSL_CTX *sctx; -static long rec_bytes; -static long sent_bytes; static int ssl_initialized; @@ -100,153 +99,42 @@ 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. +/*! \brief Accepts the ssl connection. */ -int get_real_fd(int fd) -{ - if (fd<-1) { - fd = -fd - 2; - if (fd>=0 && fd =0 && fd 0) - rec_bytes += ret; - - if (option_debug > 2) - ast_log(LOG_DEBUG, "Received data from SSL socket - %d\n", ret); - return ret; + s->ssl=SSL_new(sctx); + SSL_set_fd(s->ssl, s->fd); + do { + err = SSL_accept(s->ssl); + err = SSL_get_error(s->ssl, err); + } while( err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE); + + SSL_set_mode(s->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE); + ast_log(LOG_DEBUG, "ssl_addon: Connection accepted"); + + if (!s->ssl) + fd = -1; /* it did not work */ + + return 0; } - -/*! \brief - Needs to be called instead of close() to close a socket. - It also closes the SSL meta connection. -*/ - -int close_sock(int socket) +int close_sock(void *vs) { - int ret=0; - SSL* ssl = NULL; - - if (socket < -1) { - socket = - socket - 2; - - ssl = sec_channel[socket].ssl; - sec_channel[socket].ssl = NULL; - socket = sec_channel[socket].fd; - } + int ret; + struct mansession *s = (struct mansession *) vs; - ret= close(socket); + ret = close(s->fd); - if (ssl) - SSL_free (ssl); + if(s->ssl) + SSL_free (s->ssl); return(ret); } diff -Naur ami_ssl.orig/utils.c ami_ssl/utils.c --- ami_ssl.orig/utils.c 2006-05-16 13:28:47.000000000 -0700 +++ ami_ssl/utils.c 2006-05-16 13:27:43.000000000 -0700 @@ -48,6 +48,11 @@ #include "asterisk/options.h" #include "asterisk/compat.h" +#ifdef AMI_WITH_SSL +#include "asterisk/ssl_addon.h" +#include "asterisk/manager.h" +#endif + #define AST_API_MODULE /* ensure that inlinable API functions will be built in this module if required */ #include "asterisk/strings.h" @@ -591,14 +596,27 @@ return poll(pfd, 1, ms); } -int ast_carefulwrite(int fd, char *s, int len, int timeoutms) +int ast_carefulwrite(int fd, char *s, int len, int timeoutms, void *vs) { /* Try to write string, but wait no more than ms milliseconds before timing out */ int res = 0; struct pollfd fds[1]; +#if AMI_WITH_SSL + struct mansession *ms = (struct mansession *)vs; + + if(ms) fd = ms->fd; +#endif + while (len) { +#if AMI_WITH_SSL + if (ms->ssl) + res = SSL_write(ms->ssl, s, len); + else + res = write(ms->fd, s, len); +#else res = write(fd, s, len); +#endif if ((res < 0) && (errno != EAGAIN)) { return -1; }