summaryrefslogtreecommitdiffstats
path: root/src/ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ssl.c')
-rw-r--r--src/ssl.c272
1 files changed, 128 insertions, 144 deletions
diff --git a/src/ssl.c b/src/ssl.c
index 19b9828..40115b1 100644
--- a/src/ssl.c
+++ b/src/ssl.c
@@ -14,24 +14,8 @@
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
- */
-/*! \file
- *
- * \brief SSL for The Asterisk Management Interface - AMI
- *
- * Channel Management and more
- *
- * \author Remco Treffkorn(Architect) and Mahesh Karoshi(Senior Software Developer)
- * \ref amiconf
- */
-
-/*! \addtogroup Group_AMI AMI functions
-*/
-/*! @{
- Doxygen group */
-
-/*! \note We use negative file descriptors for secure channels. The file descriptor
+ We use negative file descriptors for secure channels. The file descriptor
-1 is reseved for errors. -2 to -... are secure file descriptors. 0 to ...
are regular file descriptors.
@@ -66,7 +50,7 @@ static int ssl_initialized;
Initializes all the ssl related stuff here. */
int init_secure(char *certfile)
{
- SSL_METHOD *meth;
+ SSL_METHOD *meth;
SSLeay_add_ssl_algorithms();
SSL_load_error_strings();
@@ -95,23 +79,23 @@ int init_secure(char *certfile)
}
-/* Initializes all the client-side ssl related stuff here.
+/* Initializes all the client-side ssl related stuff here.
*/
int client_init_secure(void)
{
- SSL_METHOD *meth;
+ SSL_METHOD *meth;
- /* client init */
- SSLeay_add_ssl_algorithms();
- meth = SSLv23_client_method();
- SSL_load_error_strings();
- cctx = SSL_CTX_new (meth);
+ /* client init */
+ SSLeay_add_ssl_algorithms();
+ meth = SSLv23_client_method();
+ SSL_load_error_strings();
+ cctx = SSL_CTX_new (meth);
- if (!cctx)
- debugmsg("Failed to create a client ssl context!");
+ if (!cctx)
+ debugmsg("Failed to create a client ssl context!");
else
debugmsg("Client SSL Context Initialized");
- return 0;
+ return 0;
}
/*! \brief Takes the negative ssl fd and returns the positive fd recieved from the os.
@@ -122,16 +106,16 @@ int get_real_fd(int fd)
if (fd<-1) {
fd = -fd - 2;
if (fd>=0 && fd <SEC_MAX)
- fd = sec_channel[fd].fd;
+ fd = sec_channel[fd].fd;
else fd = -1;
}
return fd;
}
-/*! \brief Returns the SSL pointer from the fd. This structure is filled when we accept
- * the ssl connection and used
- * for reading and writing through ssl.
+/*! \brief Returns the SSL pointer from the fd. This structure is filled when we accept
+ * the ssl connection and used
+ * for reading and writing through ssl.
*/
SSL *get_ssl(int fd)
{
@@ -145,7 +129,7 @@ SSL *get_ssl(int fd)
return ssl;
}
-/*! \brief Returns the empty ssl slot. Used to save ssl information.
+/*! \brief Returns the empty ssl slot. Used to save ssl information.
*/
int sec_getslot(void)
{
@@ -153,7 +137,7 @@ int sec_getslot(void)
for (i=0; i<SEC_MAX; i++) {
if(sec_channel[i].ssl==NULL)
- break;
+ break;
}
if (i==SEC_MAX)
@@ -161,7 +145,7 @@ int sec_getslot(void)
return i;
}
-/*! \brief Accepts the ssl connection. Returns the negative fd. negative fd's are
+/*! \brief Accepts the ssl connection. Returns the negative fd. negative fd's are
* chosen to differentiate between ssl and non-ssl connections. Positive
* fd's are used for non-ssl connections and negative fd's are used for ssl
* connections. So we purposefully calculate and return negative fds.
@@ -195,9 +179,9 @@ int saccept(int s)
fd = -(fd+2);
if (err!=1 || !ssl) {
- /* it did not work */
- sec_channel[fd].ssl = NULL; /* free the slot */
- fd = -1;
+ /* it did not work */
+ sec_channel[fd].ssl = NULL; /* free the slot */
+ fd = -1;
}
}
return fd;
@@ -269,7 +253,7 @@ int close_sock(int socket)
*/
int errexit(char s[])
{
- debugmsg("SSL critical error: %s", s);
+ debugmsg("SSL critical error: %s", s);
return -1;
}
@@ -282,107 +266,107 @@ int errexit(char s[])
*/
int is_encrypt_request(int sslclhellotimeout, int fd)
{
- fd_set listeners;
- struct timeval tv;
- char buf[1024];
- int ready_fdescriptors;
- int ret;
-
- tv.tv_sec = 0;
- tv.tv_usec = sslclhellotimeout * 1000;
-
- FD_ZERO(&listeners);
- FD_SET(fd, &listeners);
-
- ready_fdescriptors = select (fd + 1, &listeners, NULL, NULL, &tv);
-
- if (ready_fdescriptors < 0 ) {
- debugmsg("is_encrypt_request: select returned error, This should not happen:");
- return 0;
- } else if (ready_fdescriptors == 0) {
- return 0;
- }
- ret = recv(fd, buf, 100, MSG_PEEK);
- if(ret > 0) {
- /* check for sslv3 or tls*/
- if ((buf[0x00] == 0x16) && (buf[0x01] == 0x03) &&
+ fd_set listeners;
+ struct timeval tv;
+ char buf[1024];
+ int ready_fdescriptors;
+ int ret;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = sslclhellotimeout * 1000;
+
+ FD_ZERO(&listeners);
+ FD_SET(fd, &listeners);
+
+ ready_fdescriptors = select (fd + 1, &listeners, NULL, NULL, &tv);
+
+ if (ready_fdescriptors < 0 ) {
+ debugmsg("is_encrypt_request: select returned error, This should not happen:");
+ return 0;
+ } else if (ready_fdescriptors == 0) {
+ return 0;
+ }
+ ret = recv(fd, buf, 100, MSG_PEEK);
+ if(ret > 0) {
+ /* check for sslv3 or tls*/
+ if ((buf[0x00] == 0x16) && (buf[0x01] == 0x03) &&
/* for tls buf[0x02] = 0x01 and ssl v3 buf[0x02] = 0x02 */
((buf[0x02] == 0x00) || (buf[0x02] == 0x01))) {
if (debug)
- debugmsg("Received a SSL request");
+ debugmsg("Received a SSL request");
return 1;
/* check for sslv23_client_method */
} else if ((buf[0x02] == 0x01) && (buf[0x03] == 0x03) && (buf[0x04] == 0x01)) {
if (debug)
- debugmsg("Received a SSL request for SSLv23_client_method()");
+ debugmsg("Received a SSL request for SSLv23_client_method()");
return 1;
}
/* check for sslv2 and return -1 */
else if ((buf[0x02] == 0x01) && (buf[0x03] == 0x00) && (buf[0x04] == 0x02)) {
if (debug)
- debugmsg("Received a SSLv2 request()");
- return -1;
+ debugmsg("Received a SSLv2 request()");
+ return -1;
}
- }
- return 0;
+ }
+ return 0;
}
/* 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) {
- debugmsg("initiating ssl connection");
- 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 */
- } else
+ int s, err=-1, fd;
+ SSL* ssl;
+
+ fd = connect_nonb(a);
+ if ( fd < 0 )
+ return -1;
+
+ if (a->server->use_ssl) {
+ debugmsg("initiating ssl connection");
+ 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 */
+ } else
debugmsg("couldn't create ssl client context");
- fd = -(s+2); /* offset by two and negate */
- /* this tells us it is a ssl fd */
- } else
+ fd = -(s+2); /* offset by two and negate */
+ /* this tells us it is a ssl fd */
+ } else
debugmsg("couldn't get SSL slot!");
- if (err==-1) {
- close_sock(fd); /* that frees the ssl too */
- fd = -1;
- }
- }
+ if (err==-1) {
+ close_sock(fd); /* that frees the ssl too */
+ fd = -1;
+ }
+ }
- debugmsg("returning ast_connect with %d", fd);
- pthread_mutex_lock(&a->lock);
- a->fd = fd;
- pthread_mutex_unlock(&a->lock);
+ debugmsg("returning ast_connect with %d", fd);
+ pthread_mutex_lock(&a->lock);
+ a->fd = fd;
+ pthread_mutex_unlock(&a->lock);
- return fd;
+ return fd;
}
int connect_nonb(struct mansession *a)
{
- int flags, n, error;
- socklen_t len;
- fd_set rset, wset;
- struct timeval tval;
+ int flags, n, error;
+ socklen_t len;
+ fd_set rset, wset;
+ struct timeval tval;
int nsec = 1, sockfd;
sockfd = get_real_fd(a->fd);
- flags = fcntl(sockfd, F_GETFL, 0);
- fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+ flags = fcntl(sockfd, F_GETFL, 0);
+ fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
- error = 0;
- if ( (n = connect(sockfd, (struct sockaddr *) &a->sin, sizeof(a->sin)) ) < 0 ) {
+ error = 0;
+ if ( (n = connect(sockfd, (struct sockaddr *) &a->sin, sizeof(a->sin)) ) < 0 ) {
/* TODO: This seems like the nine pound hammer to me... */
/* perhaps something a bit more elegant; errno seems to change too */
if (errno == EISCONN || errno == 103 || errno==111) {
@@ -394,45 +378,45 @@ int connect_nonb(struct mansession *a)
pthread_mutex_unlock(&a->lock);
return(-1);
}
- if (errno != EINPROGRESS)
- return(-1);
+ 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);
- }
+ /* 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); */ /* disable for now, we want to retry... */
- errno = error;
- return(-1);
- }
- return(sockfd);
+ fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
+
+ if (error) {
+ /* close(sockfd); */ /* disable for now, we want to retry... */
+ errno = error;
+ return(-1);
+ }
+ return(sockfd);
}