#!/bin/sh
#called from dir2sfs, bring up a gui to choose security settings.
#code copied from /usr/local/easy_containers/easy-containers
#passed param is name of container.
#181028 rename 'repository' folder to 'releases'.
#181122 q*.sfs renamed to easy*.sfs

[ ! $1 ] && exit 1
[ ! -f /tmp/sfsget/security-overrides ] && exit 2
EC_CREATE="$1"
export LANG=C
mkdir -p /tmp/easy_containers

###defaults for the security checkboxes###
#if xorg started with "-nolisten local" then cannot use abstract socket...
#well, could be running container on other systems, but set this according to current host...
XORG_ABSTRACT_ALLOW='true'
grep '^/usr/bin/xinit .*nolisten local' /usr/bin/xwin >/dev/null
[ $? -eq 0 ] && XORG_ABSTRACT_ALLOW='false'

set_defaults_func() {
 EXEin="$1"
 . /usr/local/easy_containers/templates/defaults/configuration
 if [ -f /usr/local/easy_containers/templates/${EC_CREATE}/configuration ];then
  . /usr/local/easy_containers/templates/${EC_CREATE}/configuration
 fi
 #dir2sfs will have written some overrides here:
 . /tmp/sfsget/security-overrides
 
 #xorg...
 [ "$XORG_ABSTRACT_ALLOW" == "false" ] && [ "$EC_XSOCKET" == "abstract" ] && EC_XSOCKET='unix'
 case "$EC_XSOCKET" in
  abstract)
   echo 'true' > /tmp/easy_containers/chkbx-XSOCKET_ABSTRACT
   echo 'false' > /tmp/easy_containers/chkbx-XSOCKET_UNIX
   echo 'false' > /tmp/easy_containers/chkbx-XSOCKET_PIPE
  ;;
  pipe)
   echo 'false' > /tmp/easy_containers/chkbx-XSOCKET_ABSTRACT
   echo 'false' > /tmp/easy_containers/chkbx-XSOCKET_UNIX
   echo 'true' > /tmp/easy_containers/chkbx-XSOCKET_PIPE
  ;;
  *) #unix
   echo 'false' > /tmp/easy_containers/chkbx-XSOCKET_ABSTRACT
   echo 'true' > /tmp/easy_containers/chkbx-XSOCKET_UNIX
   echo 'false' > /tmp/easy_containers/chkbx-XSOCKET_PIPE
  ;;
 esac
 case "$EC_XSERVER" in
  xephyr)
   echo 'false' > /tmp/easy_containers/chkbx-XSERVER_XORG
   echo 'true' > /tmp/easy_containers/chkbx-XSERVER_XEPHYR
  ;;
  *) #xorg
   echo 'true' > /tmp/easy_containers/chkbx-XSERVER_XORG
   echo 'false' > /tmp/easy_containers/chkbx-XSERVER_XEPHYR
  ;;
 esac
 #namespaces...
 echo "$EC_NS_UNSHARE_MOUNT" > /tmp/easy_containers/chkbx-EC_NS_UNSHARE_MOUNT
 echo "$EC_NS_UNSHARE_UTS" > /tmp/easy_containers/chkbx-EC_NS_UNSHARE_UTS
 echo "$EC_NS_UNSHARE_IPC" > /tmp/easy_containers/chkbx-EC_NS_UNSHARE_IPC
 echo "$EC_NS_UNSHARE_NETWORK" > /tmp/easy_containers/chkbx-EC_NS_UNSHARE_NETWORK
 echo "$EC_NS_UNSHARE_PID" > /tmp/easy_containers/chkbx-EC_NS_UNSHARE_PID
 #echo 'true' > /tmp/easy_containers/chkbx-EC_NS_UNSHARE_USER
 #environment...
 echo "$EC_UNSHARE_ENV_VARS" > /tmp/easy_containers/chkbx-EC_UNSHARE_ENV_VARS
 echo "$EC_ENV_ZEUS" > /tmp/easy_containers/chkbx-EC_ENV_ZEUS
 #access...
 echo "$EC_ACCESS_NET" > /tmp/easy_containers/chkbx-EC_ACCESS_NET
 echo "$EC_ACCESS_SND" > /tmp/easy_containers/chkbx-EC_ACCESS_SND
 echo "$EC_ACCESS_FOLDER" > /tmp/easy_containers/chkbx-EC_ACCESS_FOLDER
 echo -n "$EC_ACCESS_FOLDER_PATH" > /tmp/easy_containers/entry-EC_ACCESS_FOLDER_PATH
 lastPATH="$EC_ACCESS_FOLDER_PATH"
 #capabilities...
 echo "$EC_CAP_system" > /tmp/easy_containers/chkbx-EC_CAP_system
 echo "$EC_CAP_file" > /tmp/easy_containers/chkbx-EC_CAP_file
 echo "$EC_CAP_network" > /tmp/easy_containers/chkbx-EC_CAP_network
 echo "$EC_CAP_module" > /tmp/easy_containers/chkbx-EC_CAP_module
 echo "$EC_CAP_resource" > /tmp/easy_containers/chkbx-EC_CAP_resource
 echo "$EC_CAP_mount" > /tmp/easy_containers/chkbx-EC_CAP_mount
} #end set_defaults_func
export -f set_defaults_func
############
set_defaults_func ${EC_CREATE}
############

