aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config/stunnel.xml107
-rw-r--r--config/stunnel/stunnel.inc232
-rw-r--r--config/stunnel/stunnel_certs.xml147
-rwxr-xr-xpkg_config.7.xml2
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!&lt;br&gt;
+ &lt;b&gt;Leave blank to automatically create key and certificate signing request on save.&lt;/b&gt;</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.&lt;br&gt;
+ &lt;b&gt;Full chain required for private or EV certificates!&lt;/b&gt;</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>