From ddbbadedcbfa8266b6af49b4e9f6005b447f1483 Mon Sep 17 00:00:00 2001 From: bergware Date: Sat, 29 Apr 2023 16:57:52 +0200 Subject: [PATCH] Shares: enhancements and removal of csrf exposure --- plugins/dynamix/CacheDevices.page | 14 +++-- plugins/dynamix/DeviceInfo.page | 14 +++-- plugins/dynamix/DiskList.page | 38 ++++++------- plugins/dynamix/ShareList.page | 64 ++++++++++++--------- plugins/dynamix/include/DiskList.php | 51 ++++++++--------- plugins/dynamix/include/ShareList.php | 81 ++++++++++++++------------- 6 files changed, 136 insertions(+), 126 deletions(-) diff --git a/plugins/dynamix/CacheDevices.page b/plugins/dynamix/CacheDevices.page index 9cb213c2d..68616dd2a 100644 --- a/plugins/dynamix/CacheDevices.page +++ b/plugins/dynamix/CacheDevices.page @@ -16,8 +16,11 @@ Cond="($pool_devices || $var['fsState']=='Stopped')" */ ?> @@ -29,9 +32,9 @@ table.divider{margin-top:20px} - @@ -44,13 +27,42 @@ i.fa-fw{margin-right:2px} _(Name)__(Comment)__(SMB)__(NFS)__(Storage)__(Size)__(Free)_ -

- - -':' disabled>User shares must be enabled to add shares.'?> - - - -