M_close="$(gettext 'Close')"
M_help1="$(gettext 'Easy Containers is a nice GUI for creating and managing the running of apps in containers. Some useful notes:')

$(gettext 'A container is composed of a read-write folder layered on top of easy.sfs. The bottom layer is all of EasyOS, with all the builtin apps. Any one of these apps may be chosen to run in a container, however, currently only apps with a menu-entry are offered in the drop-down list.')

$(gettext 'User-installed packages are a problem, as they will have to be copied into the read-write layer of the container. If, for example, you install Firefox, and choose to run it in a container, all of the installed files of the Firefox package will be copied to the newly-created container. This is done automatically.')

$(gettext 'A caveat to the above, only applies to a package installed via the Package Manager, which maintains lists of installed files. A manually-installed package, such as one compiled from source, cannot automatically be containerized.')"
export DLG_HELP1="<window resizable=\"false\" title=\"$(gettext 'Help: Easy Containers')\" icon-name=\"gtk-index\" window_position=\"1\"><vbox><text use-markup=\"true\"><label>\"${M_help1}\"</label><variable>DLG_HELP1</variable></text><hbox><button><label>${M_close}</label><action type=\"closewindow\">DLG_HELP1</action></button></hbox></vbox></window>"

M_helpcap="$(gettext 'In Easy, the user runs as the <b>root</b> user (administrator), and the same is true in containers. Linux has a feature called <b>capabilities</b>, that can be used to restrict the rights of the root user. Easy has organized them into five categories, for ease-of-use:')

<b>$(gettext 'system')</b>
$(gettext 'Drop system administration permissions.')
<b>$(gettext 'file')</b>
$(gettext 'Prevent execution and modifications to files.')
<b>$(gettext 'network')</b>
$(gettext 'Drop network administration permissions. Note, tick the <i>network Namespace</i> checkbox to disable inheriting host network connection.')
<b>$(gettext 'module')</b>
$(gettext 'Drop kernel module loading/unloading and other admin.')
<b>$(gettext 'resource')</b>
$(gettext 'Drop system resource administration.')
<b>$(gettext 'mount')</b>
$(gettext 'Prevent mount and umount of filesystems.')

Note, for most applications it is OK to tick all of these."
export DLG_HELPcap="<window resizable=\"false\" title=\"$(gettext 'Help: Linux capabilities')\" icon-name=\"gtk-index\" window_position=\"1\"><vbox><text use-markup=\"true\"><label>\"${M_helpcap}\"</label><variable>DLG_HELPcap</variable></text><hbox><button><label>${M_close}</label><action type=\"closewindow\">DLG_HELPcap</action></button></hbox></vbox></window>"

M_helpns="$(gettext 'Linux namespaces are a mechanism to isolate some functionality of a container from the main system. There are six types:')

