#!/bin/bash

OBSOLETE
--------

I am not using this any more.  Please do read the WHY section below for the original motivation.  However, after some years of doing this I realised that I rarely, if ever, run more than one such private browser at once, so it seems sufficient to relegate them *all* to a secondary userid and run them from there.  Code for that is in the new "usff" to be added here soon.

shopt -s inherit_errexit
set -euo pipefail
IFS=$'\n\t'
die() { echo >&2 "$*"; exit 1; }

cat <<EOF >/dev/null

"usff" stands for "user separated firefox".  Or maybe "ultimate separation for firefox" :)

WHY
---

    I want persistent logins to several sites, with the ultimate separation
    between them, even more than Firefox's profiles or container tabs can give
    me.  I don't need it for all sites; only for anything to do with money
    (bank, credit card, etc., shopping sites, and my primary email where bank
    may send statements etc).

    Unix's user-to-user separation has been around longer than anything else I
    can *trivially* get my hands on (translation: Qubes is overkill and anyway
    I don't have the hardware for it!) so why not use that instead?  Just
    create and use a separate Unix userid for each site you want to log on to.

    Advantages:
    -   Unix OS level separation is much older and much more time-tested than
        any firefox-internal mechanisms like container tabs or profiles
        (consider the probability of a bug in firefox that breaks the wall
        between profiles, and the probability of the same thing happening to
        the Unix user-id separation)
    -   Invoked programs (e.g., PDF reader) also run separated (consider the
        likelihood of downloading a malicious PDF, for example)

    Disadvantages (also see "REMINDER" section below):
    -   Any files downloaded that you want to preserve will have to be moved
        manually, using some other mechanism.  (I typically just use /tmp/tmp,
        (chmod 1777, just like /tmp), and a cron job that goes in and wipes
        out files older than a day to keep it sane).

HOW
---

    ONE-TIME preparation:

    -   Put this script (usff) somewhere in PATH.

    -   As root, create the group which will hold all these userids:

            groupadd usff

    -   As root, add this line to the sudoers file (by running "visudo"):

            xkcd386 ALL=(%usff) NOPASSWD: ALL

        (replace "xkcd386" with whatever your userid is).

    ONE-TIME per site you want to enable this for:

    -   As root, for each site you want to separate, run this (using a
        fictional "mybank" as an example):

            usff new mybank.com

    REGULAR USE

    -   From your normal userid, (again using mybank as an example) just run:

            usff mybank.com

    -   If you want to open a PDF or a media file from within this browser,
        you will either have to rerun the usff command above just before you
        open it, or you may choose to comment out the last line in this script
        (the "xhost -" line)

    -   You can even start other programs.  Let's say you already downloaded
        your bank statement PDF in a session yesterday.  Just run

            usff mybank.com okular

        and hit Ctrl-O to navigate to your file and open it.

REMINDER
--------

    Nothing stops you from using a mybank.com firefox instance to log on to,
    say, google.  This is not meant to protect against **you** :-)

    The biggest adjustment is links.  Don't click on links that go to some
    other site.  Instead, start the other browser also (if needed), then copy
    and paste the link.

    In reality, the sites I use it for rarely have any cross bleed like this
    so this has not been a problem for me so far.  YMMV.

EOF

# ----------------------------------------------------------------------

sitename_to_username() {
    SITE=$(echo "$1" | tr -cd a-z0-9)
    SITE=usff-$SITE   # mandatory prefix, to distinguish from other users
    echo $SITE
    # i.e., "mybank.com" becomes "usff-mybankcom"
}

# ----------------------------------------------------------------------

if [[ $USER == root ]]; then
    # arg 1 should be "new"; just as a sanity check
    [[ $1 == new ]] || die "Usage: '$0' new somesite.com"
    shift;

    SITE=$(sitename_to_username "$1")
    SITEHOME="/home/$SITE"

    useradd -m -G usff $SITE
    chmod -R go-rwx $SITEHOME
    chown -R $SITE:$SITE $SITEHOME

    echo "$SITE:"`openssl rand -hex 32` | chpasswd

    echo >&2 "Created new user $SITE..."

    exit 0
fi

[[ -z ${1:-} ]] && die "need a site name"

# ----------------------------------------------------------------------

SITE=$(sitename_to_username "$1")
SITE=$(cd /home; ls -d usff-* | grep "$1" | head -1 || echo NOTFOUND)
[[ -d /home/$SITE ]] || die "run 'usff new $1' as root first"
shift

sudo -u $SITE id    # will provoke asking for password

# browser or other tool to start
if [[ -n "${1:-}" ]]; then
    :
elif sudo -u $SITE ls -d /home/$SITE/.librewolf >/dev/null 2>&1 ; then
    set -- librewolf
else
    set -- firefox
fi

# enable X programs to run as user $SITE
xhost +SI:localuser:$SITE

# start the browser if it's not already started
pgrep -c -u $SITE -f "$1" || dm sudo -u $SITE "$@"

sleep 5
# disable any more X programs from running (see usage notes above)
xhost -SI:localuser:$SITE