+ +
+ + + +
:share_list_help: + + diff --git a/plugins/dynamix/include/DiskList.php b/plugins/dynamix/include/DiskList.php index 6479da36b..f8bd58e40 100644 --- a/plugins/dynamix/include/DiskList.php +++ b/plugins/dynamix/include/DiskList.php @@ -13,24 +13,27 @@ "._('There are no exportable disk shares').""; +if (!$disks) die($nodisks); + +// GUI settings +extract(parse_plugin_cfg('dynamix',true)); // Display export settings function disk_share_settings($protocol,$share) { @@ -38,40 +41,35 @@ function disk_share_settings($protocol,$share) { if ($protocol!='yes' || _var($share,'export')=='-') return "-"; return (_var($share,'export')=='e') ? _(ucfirst(_var($share,'security'))) : ''._(ucfirst(_var($share,'security'))).''; } - function globalInclude($name) { global $var; return substr($name,0,4)!='disk' || !_var($var,'shareUserInclude') || strpos(_var($var,'shareUserInclude').",","$name,")!==false; } - function shareInclude($name) { global $include; return !$include || substr($name,0,4)!='disk' || strpos("$include,", "$name,")!==false; } - function sharesOnly($disk) { return in_array(_var($disk,'type'),['Data','Cache']) && _var($disk,'exportable')=='yes'; } - // filter disk shares $disks = array_filter($disks,'sharesOnly'); -// Compute all disk shares & check encryption +// Compute disk shares & check encryption $crypto = false; foreach ($disks as $name => $disk) { - if ($compute=='yes') exec("webGui/scripts/disk_size ".escapeshellarg($name)." ssz2"); + if ($all!=0 && (!$compute || $compute==$name)) exec("/$docroot/webGui/scripts/disk_size ".escapeshellarg($name)." ssz2"); $crypto |= strpos(_var($disk,'fsType'),'luks:')!==false; } - // global shares include/exclude $myDisks = array_filter(array_diff(array_keys($disks), explode(',',_var($var,'shareUserExclude'))), 'globalInclude'); // Share size per disk $ssz2 = []; -if ($fill) - foreach (glob("state/*.ssz2", GLOB_NOSORT) as $entry) $ssz2[basename($entry, ".ssz2")] = file($entry,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); -else +if ($all==0) exec("rm -f /var/local/emhttp/*.ssz2"); +else + foreach (glob("state/*.ssz2",GLOB_NOSORT) as $entry) $ssz2[basename($entry,'.ssz2')] = file($entry,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); // Build table $row = 0; @@ -95,7 +93,7 @@ foreach ($disks as $name => $disk) { echo "",disk_share_settings(_var($var,'shareNFSEnabled'), $sec_nfs[$name]),""; $cmd="/webGui/scripts/disk_size&arg1=$name&arg2=ssz2"; $type = _var($disk,'rotational') ? _('HDD') : _('SSD'); - if (array_key_exists($name, $ssz2)) { + if (array_key_exists($name,$ssz2)) { echo "$type"; echo "",my_scale(_var($disk,'fsSize',0)*1024, $unit)," $unit"; echo "",my_scale(_var($disk,'fsFree',0)*1024, $unit)," $unit"; @@ -103,28 +101,23 @@ foreach ($disks as $name => $disk) { foreach ($ssz2[$name] as $entry) { [$sharename,$sharesize] = my_explode('=',$entry); if ($sharename=='share.total') continue; - $include = _var($shares[$sharename],'include'); $inside = in_array(_var($disk,'name'), array_filter(array_diff($myDisks, explode(',',_var($shares[$sharename],'exclude'))), 'shareInclude')); echo "" : "warning'>"); - echo " $sharename"; + echo " $sharename"; echo "",($inside ? "" : ""._('Share is outside the list of designated disks').""),""; echo ""; echo ""; echo ""; - echo "",my_scale($sharesize, $unit)," $unit"; - echo "",my_scale(_var($disk,'fsFree',0)*1024, $unit)," $unit"; + echo "",my_scale($sharesize, $unit)," $unit"; + echo "",my_scale(_var($disk,'fsFree',0)*1024, $unit)," $unit"; echo ""; } } else { echo "$type"; - echo "",_('Compute'),"..."; + echo "",_('Compute'),"..."; echo "",my_scale(_var($disk,'fsFree',0)*1024, $unit)," $unit"; echo ""; } } -if ($row==0) { - echo "",_('There are no exportable disk shares'),""; -} +if ($row==0) echo $nodisks; ?> diff --git a/plugins/dynamix/include/ShareList.php b/plugins/dynamix/include/ShareList.php index 056f756b6..1e50ea855 100644 --- a/plugins/dynamix/include/ShareList.php +++ b/plugins/dynamix/include/ShareList.php @@ -14,7 +14,18 @@ $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp'; if (isset($_POST['scan'])) { - die((new \FilesystemIterator("/mnt/user/{$_POST['scan']}"))->valid() ? '0' : '1'); + die((new FilesystemIterator("/mnt/user/{$_POST['scan']}"))->valid() ? '0' : '1'); +} +if (isset($_POST['cleanup'])) { + $n = 0; + // active shares + $shares = array_keys(parse_ini_file('state/shares.ini',true)); + // stored shares + foreach (glob("/boot/config/shares/*.cfg",GLOB_NOSORT) as $name) { + if (!in_array(basename($name,'.cfg'),$shares)) {$n++; unlink($name);} + } + // return number of deleted files + die((string)$n); } // add translations @@ -22,27 +33,26 @@ $_SERVER['REQUEST_URI'] = 'shares'; require_once "$docroot/webGui/include/Translations.php"; require_once "$docroot/webGui/include/Helpers.php"; +$compute = rawurldecode(_var($_POST,'compute')); +$path = rawurldecode(_var($_POST,'path')); +$all = _var($_POST,'all'); + $shares = parse_ini_file('state/shares.ini',true); $disks = parse_ini_file('state/disks.ini',true); $var = parse_ini_file('state/var.ini'); $sec = parse_ini_file('state/sec.ini',true); $sec_nfs = parse_ini_file('state/sec_nfs.ini',true); -$compute = unscript(_var($_GET,'compute')); -$path = unscript(_var($_GET,'path')); -$fill = unscript(_var($_GET,'fill')); -$display = []; -$display['scale'] = unscript(_var($_GET,'scale')); -$display['number'] = unscript(_var($_GET,'number','.,')); -$display['raw'] = unscript(_var($_GET,'raw')); +// exit when no shares +$noshares = ""._('There are no exportable user shares').""; +if (!$shares) die($noshares); + +// GUI settings +extract(parse_plugin_cfg('dynamix',true)); $pools_check = pools_filter(cache_filter($disks)); $pools = implode(',', $pools_check); -if (!$shares) { - echo "",_('There are no exportable user shares'),""; - exit; -} // Natural sorting of share names uksort($shares,'strnatcasecmp'); @@ -52,33 +62,29 @@ function user_share_settings($protocol,$share) { if ($protocol!='yes' || $share['export']=='-') return "-"; return ($share['export']=='e') ? _(ucfirst($share['security'])) : ''._(ucfirst($share['security'])).''; } - function globalInclude($name) { global $var; return substr($name,0,4)!='disk' || !$var['shareUserInclude'] || strpos("{$var['shareUserInclude']},","$name,")!==false; } - function shareInclude($name) { global $include; return !$include || substr($name,0,4)!='disk' || strpos("$include,", "$name,")!==false; } - -// Compute all user shares & check encryption +// Compute user shares & check encryption $crypto = false; foreach ($shares as $name => $share) { - if ($compute=='yes') exec("webGui/scripts/share_size ".escapeshellarg($name)." ssz1 ".escapeshellarg($pools)); - $crypto |= $share['luksStatus']>0; + if ($all!=0 && (!$compute || $compute==$name)) exec("$docroot/webGui/scripts/share_size ".escapeshellarg($name)." ssz1 ".escapeshellarg($pools)); + $crypto |= _var($share,'luksStatus',0)>0; } - // global shares include/exclude $myDisks = array_filter(array_diff(array_keys($disks), explode(',',$var['shareUserExclude'])), 'globalInclude'); // Share size per disk $ssz1 = []; -if ($fill) - foreach (glob("state/*.ssz1", GLOB_NOSORT) as $entry) $ssz1[basename($entry, ".ssz1")] = parse_ini_file($entry); -else +if ($all==0) exec("rm -f /var/local/emhttp/*.ssz1"); +else + foreach (glob("state/*.ssz1",GLOB_NOSORT) as $entry) $ssz1[basename($entry,'.ssz1')] = parse_ini_file($entry); // Build table $row = 0; @@ -95,19 +101,16 @@ foreach ($shares as $name => $share) { case 2: $luks = ""._('Some or all files unencrypted').""; break; default: $luks = ""._('Unknown encryption state').""; break; } else $luks = ""; - echo ""; + echo ""; echo "$help$luks",compress($name),""; + echo rawurlencode($name),"\" onclick=\"$.cookie('one','tab1')\">",compress($name),""; echo "{$share['comment']}"; echo "",user_share_settings($var['shareSMBEnabled'], $sec[$name]),""; echo "",user_share_settings($var['shareNFSEnabled'], $sec_nfs[$name]),""; - $cmd="/webGui/scripts/share_size&arg1=".urlencode($name)."&arg2=ssz1&arg3=".urlencode($pools); - /* Check for non existent pool device. */ - if ($share['cachePool']) { - if (! in_array($share['cachePool'], $pools_check)) { - $share['useCache'] = "no"; - } - } + + // Check for non existent pool device + if (isset($share['cachePool']) && !in_array($share['cachePool'], $pools_check)) $share['useCache'] = "no"; + switch ($share['useCache']) { case 'no': $cache = ""._('Array')."".sprintf(_('Primary storage %s'),_('Array')).""; @@ -123,7 +126,7 @@ foreach ($shares as $name => $share) { $cache = "$exclusive".compress(my_disk($share['cachePool'],$display['raw']))."".sprintf(_('Primary storage %s'),$share['cachePool']).($exclusive ? ", "._('Exclusive access') : "").""; break; } - if (array_key_exists($name, $ssz1)) { + if (array_key_exists($name,$ssz1)) { echo "$cache"; echo "",my_scale($ssz1[$name]['disk.total'], $unit)," $unit"; echo "",my_scale($share['free']*1024, $unit)," $unit"; @@ -133,23 +136,21 @@ foreach ($shares as $name => $share) { $include = $share['include']; $inside = in_array($diskname, array_filter(array_diff($myDisks, explode(',',$share['exclude'])), 'shareInclude')); echo "" : "warning'>"); - echo " ",_(my_disk($diskname,$display['raw']),3),""; + echo " ",_(my_disk($diskname,$display['raw']),3),""; echo "",($inside ? "" : ""._('Share is outside the list of designated disks').""),""; echo ""; echo ""; echo ""; - echo "",my_scale($disksize, $unit)," $unit"; - echo "",my_scale($disks[$diskname]['fsFree']*1024, $unit)," $unit"; + echo "",my_scale($disksize, $unit)," $unit"; + echo "",my_scale($disks[$diskname]['fsFree']*1024, $unit)," $unit"; echo ""; } } else { echo "$cache"; - echo "",_('Compute'),"..."; + echo "",_('Compute'),"..."; echo "",my_scale($share['free']*1024, $unit)," $unit"; echo ""; } } -if ($row==0) { - echo "",_('There are no exportable user shares'),""; -} +if ($row==0) echo $noshares; +?>