<b>$(gettext 'mount')</b>
$(gettext 'Mount points. Recommend do tick this.')
<b>$(gettext 'UTS')</b>
$(gettext 'Hostname and NIS domain name. May be ticked, however, do <i>not</i> tick if choose Pipe Xorg socket, as X apps will not run.')
<b>$(gettext 'IPC')</b>
$(gettext 'Inter Process Communication. Recommend do <i>not</i> tick this, as it will prevent X apps from running.')
<b>$(gettext 'network')</b>
$(gettext 'Network devices, stacks, ports. Tick this for more secure network and Internet connection.')
<b>$(gettext 'PID')</b>
$(gettext 'Process IDs. Ticking this will prevent the container from seeing the host-system PIDs. Recommended to always tick this.')
<b>$(gettext 'user')</b>
$(gettext 'User and group IDs. Easy Containers does not use this, as it was determined to be unnecessary, and even conflicting, with Linux capabilities.')"
export DLG_HELPns="<window resizable=\"false\" title=\"$(gettext 'Help: Linux namespaces')\" icon-name=\"gtk-index\" window_position=\"1\"><vbox><text use-markup=\"true\"><label>\"${M_helpns}\"</label><variable>DLG_HELPns</variable></text><hbox><button><label>${M_close}</label><action type=\"closewindow\">DLG_HELPns</action></button></hbox></vbox></window>"

M_helpxorg="$(gettext 'The X server is a potential security weakness, as an X app running in a container must use the system X server. The connection is via what is called a <i>socket</i>, and there are three ways of doing it:')

<b>$(gettext 'Unix Domain Socket')</b>
$(gettext 'This uses a path in the main filesystem, /tmp/.X11-unix, which would have to be visible from a container to be used by apps in the container.')

<b>$(gettext 'Abstract')</b>
$(gettext 'This does not require access to /tmp in the main filesystem, however, will not work if the X server started with <i>-nolisten local</i>.')

<b>$(gettext 'Pipe')</b>
$(gettext 'This is setup in the main filesyetm, with the <i>socat</i> utility, to connect TCP port 6000 to the Unix Domain Socket. This will work even if the X server is started with <i>-nolisten tcp -nolisten local</i>. However, Pipe will not work if the <i>mount Namespace</i> is unshared.')

<b>Xorg</b>
$(gettext 'Xorg is the X server used in the main filesystem. It can also be used in containers, with any of the above three socket methods.')

<b>Xephyr</b>
$(gettext 'Xephyr is a nested X server. It will display in its own window, and is the most secure option.')

<b>$(gettext 'Technical notes')</b>
$(gettext 'Xorg commandline start options can be found in /usr/bin/xwin')
$(gettext 'Xephyr commandline start options can be found in /root/Startup/xephyr')"
export DLG_HELPxorg="<window resizable=\"false\" title=\"$(gettext 'Help: X Server')\" icon-name=\"gtk-index\" window_position=\"1\"><vbox><text use-markup=\"true\"><label>\"${M_helpxorg}\"</label><variable>DLG_HELPxorg</variable></text><hbox><button><label>${M_close}</label><action type=\"closewindow\">DLG_HELPxorg</action></button></hbox></vbox></window>"

M_helpenv="<b>$(gettext 'unshare variables')</b>
$(gettext 'If you type <i>set</i> in a terminal, all of the environment variables will be listed. To reduce the number of these appearing in a container, tick the checkbox.')

<b>user zeus</b>
$(gettext 'Execution in container is as root user, however severely constrained, which is considered secure. However, if you wish, tick this checkbox to run as user <b>zeus</b> in the container, for even more security.')
<b>WARNING: only tick this when creating a new container. Also, some apps may not work.</b>

<b>$(gettext 'network')</b>
$(gettext 'Tick this if you want to have network (and Internet) access from within the container.')

<b>$(gettext 'sound')</b>
$(gettext 'Tick this for sound output from within the container.')

<b>$(gettext 'folder')</b>
$(gettext 'Tick the checkbox, then choose a folder that will have read-write access inside the container. It will be <b>/shared-folder</b> inside the container.')"
export DLG_HELPenv="<window resizable=\"false\" title=\"$(gettext 'Help: Environment & Access')\" icon-name=\"gtk-index\" window_position=\"1\"><vbox><text use-markup=\"true\"><label>\"${M_helpenv}\"</label><variable>DLG_HELPenv</variable></text><hbox><button><label>${M_close}</label><action type=\"closewindow\">DLG_HELPenv</action></button></hbox></vbox></window>"

