[asterisk-commits] branch oej/test-this-branch r27385 - in
/team/oej/test-this-branch: ./ config...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Tue May 16 08:14:43 MST 2006
Author: oej
Date: Tue May 16 10:14:43 2006
New Revision: 27385
URL: http://svn.digium.com/view/asterisk?rev=27385&view=rev
Log:
Issue #6812 - SSL for AMI (jtodd)
Added:
team/oej/test-this-branch/doc/ssl.conf.sample (with props)
team/oej/test-this-branch/include/asterisk/ssl_addon.h (with props)
team/oej/test-this-branch/ssl_addon.c (with props)
Modified:
team/oej/test-this-branch/Makefile
team/oej/test-this-branch/README.test-this-branch
team/oej/test-this-branch/README.test-this-branch.html
team/oej/test-this-branch/configs/manager.conf.sample
team/oej/test-this-branch/manager.c
Modified: team/oej/test-this-branch/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/Makefile?rev=27385&r1=27384&r2=27385&view=diff
==============================================================================
--- team/oej/test-this-branch/Makefile (original)
+++ team/oej/test-this-branch/Makefile Tue May 16 10:14:43 2006
@@ -136,6 +136,11 @@
ASTCFLAGS=
+# Compile Asterisk manager Interface with SSL support
+# Requires OpenSSL development libraries
+# (This will be disabled in svn, but not in the dev branch)
+ASTCFLAGS+=-DAMI_WITH_SSL
+
# Uncomment this to use the older DSP routines
#ASTCFLAGS+=-DOLD_DSP_ROUTINES
@@ -293,7 +298,7 @@
OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \
translate.o file.o pbx.o cli.o md5.o term.o \
ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \
- cdr.o tdd.o acl.o rtp.o udptl.o manager.o asterisk.o \
+ cdr.o tdd.o acl.o rtp.o udptl.o manager.o ssl_addon.o asterisk.o \
dsp.o chanvars.o indications.o autoservice.o db.o privacy.o \
astmm.o enum.o srv.o dns.o aescrypt.o aestab.o aeskey.o \
utils.o plc.o jitterbuf.o scx_jitterbuf.o abstract_jb.o dnsmgr.o devicestate.o \
@@ -374,6 +379,10 @@
HAVEDOT=yes
else
HAVEDOT=no
+endif
+
+ifeq ($(findstring AMI_WITH_SSL, $(ASTCFLAGS)), AMI_WITH_SSL)
+ LIBS+=-lssl
endif
INSTALL=install
@@ -692,7 +701,7 @@
echo " WARNING WARNING WARNING" ;\
fi
-install: all datafiles bininstall install-subdirs
+install: all datafiles cert bininstall install-subdirs
@if [ -x /usr/sbin/asterisk-post-install ]; then \
/usr/sbin/asterisk-post-install $(DESTDIR) . ; \
fi
@@ -716,6 +725,15 @@
@echo " + +"
@echo " + **Note** This requires that you have +"
@echo " + doxygen installed on your local system +"
+ @echo " +-------------------------------------------+"
+ @echo " + +"
+ @echo " + AMI can be encrypted or unencrypted. For +"
+ @echo " + encrypted you can either create your own +"
+ @echo " + certificate or use the one provided by +"
+ @echo " + the asterisk. If you want to create your +"
+ @echo " + own certificate, please read the ssl.txt +"
+ @echo " + documentation in the doc directory. +"
+ @echo " + +"
@echo " +-------------------------------------------+"
@$(MAKE) -s oldmodcheck
@@ -915,6 +933,59 @@
env:
env
+
+UTF8 := $(shell locale -c LC_CTYPE -k | grep -q charmap.*UTF-8 && echo -utf8)
+SERIAL=0
+
+cert:
+ if [ ! -f /var/lib/asterisk/certs/server.pem ]; then \
+ umask 77 ; \
+ PEM1=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
+ PEM2=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
+ sudo cp ./configs/ssl.conf.sample /etc/asterisk/ssl.conf; \
+ /usr/bin/openssl req $(UTF8) -newkey rsa:1024 -keyout $$PEM1 -nodes -x509 -days 365 -out $$PEM2 -set_serial $(SERIAL) -config /etc/asterisk/ssl.conf; \
+ cat $$PEM1 > $@ ; \
+ echo "" >> $@ ; \
+ cat $$PEM2 >> $@ ; \
+ cat $@ > server.pem ;\
+ sudo mkdir -p /var/lib/asterisk/certs; \
+ sudo mv $@ /var/lib/asterisk/certs/server.pem; \
+ $(RM) $$PEM1 $$PEM2 $@; \
+ fi
+
+
+
+certificate:
+ createcert="1"; \
+ if [ -f /var/lib/asterisk/certs/server.pem ]; then \
+ echo -n "The certificate already exists, Do you really want to create new one(yes/no)?"; \
+ read answer; \
+ if [ "$$answer" = "yes" ]; then \
+ echo "I am creating a new certificate, Old one is copied as server.pem.old ";\
+ sudo cp /var/lib/asterisk/certs/server.pem /var/lib/asterisk/certs/server.pem.old; \
+ elif [ "$$answer" = "no" ]; then \
+ echo "Certificate already exists, I am not creating a new certificate,";\
+ createcert="0"; \
+ else \
+ echo "You need to enter either yes or no"; \
+ createcert="0"; \
+ fi; \
+ fi; \
+ if [ "$$createcert" = "1" ]; then \
+ umask 77 ; \
+ PEM1=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
+ PEM2=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
+ sudo cp ./configs/ssl.conf.sample /etc/asterisk/ssl.conf; \
+ /usr/bin/openssl req $(UTF8) -newkey rsa:1024 -keyout $$PEM1 -nodes -x509 -days 365 -out $$PEM2 -set_serial $(SERIAL) -config /etc/asterisk/ssl.conf; \
+ cat $$PEM1 > $@ ; \
+ echo "" >> $@ ; \
+ cat $$PEM2 >> $@ ; \
+ cat $@ > server.pem ;\
+ sudo mkdir -p /var/lib/asterisk/certs; \
+ sudo mv $@ /var/lib/asterisk/certs/server.pem; \
+ $(RM) $$PEM1 $$PEM2 $@; \
+ fi
+
# If the cleancount has been changed, force a make clean.
# .cleancount is the global clean count, and .lastclean is the
# last clean count we had
Modified: team/oej/test-this-branch/README.test-this-branch
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/README.test-this-branch?rev=27385&r1=27384&r2=27385&view=diff
==============================================================================
--- team/oej/test-this-branch/README.test-this-branch (original)
+++ team/oej/test-this-branch/README.test-this-branch Tue May 16 10:14:43 2006
@@ -33,9 +33,10 @@
- metermaids: Subscription support for parking lots (#5779)
- filenamelen: Some code changes for file name lengths (oej)
- t38passthrough: Support for Fax passthrough in SIP (#5090, Steve Underwood)
-- rtptiming: Support for timed RTP (#5374, cmantunes/DEA/sokhapkin)
- findme_followme: Followme application (#5574, bweschke)
Missing sound files, config file template
+- SSL for AMI: Secured manager connections (#6812, jtodd)
+ See README file in doc/ and manager.conf.sample
And the following stand-alone patches
- Manager sendtext event (ZX81, #6131)
@@ -59,6 +60,7 @@
dialing (#6705, oej) - See configs/sip.conf.sample
- videosupport: Improved support for video (#5427, John Martin)
- iptos: New IPtos support, separate audio and signalling (#6355)
+- rtptiming: Support for timed RTP (#5374, cmantunes/DEA/sokhapkin)
- Support SIP_CODEC for early media (oej, #6576)
- Additional options for the CHANNEL dialplan function (oej, #6670)
- subscribemwi: Support for SIP subscription of MWI notification (oej #6390)
@@ -72,7 +74,6 @@
Coming here soon:
- siptransfer: Improved SIP transfer support (branch)
-- SSL for AMI: Secured manager connections
Temporarily disabled:
- G.722 support in Asterisk (passthrough, formats) (andrew, #5084)
Modified: team/oej/test-this-branch/README.test-this-branch.html
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/README.test-this-branch.html?rev=27385&r1=27384&r2=27385&view=diff
==============================================================================
--- team/oej/test-this-branch/README.test-this-branch.html (original)
+++ team/oej/test-this-branch/README.test-this-branch.html Tue May 16 10:14:43 2006
@@ -35,6 +35,8 @@
See <a href="http://svn.digium.com/view/asterisk/team/oej/test-this-branch/doc/sipt38support.txt?view=markup">doc/sipt38support.txt</a>
<li> findme_followme: Followme application
(<a href="http://bugs.digium.com/view.php?id=5574">#5574</a>, bweschke)</li>
+<li>ami_ssl: SSL for the manager port
+(<a href="http://bugs.digium.com/view.php?id=6812">#6812</a>, jtodd)</li>
</ul>
</p>
Modified: team/oej/test-this-branch/configs/manager.conf.sample
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/configs/manager.conf.sample?rev=27385&r1=27384&r2=27385&view=diff
==============================================================================
--- team/oej/test-this-branch/configs/manager.conf.sample (original)
+++ team/oej/test-this-branch/configs/manager.conf.sample Tue May 16 10:14:43 2006
@@ -32,6 +32,26 @@
; Add a Unix epoch timestamp to events (not action responses)
;
;timestampevents = yes
+;
+; To enable SSL encryption in manager, set the AMI_SSL optin
+; in the Makefile
+;
+; For SSL encryption, where is the cert file?
+;
+;certfile = /var/lib/asterisk/certs/server.pem
+;
+; How long do we wait on the manager port for an SSL session start? (ms)
+;
+;sslclienthellotimeout = 500
+;
+; Do we accept encrypted SSL manager connections?
+;
+;acceptencryptedconnection = yes
+;
+; Do we accept unencrypted manager connections?
+;
+acceptunencryptedconnection = yes
+;
;[mark]
;secret = mysecret
Added: team/oej/test-this-branch/doc/ssl.conf.sample
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/doc/ssl.conf.sample?rev=27385&view=auto
==============================================================================
--- team/oej/test-this-branch/doc/ssl.conf.sample (added)
+++ team/oej/test-this-branch/doc/ssl.conf.sample Tue May 16 10:14:43 2006
@@ -1,0 +1,154 @@
+# Asterisk SSL configuration
+#
+# OpenSSL configuration file for custom Certificate Authority. Use a
+# different openssl.cnf file to generate certificate signing requests;
+# this one is for use only in Certificate Authority operations (csr ->
+# cert, cert revocation, revocation list generation).
+#
+# Be sure to customize this file prior to use, e.g. the commonName and
+# other options under the root_ca_distinguished_name section.
+
+HOME = .
+RANDFILE = $ENV::HOME/.rnd
+
+[ ca ]
+default_ca = MyAsteriskCA
+
+[ MyAsteriskCA ]
+dir = .
+# unsed at present, and my limited certs can be kept in current dir
+#certs = $dir/certs
+new_certs_dir = $dir/newcerts
+crl_dir = $dir/crl
+database = $dir/index
+
+certificate = $dir/ca-cert.pem
+serial = $dir/serial
+crl = $dir/ca-crl.pem
+private_key = $dir/private/ca-key.pem
+RANDFILE = $dir/private/.rand
+
+x509_extensions = usr_cert
+
+# Comment out the following two lines for the "traditional"
+# (and highly broken) format.
+name_opt = ca_default
+cert_opt = ca_default
+
+default_crl_days= 30
+default_days = 7300
+# if need to be compatible with older software, use weaker md5
+default_md = sha1
+# MSIE may need following set to yes?
+preserve = no
+
+# A few difference way of specifying how similar the request should look
+# For type CA, the listed attributes must be the same, and the optional
+# and supplied fields are just that :-)
+policy = policy_match
+
+# For the CA policy
+[ policy_match ]
+countryName = US
+stateOrProvinceName = CA
+organizationName = XYZ
+organizationalUnitName = XYZ
+commonName = asterisk
+emailAddress = root at localhost
+
+# For the 'anything' policy
+# At this point in time, you must list all acceptable 'object'
+# types.
+[ policy_anything ]
+countryName = optional
+stateOrProvinceName = optional
+localityName = optional
+organizationName = optional
+organizationalUnitName = optional
+commonName = supplied
+emailAddress = optional
+
+####################################################################
+[ req ]
+default_bits = 2048
+default_keyfile = ./private/ca-key.pem
+default_md = sha1
+
+prompt = no
+distinguished_name = root_ca_distinguished_name
+
+x509_extensions = v3_ca
+
+# Passwords for private keys if not present they will be prompted for
+# input_password = secret
+# output_password = secret
+
+# This sets a mask for permitted string types. There are several options.
+# default: PrintableString, T61String, BMPString.
+# pkix : PrintableString, BMPString.
+# utf8only: only UTF8Strings.
+# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
+# MASK:XXXX a literal mask value.
+# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
+# so use this option with caution!
+string_mask = nombstr
+
+# req_extensions = v3_req
+
+[ root_ca_distinguished_name ]
+commonName = NoSuchCA CA
+countryName = US
+stateOrProvinceName = California
+localityName = San Mateo
+0.organizationName = domain.net
+emailAddress = nobody at localhost
+
+[ usr_cert ]
+
+# These extensions are added when 'ca' signs a request.
+
+# This goes against PKIX guidelines but some CAs do it and some software
+# requires this to avoid interpreting an end user certificate as a CA.
+
+basicConstraints=CA:FALSE
+
+# PKIX recommendations harmless if included in all certificates.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid,issuer:always
+
+nsCaRevocationUrl = https://www.sial.org/ca-crl.pem
+#nsBaseUrl
+#nsRevocationUrl
+#nsRenewalUrl
+#nsCaPolicyUrl
+#nsSslServerName
+
+[ v3_req ]
+
+# Extensions to add to a certificate request
+
+basicConstraints = CA:FALSE
+keyUsage = nonRepudiation, digitalSignature, keyEncipherment
+
+[ v3_ca ]
+
+
+# Extensions for a typical CA
+
+# PKIX recommendation.
+subjectKeyIdentifier=hash
+authorityKeyIdentifier=keyid:always,issuer:always
+
+# This is what PKIX recommends but some broken software chokes on critical
+# extensions.
+#basicConstraints = critical,CA:true
+# So we do this instead.
+basicConstraints = CA:true
+
+[ crl_ext ]
+
+# CRL extensions.
+# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
+
+# issuerAltName=issuer:copy
+authorityKeyIdentifier=keyid:always,issuer:always
Propchange: team/oej/test-this-branch/doc/ssl.conf.sample
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/oej/test-this-branch/doc/ssl.conf.sample
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/oej/test-this-branch/doc/ssl.conf.sample
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: team/oej/test-this-branch/include/asterisk/ssl_addon.h
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/include/asterisk/ssl_addon.h?rev=27385&view=auto
==============================================================================
--- team/oej/test-this-branch/include/asterisk/ssl_addon.h (added)
+++ team/oej/test-this-branch/include/asterisk/ssl_addon.h Tue May 16 10:14:43 2006
@@ -1,0 +1,91 @@
+/*
+ * ssl_addon: Encrypts the asterisk management interface
+ *
+ * Copyrights:
+ * Copyright (C) 2005-2006, Tello Corporation, Inc.
+ *
+ * Contributors:
+ * Remco Treffkorn(Architect) and Mahesh Karoshi
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU Lesser (Library) General Public License
+ *
+ * Copyright on this file is disclaimed to Digium for inclusion in Asterisk
+ */
+
+#ifndef _SSL_ADDON_H_
+#define _SSL_ADDON_H_
+
+#include <openssl/ssl.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*! \brief
+ This data structure holds the additional SSL data needed to use the ssl functions.
+ The negative fd is used as an index into this data structure (after processing).
+ Choose SEC_MAX to be impossibly large for the application.
+*/
+#define SEC_MAX 8
+struct {
+ int fd;
+ SSL* ssl;
+} sec_channel[SEC_MAX];
+
+/*! \brief
+ this has to be called before any other function dealing with ssl.
+*/
+int init_secure(char* certfile);
+
+/*! \brief
+ Returns the real fd, that is received from os, when we accept the connection.
+*/
+int get_real_fd(int fd);
+
+/*! \brief
+ Returns the ssl structure from the fd.
+*/
+SSL *get_ssl(int fd);
+
+/*! \brief
+ Returns the availabe security slot. This restricts the maximun number of security connection,
+ the asterisk server can have for AMI.
+*/
+int sec_getslot(void);
+
+/*! \brief
+ 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);
+
+/*! \brief
+ Sends the data over secured or unsecured connections.
+*/
+int m_send(int fd, const void *data, size_t len);
+
+
+/*! \brief
+ Receives the connection from either ssl or fd.
+*/
+int m_recv(int s, void *buf, size_t len, int flags);
+
+
+/*! \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 errexit(char s[]);
+
+int is_encrypt_request(int sslclhellotimeout, int fd);
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
Propchange: team/oej/test-this-branch/include/asterisk/ssl_addon.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/oej/test-this-branch/include/asterisk/ssl_addon.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/oej/test-this-branch/include/asterisk/ssl_addon.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/oej/test-this-branch/manager.c
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/manager.c?rev=27385&r1=27384&r2=27385&view=diff
==============================================================================
--- team/oej/test-this-branch/manager.c (original)
+++ team/oej/test-this-branch/manager.c Tue May 16 10:14:43 2006
@@ -65,6 +65,9 @@
#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 {
@@ -82,6 +85,12 @@
int priority;
struct ast_variable *vars;
};
+
+#ifdef AMI_WITH_SSL
+static int sslclhellotimeout = 200;
+static int acceptencryptedconnection = 0;
+static int acceptunencryptedconnection = 0;
+#endif
struct eventqent {
int usecount;
@@ -612,8 +621,12 @@
static void free_session(struct mansession *s)
{
struct eventqent *eqe;
+#ifdef AMI_WITH_SSL
+ close_sock(s->fd);
+#else
if (s->fd > -1)
close(s->fd);
+#endif
if (s->outputstr)
free(s->outputstr);
ast_mutex_destroy(&s->__lock);
@@ -1863,6 +1876,10 @@
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 {
ast_mutex_lock(&s->__lock);
@@ -1884,7 +1901,11 @@
return -1;
} 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);
+#else
res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen);
+#endif
ast_mutex_unlock(&s->__lock);
if (res < 1)
return -1;
@@ -1961,6 +1982,7 @@
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ int is_encrypted;
for (;;) {
time(&now);
@@ -2012,6 +2034,31 @@
ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
}
}
+#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);
+ continue;
+ } else {
+ if((as = saccept(as)) >= 0 ) {
+ ast_log(LOG_WARNING, "Can't accept the ssl connection, since SSL init has failed for certificate reason\n");
+ close_sock(as);
+ continue;
+ }
+ }
+ } else if (is_encrypted == -1) {
+ ast_log(LOG_ERROR, "SSL version 2 is unsecure, we don't support it\n");
+ close_sock(as);
+ 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);
+ continue;
+ }
+#endif
s = malloc(sizeof(struct mansession));
if (!s) {
ast_log(LOG_WARNING, "Failed to allocate management session: %s\n", strerror(errno));
@@ -2024,8 +2071,13 @@
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;
@@ -2466,6 +2518,9 @@
int flags;
int webenabled = 0;
int newhttptimeout = 60;
+#ifdef AMI_WITH_SSL
+ char certfile[1000], ssltimeout[1000];
+#endif
amus = NULL;
@@ -2556,6 +2611,46 @@
ast_log(LOG_WARNING, "Unable to change management port / enabled\n");
#endif
}
+#ifdef AMI_WITH_SSL
+ /* Parsing the certificate directory */
+ if ((val = ast_variable_retrieve(cfg, "general", "certfile"))) {
+ if (sscanf(val, "%s", (char *)certfile) != 1) {
+ ast_log(LOG_WARNING, "Certificate directory not found, assigning default directory\n");
+ snprintf(certfile, sizeof(certfile), "%s/%s", ast_config_AST_VAR_DIR, "certs/server.pem");
+ }
+ } else {
+ snprintf(certfile, sizeof(certfile), "%s/%s", ast_config_AST_VAR_DIR, "certs/server.pem");
+ }
+ if ((val = ast_variable_retrieve(cfg, "general", "sslclienthellotimeout"))) {
+ if (sscanf(val, "%s", (char *)ssltimeout) != 1) {
+ sslclhellotimeout = 500;
+ ast_log(LOG_NOTICE, "Failed to read sslclhellotime\n");
+ } else {
+ sslclhellotimeout = atoi(ssltimeout);
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "sslclhellotime = %d", sslclhellotimeout);
+ }
+ } else {
+ sslclhellotimeout = 500;
+ }
+ val = ast_variable_retrieve(cfg, "general", "acceptencryptedconnection");
+ if (val) {
+ acceptencryptedconnection = ast_true(val);
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "acceptencryptedconnection = %d", acceptencryptedconnection);
+ } else {
+ acceptencryptedconnection = -1;
+ }
+ val = ast_variable_retrieve(cfg, "general", "acceptunencryptedconnection");
+ if (val) {
+ acceptunencryptedconnection = ast_true(val);
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "acceptunencryptedconnection = %d", acceptunencryptedconnection);
+ } else {
+ acceptunencryptedconnection = -1;
+ }
+ init_secure(certfile);
+#endif
cat = ast_category_browse(cfg, NULL);
amus = NULL; /* Resetting the boss */
Added: team/oej/test-this-branch/ssl_addon.c
URL: http://svn.digium.com/view/asterisk/team/oej/test-this-branch/ssl_addon.c?rev=27385&view=auto
==============================================================================
--- team/oej/test-this-branch/ssl_addon.c (added)
+++ team/oej/test-this-branch/ssl_addon.c Tue May 16 10:14:43 2006
@@ -1,0 +1,313 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2006, Tello Corporation, Inc.
+ *
+ * Remco Treffkorn(Architect) and Mahesh Karoshi(Senior Software Developer)
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * 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
+ -1 is reseved for errors. -2 to -... are secure file descriptors. 0 to ...
+ are regular file descriptors.
+
+ NOTE: Commonly error checks for routines returning fd's are done with (value<0).
+ 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>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include "asterisk.h"
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/logger.h"
+#include "asterisk/options.h"
+#include "asterisk/config.h"
+#include "asterisk/ssl_addon.h"
+
+SSL_CTX *sctx;
+static long rec_bytes;
+static long sent_bytes;
+static int ssl_initialized;
+
+
+/*! \brief this has to be called before any other function dealing with ssl.
+ Initializes all the ssl related stuff here. */
+int init_secure(char *certfile)
+{
+ SSL_METHOD *meth;
+
+ SSLeay_add_ssl_algorithms();
+ SSL_load_error_strings();
+
+ /* server init */
+ meth = SSLv23_server_method();
+ sctx = SSL_CTX_new(meth);
+
+ if (!sctx) {
+ return errexit("Failed to create a server ssl context!");
+ }
+
+ if (SSL_CTX_use_certificate_file(sctx, certfile, SSL_FILETYPE_PEM) <= 0) {
+ return errexit("Failed to use the certificate file!");
+ }
+
+ if (SSL_CTX_use_PrivateKey_file(sctx, certfile, SSL_FILETYPE_PEM) <= 0) {
+ return errexit("Failed to use the key file!\n");
+ }
+
+ if (!SSL_CTX_check_private_key(sctx)) {
+ return errexit("Private key does not match the certificate public key");
+ }
+ ssl_initialized = 1;
+ 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.
+*/
+int get_real_fd(int fd)
+{
+ if (fd<-1) {
+ fd = -fd - 2;
+ if (fd>=0 && fd <SEC_MAX)
+ 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.
+*/
+SSL *get_ssl(int fd)
+{
+ SSL *ssl = NULL;
+
+ fd = -fd - 2;
+
+ if (fd>=0 && fd <SEC_MAX)
+ ssl = sec_channel[fd].ssl;
+
+ return ssl;
+}
+
+/*! \brief Returns the empty ssl slot. Used to save ssl information.
+*/
+int sec_getslot(void)
+{
+ int i;
+
+ for (i=0; i<SEC_MAX; i++) {
+ if(sec_channel[i].ssl==NULL)
+ break;
+ }
+
+ if (i==SEC_MAX)
+ return -1;
+ return i;
+}
+
+/*! \brief Accepts the ssl connection. Retrurns the negative fd. negative fd's are
+ * choosen 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.
+ * You can always get positive fd by calling get_real_fd(negative fd).
+ * The positive fd's are required for system calls.
+ *
+*/
+int saccept(int s)
+{
+ int fd, err;
+ SSL* ssl;
+
+ if (!ssl_initialized)
+ return s;
+
+ if (((fd=sec_getslot())!=-1)) {
+ ssl=SSL_new(sctx);
+ SSL_set_fd(ssl, s);
+ sec_channel[fd].ssl = ssl; /* remember ssl */
+ sec_channel[fd].fd = s; /* remember the real fd */
+ do {
+ err = SSL_accept(ssl);
+ err = SSL_get_error(ssl, err);
+ } while( err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE);
+
+ SSL_set_mode(ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
+ ast_log(LOG_DEBUG, "ssl_addon: Connection accepted");
+
+ err=1;
+
+ fd = -(fd+2);
+
+ if (err!=1 || !ssl) {
+ /* it did not work */
+ sec_channel[fd].ssl = NULL; /* free the slot */
+ fd = -1;
+ }
+ }
+ return fd;
+}
+
+/*!
+ * \brief Writes through secured ssl connection
+*/
+int m_send(int fd, const void *data, size_t len)
+{
+ sent_bytes += len;
+
+ if (fd < -1) {
+ SSL* ssl = get_ssl(fd);
+ return SSL_write(ssl, data, len);
+ }
+ return write(fd, data, len);
+}
+
+/*!
+ * \brief Receives data from the SSL connection.
+*/
+int m_recv(int s, void *buf, size_t len, int flags)
+{
+ int ret = 0;
+
+ if (s<-1) {
+ SSL* ssl = get_ssl(s);
+ ret = SSL_read (ssl, buf, len);
+ } else
+ ret = recv(s, buf, len, flags);
+
+ if (ret > 0)
+ rec_bytes += ret;
+
+ if (option_debug > 2)
+ ast_log(LOG_DEBUG, "Received data from SSL socket - %d\n", ret);
+ return ret;
+}
+
+
+/*! \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 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;
+ }
+
+ ret= close(socket);
+
+ if (ssl)
+ SSL_free (ssl);
+
+ return(ret);
+}
+
+/*! \brief This process cannot continue without fixing this error.
+*/
+int errexit(char s[])
+{
+ ast_log(LOG_ERROR, "SSL critical error: %s", s);
+ return -1;
+}
+
+/*! \brief Checks whether the client is requesting an ssl encrypted connection or not. If its encrypted
+ * request we expect "Client Hello" in the beginning of the message and ssl version 2.
+ * This can be verified by checking buf[0x02], buf[0x03] and buf[0x04]. If the contents are
+ * 0x01, 0x00, 0x02, then its an ssl packet with content "Client Hello", "SSL version 2".
+ * For SSL version 3, we might need to check for 0x01, 0x00, 0x03.
+ *
+*/
+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 ) {
+ ast_log(LOG_ERROR, "select returned error, This should not happen: \n");
+ 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 (option_debug > 1)
+ ast_log(LOG_DEBUG, "Received a SSL request\n");
+ return 1;
+ /* check for sslv23_client_method */
+ } else if ((buf[0x02] == 0x01) && (buf[0x03] == 0x03) && (buf[0x04] == 0x01)) {
+ if (option_debug > 1)
+ ast_log(LOG_DEBUG, "Received a SSL request for SSLv23_client_method()\n");
+ return 1;
+ }
+ /* check for sslv2 and return -1 */
+ else if ((buf[0x02] == 0x01) && (buf[0x03] == 0x00) && (buf[0x04] == 0x02)) {
+ return -1;
+ }
+ }
+ return 0;
+}
+#endif
Propchange: team/oej/test-this-branch/ssl_addon.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/oej/test-this-branch/ssl_addon.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/oej/test-this-branch/ssl_addon.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the asterisk-commits
mailing list