diff options
Diffstat (limited to 'src/ssl.c')
-rw-r--r-- | src/ssl.c | 272 |
1 files changed, 128 insertions, 144 deletions
@@ -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); } |