#chooser for shared folder...
export DLG_CHOOSER="<window title=\"$(gettext 'Easy Containers')\" icon-name=\"gtk-convert\">
 <vbox>
  <text><label>$(gettext 'Choose a folder that will be shared inside container')</label></text>
  <chooser>
   <width>600</width>
   <height>400</height>
   <variable>PATHCHOOSER</variable>
   <default>${lastPATH}</default>
  </chooser>
  <hbox>
   <button ok>
     <action>echo -n \$PATHCHOOSER > /tmp/easy_containers/entry-EC_ACCESS_FOLDER_PATH</action>
     <action>refresh:ACCESS_FOLDER_PATH</action>
     <action function=\"closewindow\">DLG_CHOOSER</action>
   </button>
   <button cancel>
     <action function=\"closewindow\">DLG_CHOOSER</action>
   </button>
  </hbox>
 </vbox>
 <variable>DLG_CHOOSER</variable>
</window>"


export SFS_SEC_DLG="<window title=\"Container security\" icon-name=\"gtk-convert\">
<vbox>

     <notebook labels=\"Simple|Expert\">
      <vbox>
       <hbox>
        <text><label>Reset security settings to defaults:</label></text>
        <button>
         <label>Reset</label>
         <action>set_defaults_func \$EC_CREATE</action>
         <action>refresh:ENV_VARS</action>
         <action>refresh:ENV_ZEUS</action>
         <action>refresh:ACCESS_NET</action>
         <action>refresh:ACCESS_SND</action>
         <action>refresh:ACCESS_FOLDER</action>
         <action>refresh:ACCESS_FOLDER_PATH</action>
         <action>refresh:NS_MOUNT</action>
         <action>refresh:NS_UTS</action>
         <action>refresh:NS_IPC</action>
         <action>refresh:NS_NETWORK</action>
         <action>refresh:NS_PID</action>
         <action>refresh:XSERVER_XEPHYR</action>
         <action>refresh:XSERVER_XORG</action>
         <action>refresh:XSOCKET_ABSTRACT</action>
         <action>refresh:XSOCKET_PIPE</action>
         <action>refresh:XSOCKET_UNIX</action>
         <action>refresh:CAP_system</action>
         <action>refresh:CAP_file</action>
         <action>refresh:CAP_network</action>
         <action>refresh:CAP_module</action>
         <action>refresh:CAP_resource</action>
         <action>refresh:CAP_mount</action>
        </button>
       </hbox>
       <text><label>\"  \"</label></text>
       <text><label>more coming soon</label></text>
      </vbox>
      <vbox>
       <hbox>
        <vbox>
         <frame Environment>
          <checkbox><variable>ENV_VARS</variable><label>unshare variables</label><input file>/tmp/easy_containers/chkbx-EC_UNSHARE_ENV_VARS</input></checkbox>
          <checkbox><variable>ENV_ZEUS</variable><label>user zeus</label><input file>/tmp/easy_containers/chkbx-EC_ENV_ZEUS</input></checkbox>
         </frame>
         <frame Access>
          <checkbox><variable>ACCESS_NET</variable><label>network</label><input file>/tmp/easy_containers/chkbx-EC_ACCESS_NET</input></checkbox>
          <checkbox><variable>ACCESS_SND</variable><label>sound</label><input file>/tmp/easy_containers/chkbx-EC_ACCESS_SND</input></checkbox>
          <hbox>
           <checkbox>
            <variable>ACCESS_FOLDER</variable>
            <label>folder</label>
            <input file>/tmp/easy_containers/chkbx-EC_ACCESS_FOLDER</input>
           </checkbox>
           <text><label>\"  \"</label></text>
           <button>
            <input file>/usr/local/lib/X11/mini-icons/mini-folder.xpm</input>
            <action type=\"launch\">DLG_CHOOSER</action>
           </button>
          </hbox>
          <entry>
           <variable>ACCESS_FOLDER_PATH</variable>
           <input file>/tmp/easy_containers/entry-EC_ACCESS_FOLDER_PATH</input>
          </entry>
         </frame>
         <hbox>
          <button><input file>/usr/local/lib/X11/mini-icons/mini-question.xpm</input><action type=\"launch\">DLG_HELPenv</action></button>
         </hbox>
        </vbox>
        <vbox>
         <frame Capabilities>
          <text><label>Drop:</label></text>
          <checkbox><variable>CAP_system</variable><label>system</label><input file>/tmp/easy_containers/chkbx-EC_CAP_system</input></checkbox>
          <checkbox><variable>CAP_file</variable><label>file</label><input file>/tmp/easy_containers/chkbx-EC_CAP_file</input></checkbox>
          <checkbox><variable>CAP_network</variable><label>network</label><input file>/tmp/easy_containers/chkbx-EC_CAP_network</input></checkbox>
          <checkbox><variable>CAP_module</variable><label>module</label><input file>/tmp/easy_containers/chkbx-EC_CAP_module</input></checkbox>
          <checkbox><variable>CAP_resource</variable><label>resource</label><input file>/tmp/easy_containers/chkbx-EC_CAP_resource</input></checkbox>
          <hbox>
           <button><input file>/usr/local/lib/X11/mini-icons/mini-question.xpm</input><action type=\"launch\">DLG_HELPcap</action></button>
          </hbox>
         </frame>
        </vbox>
        <vbox>
         <frame Namespaces>
          <text><label>Unshare:</label></text>
          <checkbox><variable>NS_MOUNT</variable><label>mount</label><input file>/tmp/easy_containers/chkbx-EC_NS_UNSHARE_MOUNT</input></checkbox>
          <checkbox><variable>NS_UTS</variable><label>UTS</label><input file>/tmp/easy_containers/chkbx-EC_NS_UNSHARE_UTS</input></checkbox>
          <checkbox><variable>NS_IPC</variable><label>IPC</label><input file>/tmp/easy_containers/chkbx-EC_NS_UNSHARE_IPC</input></checkbox>
          <checkbox><variable>NS_NETWORK</variable><label>network</label><input file>/tmp/easy_containers/chkbx-EC_NS_UNSHARE_NETWORK</input></checkbox>
          <checkbox><variable>NS_PID</variable><label>PID</label><input file>/tmp/easy_containers/chkbx-EC_NS_UNSHARE_PID</input></checkbox>
          <hbox>
           <button><input file>/usr/local/lib/X11/mini-icons/mini-question.xpm</input><action type=\"launch\">DLG_HELPns</action></button>
          </hbox>
         </frame>
        </vbox>
        <vbox>
         <frame X server>
          <radiobutton><variable>XSERVER_XORG</variable><label>Xorg</label><input file>/tmp/easy_containers/chkbx-XSERVER_XORG</input></radiobutton>
          <radiobutton><variable>XSERVER_XEPHYR</variable><label>Xephyr</label><input file>/tmp/easy_containers/chkbx-XSERVER_XEPHYR</input></radiobutton>
         </frame>
         <frame X socket>
          <radiobutton><variable>XSOCKET_ABSTRACT</variable><label>Abstract</label><input file>/tmp/easy_containers/chkbx-XSOCKET_ABSTRACT</input></radiobutton>
          <radiobutton><variable>XSOCKET_PIPE</variable><label>Pipe</label><input file>/tmp/easy_containers/chkbx-XSOCKET_PIPE</input></radiobutton>
          <radiobutton><variable>XSOCKET_UNIX</variable><label>Unix</label><input file>/tmp/easy_containers/chkbx-XSOCKET_UNIX</input></radiobutton>
         </frame>
         <hbox>
          <button><input file>/usr/local/lib/X11/mini-icons/mini-question.xpm</input><action type=\"launch\">DLG_HELPxorg</action></button>
         </hbox>
        </vbox>
       </hbox>
      </vbox>
     </notebook>
  
  <hbox>
    <button><label>OK</label><action>exit:ok</action></button>
  </hbox>
