diff --git a/src/etc/inc/plugins.inc.d/openvpn.inc b/src/etc/inc/plugins.inc.d/openvpn.inc
index f15c9c8cf..79112efb7 100644
--- a/src/etc/inc/plugins.inc.d/openvpn.inc
+++ b/src/etc/inc/plugins.inc.d/openvpn.inc
@@ -666,6 +666,7 @@ function openvpn_reconfigure($mode, $settings, $device_only = false)
}
if (!empty($settings['authmode'])) {
$conf .= "auth-user-pass-verify \"/usr/local/opnsense/scripts/openvpn/ovpn_event.py '{$vpnid}'\" via-env\n";
+ $conf .= "learn-address \"/usr/local/opnsense/scripts/openvpn/ovpn_event.py '{$vpnid}'\"\n";
}
break;
}
diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/AliasController.php b/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/AliasController.php
index d17dede2b..3d16ea6f6 100644
--- a/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/AliasController.php
+++ b/src/opnsense/mvc/app/controllers/OPNsense/Firewall/Api/AliasController.php
@@ -66,13 +66,32 @@ class AliasController extends ApiMutableModelControllerBase
$filter_funct
);
- // append category uuid's so we can use these in the frontend
- $tmp = [];
+ /**
+ * remap some source data from the model as searchBase() is not able to distinct this.
+ * - category uuid's
+ * - unix group id's to names in content fields
+ */
+ $categories = [];
+ $types = [];
foreach ($this->getModel()->aliases->alias->iterateItems() as $key => $alias) {
- $tmp[$key] = !empty((string)$alias->categories) ? explode(',', (string)$alias->categories) : [];
+ $categories[$key] = !empty((string)$alias->categories) ? explode(',', (string)$alias->categories) : [];
+ $types[$key] = (string)$alias->type;
}
+ $group_mapping = null;
foreach ($result['rows'] as &$record) {
- $record['categories_uuid'] = $tmp[$record['uuid']];
+ $record['categories_uuid'] = $categories[$record['uuid']];
+ if ($types[$record['uuid']] == 'authgroup') {
+ if ($group_mapping === null) {
+ $group_mapping = $this->listUserGroupsAction();
+ }
+ $groups = [];
+ foreach (explode(',', $record['content']) as $grp) {
+ if (isset($group_mapping[$grp])) {
+ $groups[] = $group_mapping[$grp]['name'];
+ }
+ }
+ $record['content'] = implode(',', $groups);
+ }
}
return $result;
@@ -266,6 +285,29 @@ class AliasController extends ApiMutableModelControllerBase
return $result;
}
+ /**
+ * list user groups
+ * @return array user groups
+ */
+ public function listUserGroupsAction()
+ {
+ $result = [];
+ $cnf = Config::getInstance()->object();
+ if (isset($cnf->system->group)) {
+ foreach ($cnf->system->group as $group) {
+ $name = (string)$group->name;
+ if ($name != 'all') {
+ $result[(string)$group->gid] = [
+ "name" => $name,
+ "gid" => (string)$group->gid
+ ];
+ }
+ }
+ ksort($result);
+ }
+ return $result;
+ }
+
/**
* list network alias types
* @return array indexed by country alias name
diff --git a/src/opnsense/mvc/app/models/OPNsense/Firewall/Alias.xml b/src/opnsense/mvc/app/models/OPNsense/Firewall/Alias.xml
index 78a4284bd..9997dc8f3 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Firewall/Alias.xml
+++ b/src/opnsense/mvc/app/models/OPNsense/Firewall/Alias.xml
@@ -38,6 +38,7 @@
MAC address
BGP ASN
Dynamic IPv6 Host
+ OpenVPN group
Internal (automatic)
External (advanced)
diff --git a/src/opnsense/mvc/app/models/OPNsense/Firewall/FieldTypes/AliasContentField.php b/src/opnsense/mvc/app/models/OPNsense/Firewall/FieldTypes/AliasContentField.php
index 54203f08f..413e1bc27 100644
--- a/src/opnsense/mvc/app/models/OPNsense/Firewall/FieldTypes/AliasContentField.php
+++ b/src/opnsense/mvc/app/models/OPNsense/Firewall/FieldTypes/AliasContentField.php
@@ -32,6 +32,7 @@ use OPNsense\Base\FieldTypes\BaseField;
use OPNsense\Base\Validators\CallbackValidator;
use OPNsense\Phalcon\Filter\Validation\Validator\Regex;
use OPNsense\Phalcon\Filter\Validation\Validator\ExclusionIn;
+use OPNsense\Core\Config;
use Phalcon\Messages\Message;
use OPNsense\Firewall\Util;
@@ -54,7 +55,12 @@ class AliasContentField extends BaseField
/**
* @var array list of known countries
*/
- private static $internalCountryCodes = array();
+ private static $internalCountryCodes = [];
+
+ /**
+ * @var array list of known user groups
+ */
+ private static $internalAuthGroups = [];
/**
* item separator
@@ -117,6 +123,23 @@ class AliasContentField extends BaseField
return self::$internalCountryCodes;
}
+ /**
+ * fetch valid user groups
+ * @return array valid groups
+ */
+ public function getUserGroups()
+ {
+ if (empty(self::$internalAuthGroups)) {
+ $cnf = Config::getInstance()->object();
+ if (isset($cnf->system->group)) {
+ foreach ($cnf->system->group as $group) {
+ self::$internalAuthGroups[(string)$group->gid] = (string)$group->name;
+ }
+ }
+ }
+ return self::$internalAuthGroups;
+ }
+
/**
* Validate port alias options
* @param array $data to validate
@@ -304,6 +327,25 @@ class AliasContentField extends BaseField
return $messages;
}
+ /**
+ * Validate (partial) mac address options
+ * @param array $data to validate
+ * @return array
+ * @throws \OPNsense\Base\ModelException
+ */
+ private function validateGroups($data)
+ {
+ $messages = [];
+ $all_groups = $this->getUserGroups();
+ foreach ($this->getItems($data) as $group) {
+ if (!isset($all_groups[$group])) {
+ $messages[] = sprintf(gettext('Entry "%s" is not a valid group id.'), $group);
+ }
+ }
+ return $messages;
+ }
+ //
+
/**
* retrieve field validators for this field type
* @return array
@@ -361,6 +403,12 @@ class AliasContentField extends BaseField
}
]);
break;
+ case "authgroup":
+ $validators[] = new CallbackValidator(["callback" => function ($data) {
+ return $this->validateGroups($data);
+ }
+ ]);
+ break;
default:
break;
}
diff --git a/src/opnsense/mvc/app/views/OPNsense/Firewall/alias.volt b/src/opnsense/mvc/app/views/OPNsense/Firewall/alias.volt
index 9dadb2abb..fe1d5848b 100644
--- a/src/opnsense/mvc/app/views/OPNsense/Firewall/alias.volt
+++ b/src/opnsense/mvc/app/views/OPNsense/Firewall/alias.volt
@@ -96,7 +96,7 @@
$("#grid-aliases").bootgrid().on("loaded.rs.jquery.bootgrid", function (e){
// network content field should only contain valid aliases, we need to fetch them separately
// since the form field misses context
- ajaxGet("/api/firewall/alias/listNetworkAliases", {}, function(data){
+ ajaxGet("/api/firewall/alias/list_network_aliases", {}, function(data){
$("#network_content").empty();
$.each(data, function(alias, value) {
let $opt = $("").val(alias).text(value.name);
@@ -250,14 +250,30 @@
});
});
+ /**
+ * fetch user groups
+ **/
+ ajaxGet("/api/firewall/alias/list_user_groups", {}, function(data){
+ $("#authgroup_content").empty();
+ $.each(data, function(alias, value) {
+ let $opt = $("").val(alias).text(value.name);
+ $opt.data('subtext', value.description);
+ $("#authgroup_content").append($opt);
+ });
+ $("#authgroup_content").selectpicker('refresh');
+ });
+
+
/**
* hook network group type changes, replicate content
*/
- $("#network_content").change(function(){
+ $("#network_content, #authgroup_content").change(function(){
+ let target = $(this);
+ console.log(target);
let $content = $("#alias\\.content");
$content.unbind('tokenize:tokens:change');
$content.tokenize2().trigger('tokenize:clear');
- $("#network_content").each(function () {
+ target.each(function () {
$.each($(this).val(), function(key, item){
$content.tokenize2().trigger('tokenize:tokens:add', item);
});
@@ -270,7 +286,6 @@
});
});
-
/**
* Type selector, show correct type input.
*/
@@ -280,6 +295,10 @@
$("#row_alias\\.interface").hide();
$("#copy-paste").hide();
switch ($(this).val()) {
+ case 'authgroup':
+ $("#alias_type_authgroup").show();
+ $("#alias\\.proto").selectpicker('hide');
+ break;
case 'geoip':
$("#alias_type_geoip").show();
$("#alias\\.proto").selectpicker('show');
@@ -321,24 +340,18 @@
*/
$("#alias\\.content").change(function(){
var items = $(this).val();
- $(".geoip_select").each(function(){
- var geo_item = $(this);
- geo_item.val([]);
- for (var i=0; i < items.length; ++i) {
- geo_item.find('option[value="' + $.escapeSelector(items[i]) + '"]').prop("selected", true);
- }
-
+ ['#authgroup_content', '#network_content', '.geoip_select'].forEach(function(target){
+ console.log(target);
+ $(target).each(function(){
+ var content_item = $(this);
+ content_item.val([]);
+ for (var i=0; i < items.length; ++i) {
+ content_item.find('option[value="' + $.escapeSelector(items[i]) + '"]').prop("selected", true);
+ }
+ });
+ $(target).selectpicker('refresh');
});
- $(".geoip_select").selectpicker('refresh');
geoip_update_labels();
- $("#network_content").each(function(){
- var network_item = $(this);
- network_item.val([]);
- for (var i=0; i < items.length; ++i) {
- network_item.find('option[value="' + $.escapeSelector(items[i]) + '"]').prop("selected", true);
- }
- });
- $("#network_content").selectpicker('refresh');
});
/**
@@ -574,7 +587,7 @@
-