diff options
-rw-r--r-- | config/stunnel.xml | 107 | ||||
-rw-r--r-- | config/stunnel/stunnel.inc | 232 | ||||
-rw-r--r-- | config/stunnel/stunnel_certs.xml | 147 | ||||
-rwxr-xr-x | pkg_config.7.xml | 2 |
4 files changed, 430 insertions, 58 deletions
diff --git a/config/stunnel.xml b/config/stunnel.xml index 64c9becd..6ea9f99f 100644 --- a/config/stunnel.xml +++ b/config/stunnel.xml @@ -51,11 +51,35 @@ <section>Services</section> <configfile>stunnel.xml</configfile> </menu> + + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>0644</chmod> + <item>http://www.pfsense.com/packages/config/stunnel/stunnel.inc</item> + </additional_files_needed> + <additional_files_needed> + <prefix>/usr/local/pkg/</prefix> + <chmod>0644</chmod> + <item>http://www.pfsense.com/packages/config/stunnel/stunnel_certs.xml</item> + </additional_files_needed> <!-- configpath gets expanded out automatically and config items will be stored in that location --> <configpath>['installedpackages']['package']['$packagename']['configuration']</configpath> + + <tabs> + <tab> + <text>Tunnels</text> + <url>/pkg.php?xml=stunnel.xml</url> + <active/> + </tab> + <tab> + <text>Certificates</text> + <url>/pkg.php?xml=stunnel_certs.xml</url> + </tab> + </tabs> + <!-- adddeleteeditpagefields items will appear on the first page where you can add / delete or edit - items. An example of this would be the nat page where you add new nat redirects --> + items. An example of this would be the nat page where you add new nat redirects --> <adddeleteeditpagefields> <columnitem> <fielddescr>Description</fielddescr> @@ -70,6 +94,10 @@ <fieldname>localport</fieldname> </columnitem> <columnitem> + <fielddescr>Certificate</fielddescr> + <fieldname>certificatelink</fieldname> + </columnitem> + <columnitem> <fielddescr>Redirects to IP</fielddescr> <fieldname>redirectip</fieldname> </columnitem> @@ -100,6 +128,16 @@ <type>input</type> </field> <field> + <fielddescr>Certificate</fielddescr> + <fieldname>certificate</fieldname> + <description>Select server certificate to use for this tunnel. Certificates are defined on the 'Certificates' page.</description> + <type>select</type> + <options> + <option><name> --- default --- </name><value></value></option> + </options> + <default_value></default_value> + </field> + <field> <fielddescr>Redirects to IP</fielddescr> <fieldname>redirectip</fieldname> <description>Enter the IP address to redirect this to.</description> @@ -117,72 +155,27 @@ <description>Enter the source IP address for outgoing connections.</description> <type>input</type> </field> - </fields> + <service> <name>stunnel</name> <rcfile>/usr/local/etc/rc.d/stunnel.sh</rcfile> <executable>stunnel</executable> </service> + + <include_file>/usr/local/pkg/stunnel.inc</include_file> + <custom_add_php_command_late> - <![CDATA[ - conf_mount_rw(); - config_lock(); - $fout = fopen("/usr/local/etc/stunnel/stunnel.conf","w"); - fwrite($fout, "cert = /usr/local/etc/stunnel/stunnel.pem \n"); - fwrite($fout, "chroot = /var/tmp/stunnel \n"); - fwrite($fout, "setuid = stunnel \n"); - fwrite($fout, "setgid = stunnel \n"); - foreach($config['installedpackages']['stunnel']['config'] as $pkgconfig) { - fwrite($fout, "\n[" . $pkgconfig['description'] . "]\n"); - if($pkgconfig['sourceip']) fwrite($fout, "local = " . $pkgconfig['sourceip'] . "\n"); - fwrite($fout, "accept = " . $pkgconfig['localip'] . ":" . $pkgconfig['localport'] . "\n"); - fwrite($fout, "connect = " . $pkgconfig['redirectip'] . ":" . $pkgconfig['redirectport'] . "\n"); - fwrite($fout, "TIMEOUTclose = 0\n\n"); - } - fclose($fout); - conf_mount_ro(); - config_unlock(); - system("/usr/local/etc/rc.d/stunnel.sh stop 2>/dev/null"); - system("/usr/local/etc/rc.d/stunnel.sh start 2>/dev/null"); - ]]> + stunnel_save($config); </custom_add_php_command_late> <custom_php_install_command> - <![CDATA[ - safe_mkdir("/usr/local/etc/stunnel"); - system("/usr/bin/openssl req -new -x509 -days 365 -nodes -out /usr/local/etc/stunnel/stunnel.pem -keyout /usr/local/etc/stunnel/stunnel.pem 2>/dev/null"); - chmod("/usr/local/etc/stunnel/stunnel.pem", 600); - make_dirs("/var/tmp/stunnel/var/tmp/run/stunnel"); - system("/usr/sbin/chown -R stunnel:stunnel /var/tmp/stunnel"); - $_rcfile['file']='stunnel.sh'; - $_rcfile['start'].="/usr/local/bin/stunnel /usr/local/etc/stunnel/stunnel.conf \n\t"; - $_rcfile['stop'].="killall stunnel \n\t"; - write_rcfile($_rcfile); - unlink_if_exists("/usr/local/etc/rc.d/stunnel"); - conf_mount_rw(); - config_lock(); - $fout = fopen("/usr/local/etc/stunnel/stunnel.conf","w"); - fwrite($fout, "cert = /usr/local/etc/stunnel/stunnel.pem \n"); - fwrite($fout, "chroot = /var/tmp/stunnel \n"); - fwrite($fout, "setuid = stunnel \n"); - fwrite($fout, "setgid = stunnel \n"); - foreach($config['installedpackages']['stunnel']['config'] as $pkgconfig) { - fwrite($fout, "\n[" . $pkgconfig['description'] . "]\n"); - if($pkgconfig['sourceip']) fwrite($fout, "local = " . $pkgconfig['sourceip'] . "\n"); - fwrite($fout, "accept = " . $pkgconfig['localip'] . ":" . $pkgconfig['localport'] . "\n"); - fwrite($fout, "connect = " . $pkgconfig['redirectip'] . ":" . $pkgconfig['redirectport'] . "\n"); - fwrite($fout, "TIMEOUTclose = 0\n\n"); - } - fclose($fout); - conf_mount_ro(); - config_unlock(); - ]]> + stunnel_install(); </custom_php_install_command> <custom_php_deinstall_command> - <![CDATA[ - rmdir_recursive("/var/tmp/stunnel"); - rmdir_recursive("/usr/local/etc/stunnel*"); - unlink_if_exists("/usr/local/etc/rc.d/stunnel.sh"); - ]]> + stunnel_deinstall(); </custom_php_deinstall_command> + <custom_php_after_form_command> + stunnel_addcerts($config); + </custom_php_after_form_command> + </packagegui> diff --git a/config/stunnel/stunnel.inc b/config/stunnel/stunnel.inc new file mode 100644 index 00000000..62558e34 --- /dev/null +++ b/config/stunnel/stunnel.inc @@ -0,0 +1,232 @@ +<?php + +if(!isset($_GET['id']) and !isset($_POST['id'])) { + if($GLOBALS['config']['installedpackages']['stunnelcerts']['savemsg']) { + $savemsg=$GLOBALS['config']['installedpackages']['stunnelcerts']['savemsg']; + unset($GLOBALS['config']['installedpackages']['stunnelcerts']['savemsg']); + write_config(); + } + +} + +if(isset($_GET['id'])) { + $config['installedpackages']['stunnelcerts']['config'][$_GET['id']]['cert_chain']= + base64_decode($config['installedpackages']['stunnelcerts']['config'][$_GET['id']]['cert_chain']); + $config['installedpackages']['stunnelcerts']['config'][$_GET['id']]['cert_key']= + base64_decode($config['installedpackages']['stunnelcerts']['config'][$_GET['id']]['cert_key']); +} + +$certs=$config['installedpackages']['stunnelcerts']['config']; +is_array($certs) ? $num_certs=count($certs) : $num_certs=0; +if(!isset($_GET['id']) and !isset($_POST['id']) and $num_certs) { + for ($i=0;$i<$num_certs;$i++) { + $cert=$certs[$i]; + $_info=openssl_x509_parse(base64_decode($cert['cert_chain'])); + $valid=floor(($_info['validTo_time_t']-time())/86400); + if(!openssl_x509_check_private_key(base64_decode($cert['cert_chain']), base64_decode($cert['cert_key']))) { + $_status='<font color="#AA0000"><b>Invalid key/cert!</b></font>'; + } elseif($valid<30) { + $_status='<font color="#B27D4B">Expires in '.$valid.' days!</font>'; + } else { + $_status='<font color="#008800">OK ('.$valid.' days)</font>'; + } + $config['installedpackages']['stunnelcerts']['config'][$i]['status']=$_status; + } +} + + +$tunnels=$config['installedpackages']['stunnel']['config']; +is_array($tunnels) ? $num_tunnels=count($tunnels) : $num_tunnels=0; +if(!isset($_GET['id']) and $num_tunnels) { + for ($i=0;$i<$num_tunnels;$i++) { + $tunnel=$tunnels[$i]; + if($tunnel['certificate']) { + $certid=0; + if(is_array($config['installedpackages']['stunnelcerts']['config'])) { + foreach($config['installedpackages']['stunnelcerts']['config'] as $cert) { + if($tunnel['certificate']==$cert['filename']) + $config['installedpackages']['stunnel']['config'][$i]['certificatelink']= + '<a href="/pkg_edit.php?xml=stunnel_certs.xml&act=edit&id='.$certid.'">'.$cert['description'].'</a>'; + $certid++; + } + } + } + } +} + +function stunnel_printcsr() { +# $GLOBALS['savemsg']="<pre>" . print_r($GLOBALS['config']['installedpackages']['stunnelcerts']['config'],true) . "</pre>"; +} + +function stunnel_addcerts($config) { + $certs=$config['installedpackages']['stunnelcerts']['config']; + $tunnels=$config['installedpackages']['stunnel']['config']; + ?> + <script type="text/javascript"> + function addcerts() { + <?php + + foreach($certs as $cert) { + echo("document.forms['iform'].certificate.appendChild(new Option('".$cert['description']."', '".$cert['filename']."'));"); + } + + ?> + } + addcerts(); + for (var i=0; i < document.forms['iform'].certificate.length; i++) { + <?php + $filename=$tunnels[$_GET['id']]['certificate']; + echo('if (document.forms["iform"].certificate[i].value == "'.$filename.'") {'); + ?> + document.forms['iform'].certificate[i].selected = true; + } else { + document.forms['iform'].certificate[i].selected = false; + } + } + + </script> + <?php +} + +function stunnel_disablefields() { + ?> + <script type="text/javascript"> + document.forms['iform'].subject.readOnly=true; + document.forms['iform'].filename.readOnly=true; + document.forms['iform'].expiry.readOnly=true; + </script> + <?php +} + +function stunnel_delete($config) { + $cert=$config['installedpackages']['stunnelcerts']['config'][$_GET['id']]; + if(isset($_GET['id'])) { + unlink_if_exists('/usr/local/etc/stunnel/'.$cert['filename'].'pem'); + unlink_if_exists('/usr/local/etc/stunnel/'.$cert['filename'].'key'); + unlink_if_exists('/usr/local/etc/stunnel/'.$cert['filename'].'chain'); + } +} + +function stunnel_save($config) { + $GLOBALS['config']['installedpackages']['stunnelcerts']['savemsg']=''; + conf_mount_rw(); + config_lock(); + $fout = fopen("/usr/local/etc/stunnel/stunnel.conf","w"); + fwrite($fout, "cert = /usr/local/etc/stunnel/stunnel.pem \n"); + fwrite($fout, "chroot = /var/tmp/stunnel \n"); + fwrite($fout, "setuid = stunnel \n"); + fwrite($fout, "setgid = stunnel \n"); + foreach($config['installedpackages']['stunnel']['config'] as $pkgconfig) { + fwrite($fout, "\n[" . $pkgconfig['description'] . "]\n"); + if($pkgconfig['certificate']) { + if(file_exists('/usr/local/etc/stunnel/'.$pkgconfig['certificate'].'.key') and + file_exists('/usr/local/etc/stunnel/'.$pkgconfig['certificate'].'.chain')) { + fwrite($fout, "key = /usr/local/etc/stunnel/" . $pkgconfig['certificate'] . ".key\n"); + fwrite($fout, "cert = /usr/local/etc/stunnel/" . $pkgconfig['certificate'] . ".chain\n"); + } + } + if($pkgconfig['sourceip']) fwrite($fout, "local = " . $pkgconfig['sourceip'] . "\n"); + fwrite($fout, "accept = " . $pkgconfig['localip'] . ":" . $pkgconfig['localport'] . "\n"); + fwrite($fout, "connect = " . $pkgconfig['redirectip'] . ":" . $pkgconfig['redirectport'] . "\n"); + fwrite($fout, "TIMEOUTclose = 0\n\n"); + } + fclose($fout); + conf_mount_ro(); + config_unlock(); + system("/usr/local/etc/rc.d/stunnel.sh stop 2>/dev/null"); + system("/usr/local/etc/rc.d/stunnel.sh start 2>/dev/null"); +} +function stunnel_save_cert($config) { + $GLOBALS['config']['installedpackages']['stunnelcerts']['savemsg']=''; + if(isset($_POST['id'])) { +# echo "<pre>"; +# print_r($_POST); +# echo "</pre>"; + + if(!$_POST['cert_chain']) { + $GLOBALS['config']['installedpackages']['stunnelcerts']['savemsg'].="Certificate chain must be specified!<br>"; + } if(!$_POST['cert_key']) { + $GLOBALS['config']['installedpackages']['stunnelcerts']['savemsg'].="RSA Key must be specified!<br>"; + } + if($_POST['cert_chain'] and $_POST['cert_key']) { + $_cert=openssl_x509_parse($_POST['cert_chain']); +# echo("<pre>"); +# print_r($_cert); +# echo("</pre>"); + if($_cert['hash']) { + if(openssl_x509_check_private_key($_POST['cert_chain'], $_POST['cert_key'])) { + file_put_contents('/usr/local/etc/stunnel/'.$_cert['hash'].'.key', + $_POST['cert_key']); + file_put_contents('/usr/local/etc/stunnel/'.$_cert['hash'].'.chain', + $_POST['cert_chain']); + file_put_contents('/usr/local/etc/stunnel/'.$_cert['hash'].'.pem', + $_POST['cert_key']."\n".$_POST['cert_chain']); + system('chown stunnel:stunnel /usr/local/etc/stunnel/*'); + chmod('/usr/local/etc/stunnel/'.$_cert['hash'].'.key', 0600); + chmod('/usr/local/etc/stunnel/'.$_cert['hash'].'.pem', 0600); + + $_POST['filename']=$_cert['hash']; + $_POST['expiry_raw']=$_cert['validTo_time_t']; + $_POST['expiry']=date('Y-m-d', $_cert['validTo_time_t']); + $_POST['subject']=$_cert['name']; + } else { + $GLOBALS['config']['installedpackages']['stunnelcerts']['savemsg'].="Certificate and key do not match!<br>"; + $_POST['filename']=''; + } + } else { + $GLOBALS['config']['installedpackages']['stunnelcerts']['savemsg'].="Couldn't parse certificate!<br>"; + $_POST['expiry_raw']=''; + $_POST['expiry']=''; + $_POST['subject']=''; + $_POST['filename']=''; + } + } + $_POST['cert_key']=base64_encode($_POST['cert_key']); + $_POST['cert_chain']=base64_encode($_POST['cert_chain']); + $_fname=$GLOBALS['config']['installedpackages']['stunnelcerts']['config'][$_POST['id']]['filename']; + if($_fname and $_fname!=$_POST['filename']) { + unlink_if_exists('/usr/local/etc/stunnel/'.$_fname.'.chain'); + unlink_if_exists('/usr/local/etc/stunnel/'.$_fname.'.key'); + unlink_if_exists('/usr/local/etc/stunnel/'.$_fname.'.pem'); + } + } +} + +function stunnel_install() { + safe_mkdir("/usr/local/etc/stunnel"); + system("/usr/bin/openssl req -new -x509 -days 365 -nodes -out /usr/local/etc/stunnel/stunnel.pem -keyout /usr/local/etc/stunnel/stunnel.pem 2>/dev/null"); + chmod("/usr/local/etc/stunnel/stunnel.pem", 0600); + make_dirs("/var/tmp/stunnel/var/tmp/run/stunnel"); + system("/usr/sbin/chown -R stunnel:stunnel /var/tmp/stunnel"); + $_rcfile['file']='stunnel.sh'; + $_rcfile['start'].="/usr/local/bin/stunnel /usr/local/etc/stunnel/stunnel.conf \n\t"; + $_rcfile['stop'].="killall stunnel \n\t"; + write_rcfile($_rcfile); + unlink_if_exists("/usr/local/etc/rc.d/stunnel"); + + conf_mount_rw(); + config_lock(); + $fout = fopen("/usr/local/etc/stunnel/stunnel.conf","w"); + fwrite($fout, "cert = /usr/local/etc/stunnel/stunnel.pem \n"); + fwrite($fout, "chroot = /var/tmp/stunnel \n"); + fwrite($fout, "setuid = stunnel \n"); + fwrite($fout, "setgid = stunnel \n"); + foreach($config['installedpackages']['stunnel']['config'] as $pkgconfig) { + fwrite($fout, "\n[" . $pkgconfig['description'] . "]\n"); + if($pkgconfig['sourceip']) fwrite($fout, "local = " . $pkgconfig['sourceip'] . "\n"); + fwrite($fout, "accept = " . $pkgconfig['localip'] . ":" . $pkgconfig['localport'] . "\n"); + fwrite($fout, "connect = " . $pkgconfig['redirectip'] . ":" . $pkgconfig['redirectport'] . "\n"); + fwrite($fout, "TIMEOUTclose = 0\n\n"); + } + fclose($fout); + conf_mount_ro(); + config_unlock(); +} + +function stunnel_deinstall() { + rmdir_recursive("/var/tmp/stunnel"); + rmdir_recursive("/usr/local/etc/stunnel*"); + unlink_if_exists("/usr/local/etc/rc.d/stunnel.sh"); +} + +?>
\ No newline at end of file diff --git a/config/stunnel/stunnel_certs.xml b/config/stunnel/stunnel_certs.xml new file mode 100644 index 00000000..3d7cc3fa --- /dev/null +++ b/config/stunnel/stunnel_certs.xml @@ -0,0 +1,147 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE packagegui SYSTEM "./schema/packages.dtd"> +<?xml-stylesheet type="text/xsl" href="./xsl/package.xsl"?> +<packagegui> + <copyright> + <![CDATA[ +/* $Id$ */ +/* ========================================================================== */ +/* + stunnel.xml + part of pfSense (http://www.pfSense.com) + Copyright (C) 2007-2008 Scott Ullrich + All rights reserved. + */ +/* ========================================================================== */ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + */ +/* ========================================================================== */ + ]]> + </copyright> + <description>Stunnel certificates</description> + <requirements>Describe your package requirements here</requirements> + <faq>Currently there are no FAQ items provided.</faq> + <name>stunnelcerts</name> + <version>4.18</version> + <title>Services: Secure Tunnel - Certificates</title> + <!-- configpath gets expanded out automatically and config items will be + stored in that location --> + <configpath>['installedpackages']['package']['$packagename']['configuration']</configpath> + + <tabs> + <tab> + <text>Tunnels</text> + <url>/pkg.php?xml=stunnel.xml</url> + </tab> + <tab> + <text>Certificates</text> + <url>/pkg.php?xml=stunnel_certs.xml</url> + <active/> + </tab> + </tabs> + + <!-- adddeleteeditpagefields items will appear on the first page where you can add / delete or edit + items. An example of this would be the nat page where you add new nat redirects --> + <adddeleteeditpagefields> + <columnitem> + <fielddescr>Description</fielddescr> + <fieldname>description</fieldname> + </columnitem> + <columnitem> + <fielddescr>Subject</fielddescr> + <fieldname>subject</fieldname> + </columnitem> +<!-- <columnitem> + <fielddescr>Valid until</fielddescr> + <fieldname>expiry</fieldname> + </columnitem> --> + <columnitem> + <fielddescr>Status</fielddescr> + <fieldname>status</fieldname> + </columnitem> + + </adddeleteeditpagefields> + <!-- fields gets invoked when the user adds or edits a item. the following items + will be parsed and rendered for the user as a gui with input, and selectboxes. --> + <fields> + <field> + <fielddescr>Description</fielddescr> + <fieldname>description</fieldname> + <description>Enter a (short) description for this certificate</description> + <type>input</type> + </field> + <field> + <fielddescr>Certificate filename</fielddescr> + <fieldname>filename</fieldname> + <description>File name of certificate (read-only; updated on save). Extensions (.pem, .chain, .key) are added automatically.</description> + <type>input</type> + </field> + <field> + <fielddescr>Certificate subject</fielddescr> + <fieldname>subject</fieldname> + <description>Certificate subject (read-only; updated on save)</description> + <type>input</type> + <size>50</size> + </field> + <field> + <fielddescr>Certificate valid until</fielddescr> + <fieldname>expiry</fieldname> + <description>The certificate will expire on this date, and will no longer work.</description> + <type>input</type> + </field> + <field> + <fielddescr>RSA private key</fielddescr> + <fieldname>cert_key</fieldname> + <description>RSA private key used for certificate. Do not change for existing certificates!<br> + <b>Leave blank to automatically create key and certificate signing request on save.</b></description> + <type>textarea</type> + <rows>7</rows> + <cols>65</cols> + </field> + <field> + <fielddescr>Certificate chain</fielddescr> + <fieldname>cert_chain</fieldname> + <description>Full certificate chain; root certificate on top, then any intermediates, server certificate at the end.<br> + <b>Full chain required for private or EV certificates!</b></description> + <type>textarea</type> + <rows>7</rows> + <cols>65</cols> + </field> + </fields> + + <include_file>/usr/local/pkg/stunnel.inc</include_file> + <custom_add_php_command> + stunnel_save_cert($config); + stunnel_save($config); + </custom_add_php_command> + <custom_php_command_before_form> + stunnel_printcsr(); + </custom_php_command_before_form> + <custom_php_after_form_command> + stunnel_disablefields(); + </custom_php_after_form_command> + <custom_delete_php_command> + stunnel_delete($config); + </custom_delete_php_command> + +</packagegui> diff --git a/pkg_config.7.xml b/pkg_config.7.xml index 4404c3ac..449c30db 100755 --- a/pkg_config.7.xml +++ b/pkg_config.7.xml @@ -449,7 +449,7 @@ <category>Network Management</category> <depends_on_package_base_url>http://files.pfsense.org/packages/7/All/</depends_on_package_base_url> <depends_on_package>stunnel-4.25.tbz</depends_on_package> - <version>4.25.2</version> + <version>4.30.0</version> <status>Stable</status> <pkginfolink>http://doc.pfsense.org/index.php/Stunnel_package</pkginfolink> <required_version>1.2.1</required_version> |