</vbox>
</window>"

RETSTRING1="$(gtkdialog --program=SFS_SEC_DLG --center)"
[ $? -ne 0 ] && exit
eval "$RETSTRING1"
[ "$EXIT" != "ok" ] && exit 5

###configuration file###
  echo '#Information for setting up and running the container' > /tmp/sfsget/ec-configuration
  
  #write security options to configuration file...
  echo "
#Connect to X by abstract socket, pipe or unix domain socket (abstract|pipe|unix)..." >> /tmp/sfsget/ec-configuration
  [ "$XSOCKET_ABSTRACT" == "true" ] && echo "EC_XSOCKET='abstract'" >> /tmp/sfsget/ec-configuration
  [ "$XSOCKET_PIPE" == "true" ] && echo "EC_XSOCKET='pipe'" >> /tmp/sfsget/ec-configuration
  [ "$XSOCKET_UNIX" == "true" ] && echo "EC_XSOCKET='unix'" >> /tmp/sfsget/ec-configuration
  echo "#Use Xorg or Xephyr server (xorg|xephyr)..." >> /tmp/sfsget/ec-configuration
  [ "$XSERVER_XEPHYR" == "true" ] && echo "EC_XSERVER='xephyr'" >> /tmp/sfsget/ec-configuration
  [ "$XSERVER_XORG" == "true" ] && echo "EC_XSERVER='xorg'" >> /tmp/sfsget/ec-configuration
  #namespaces...
  echo '
#For security, unshare these namespaces:' >> /tmp/sfsget/ec-configuration
  echo "EC_NS_UNSHARE_MOUNT='${NS_MOUNT}'" >> /tmp/sfsget/ec-configuration
  echo "EC_NS_UNSHARE_UTS='${NS_UTS}'" >> /tmp/sfsget/ec-configuration
  echo "EC_NS_UNSHARE_IPC='${NS_IPC}'" >> /tmp/sfsget/ec-configuration
  echo "EC_NS_UNSHARE_NETWORK='${NS_NETWORK}'" >> /tmp/sfsget/ec-configuration
  echo "EC_NS_UNSHARE_PID='${NS_PID}'" >> /tmp/sfsget/ec-configuration
  #echo "EC_NS_UNSHARE_USER='${NS_USER}'" >> /tmp/sfsget/ec-configuration
  #environment...
  echo '
#Clear environment variables, except some such as TERM and DISPLAY:' >> /tmp/sfsget/ec-configuration
  echo "EC_UNSHARE_ENV_VARS='${ENV_VARS}'" >> /tmp/sfsget/ec-configuration
echo '#Tick to run as user zeus in container:' >> /tmp/sfsget/ec-configuration
  echo "EC_ENV_ZEUS='${ENV_ZEUS}'" >> /tmp/sfsget/ec-configuration
  #access...
  echo '
#Specify what you are allowed to access outside the container:' >> /tmp/sfsget/ec-configuration
  echo "EC_ACCESS_NET='${ACCESS_NET}'" >> /tmp/sfsget/ec-configuration
  echo "EC_ACCESS_SND='${ACCESS_SND}'" >> /tmp/sfsget/ec-configuration
  echo "EC_ACCESS_FOLDER='${ACCESS_FOLDER}'" >> /tmp/sfsget/ec-configuration
  echo "EC_ACCESS_FOLDER_PATH='${ACCESS_FOLDER_PATH}'" >> /tmp/sfsget/ec-configuration
  #capabilities...
  echo '
#Drop these Linux capabilities:' >> /tmp/sfsget/ec-configuration
  echo "EC_CAP_system='${CAP_system}'" >> /tmp/sfsget/ec-configuration
  echo "EC_CAP_file='${CAP_file}'" >> /tmp/sfsget/ec-configuration
  echo "EC_CAP_network='${CAP_network}'" >> /tmp/sfsget/ec-configuration
  echo "EC_CAP_module='${CAP_module}'" >> /tmp/sfsget/ec-configuration
  echo "EC_CAP_resource='${CAP_resource}'" >> /tmp/sfsget/ec-configuration
  echo "EC_CAP_mount='${CAP_mount}'" >> /tmp/sfsget/ec-configuration
  echo "
#if you want to load another .sfs file, resident in the releases folder of the
#current version of Easy, for example: releases/easy-0.1.6/devx.sfs
#then uncomment this. Glob wildcard accepted, in fact is recommended
#for automatic version updating:
#EASY_LAYER_RO1='devx*.sfs'" >> /tmp/sfsget/ec-configuration


###end###
