Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5fffe596 authored by Felix's avatar Felix Committed by thilo
Browse files

Use fpm-alpine as base image, run as non-root (fixes #10)

parent 879cdd33
Loading
Loading
Loading
Loading
+6 −13
Original line number Diff line number Diff line
FROM php:7-apache-stretch
FROM php:7-fpm-alpine
ARG DOMAIN=welcome.ecloud.global
LABEL maintainer "thilo@e.email"
RUN mkdir -p /home/www-data/.ssh \
 && chown www-data:www-data /home/www-data/ -R \
 && chmod 700 /home/www-data/.ssh
COPY scripts/createAccount.sh /var/script/
COPY htdocs /var/www/html/
RUN chown www-data:www-data /var/script /var/www -R \
 && chmod +x /var/script/createAccount.sh \
 && mkdir -p /home/www-data/.ssh \
 && chown www-data:www-data /home/www-data/ -R \
 && chmod 700 /home/www-data/.ssh
RUN chown www-data:www-data /var/www -R

# Use the default production configuration
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
@@ -18,11 +10,12 @@ RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# copy composer executable from official Docker image
# https://hub.docker.com/_/composer
COPY --from=composer:1.8 /usr/bin/composer /usr/bin/composer
RUN apt-get update && apt-get install -y --no-install-recommends git unzip openssh-client \
RUN apk --no-cache add --virtual composer-deps git unzip \
 # these params are recommended for installing untrusted extensions
 # https://getcomposer.org/doc/faqs/how-to-install-untrusted-packages-safely.md
 && composer require --no-plugins --no-scripts pear/mail pear/net_smtp pear/auth_sasl pear/mail_mime \
 && apt-get remove -y git unzip \
 && rm -rf /var/lib/apt/lists/* \
 && apk del composer-deps \
 # composer shouldnt be present in production setups
 && rm /usr/bin/composer

USER www-data
+38 −55
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@ $name=$_POST['displayname'];
$quota=5120;
$active=1;
$wmail=0;
$script="/var/script/createAccount.sh";
$authmail=$_POST['authmail'];
$authsecret=$_POST['authsecret'];
$GLOBALS["lang"]="en";
@@ -116,65 +115,49 @@ if(!isAuthorized(trim($authmail),trim($authsecret))) {

if(!isset($_POST['username']) || !isset($_POST['password']) ||!isset($_POST['displayname']) ||!isset($_POST['repassword']) || strcmp($pw,$pw2)!=0) 
{
	if(strcmp($pw,$pw2)==0)
	if(strcmp($pw,$pw2)==0) {
		echo "Error: Mandatory fields are missing";
	else
		echo "Passwords do not match";
	} else {
		echo "Passwords do not match";
    }
    return;
}

$resultmail=$mbox."@".$domain;
$cmd = "$script ".$resultmail." 2>&1";
$ret=shell_exec($cmd);

//$pw=escapeshellarg($pw);
//$pw=str_replace("\"","\\\"",$pw);
//$pw=str_replace("'","\'",$pw);
//$pw=str_replace("$","\$",$pw);
//$pw2=escapeshellarg($pw2);
//$pw2=str_replace("\"","\\\"",$pw2);
//$pw2=str_replace("'","\'",$pw2);
//$pw2=str_replace("$","\$",$pw2);

if(strcmp(trim($ret),"0")==0) {
   $tmpfilename="/tmp/$mbox-details";
   $tmpfile = file_put_contents($tmpfilename,$resultmail.PHP_EOL , FILE_APPEND | LOCK_EX);
   $tmpfile = file_put_contents($tmpfilename,$pw.PHP_EOL , FILE_APPEND | LOCK_EX);
   $tmpfile = file_put_contents($tmpfilename,$pw2.PHP_EOL , FILE_APPEND | LOCK_EX);
   $tmpfile = file_put_contents($tmpfilename,$name.PHP_EOL , FILE_APPEND | LOCK_EX);
   $tmpfile = file_put_contents($tmpfilename,$quota.PHP_EOL , FILE_APPEND | LOCK_EX);
   $cmd="scp -i /home/www-data/.ssh/id_rsa -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $tmpfilename pfexec@postfixadmin:/tmp && rm $tmpfilename";
   $ret=shell_exec($cmd);
   $cmd="ssh -2i /home/www-data/.ssh/id_rsa pfexec@postfixadmin -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \"cat $tmpfilename | /usr/local/bin/wrapper.sh\" 2>&1";
   $ret=shell_exec($cmd);
   $cmd="ssh -2i /home/www-data/.ssh/id_rsa pfexec@postfixadmin -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \"rm -f $tmpfilename\"";
   $retDel=shell_exec($cmd);
   $find = "The mailbox $mbox@$domain has been added to the mailbox table";
   $output=nl2br($ret);
   $success = strpos($output, $find);
   if ($success === false) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
$data = array("auth" => getenv("CREATE_ACCOUNT_PASSWORD"), "target_email" => $resultmail,
              "password" => $pw, "password_confirm" => $pw2, "displayname" => $name,
              "email_quota" => $quota, "fallback_email" => $authmail, "nextcloud_quota" => "$quota MB");
curl_setopt($ch, CURLOPT_URL, "create-account:9000/create-account");
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
$output = curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
error_log($output);
	echo "Internal error";
   } else {
error_log("status code: $statusCode");
if ($statusCode === 200) {
    echo "Account $mbox@$domain created";
    sendWelcomeMsg($authmail,$mbox,$domain);
    $done = "$authmail:$authsecret:$mbox";
    $myfile = file_put_contents("/var/accounts/auth.file.done", $done.PHP_EOL , FILE_APPEND | LOCK_EX);
    if ( $myfile === false ) {
        echo "Error: Persisting creation info failed";
           exit;
      }
    }
} else {
   if(startsWith($ret, '1: ')) {
	error_log($output);
	echo "Internal error";
   }
   if(startsWith($ret, '2: ')) {
	echo "Username $mbox@$domain is already taken";
   }
   if(startsWith($ret, '3: ')) {
    $json = json_decode($output, true);
    switch ($json["message"]) {
        case "username_forbidden":
            echo "Username $mbox@$domain is not allowed";
   }
            break;
        case "username_taken":
            echo "Username $mbox@$domain is already taken";
            break;
        case "internal_error":
            echo "Internal error";
            break;
    }
}
?>

htdocs/users.php

deleted100644 → 0
+0 −39
Original line number Diff line number Diff line
<?php
      function db_connect() {
	$link = new mysqli("p:".getenv("PFDB_HOST"), getenv("PFDB_DB"), getenv("PFDB_PW"),getenv("PFDB_USR"));
        if (!$link){
            die('Could not connect: ' . mysqli_error());
            return -1;
        }
	$GLOBALS["mysqli_user"] = $link;
        return $GLOBALS["mysqli_user"];
    }

    function query($sql){//wrapper
        $link=db_connect();
	mysqli_set_charset($link, "utf8");
        $result=mysqli_query($link,$sql);
        if (!$result) {
            die('Invalid query: ' . mysqli_error());
		echo "error";
}
    	else
    		return $result;
        mysqli_close($link);
    }
    function printAccounts() {
        $sql = "SELECT DISTINCT username AS account FROM mailbox WHERE domain LIKE 'eelo.%' OR domain='e.email' UNION ALL SELECT DISTINCT address AS account FROM alias WHERE domain='eelo.%' OR domain='e.email';";
        $result=query($sql);
        while($erg=mysqli_fetch_array($result))
        {
             echo "$erg[account]\n";
        }
   }
?>
<?php
if(strcmp($_SERVER['REMOTE_ADDR'],"127.0.0.1")==0) {
	printAccounts();
} else {
	echo "access denied for ".$_SERVER['REMOTE_ADDR'];
}
?>

id_rsa_postfixadmincontainer.pub

deleted100644 → 0
+0 −1
Original line number Diff line number Diff line
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDF+1sKPgDIKEv5rMpXlJizexdNcHFVlStqB6x/x2dp0Rb8r0MT20XEQEc9g+v3waKKgNL0CkuUQiRhNoFMcTf3pS6NFMeucWUVjv2Cv8BArl7Q3LTiBGgKSeaPNNmsu3QM7cwbAqY+M28eFuFRUFxBs6hzTatPPnJwJw7WnWaBHZmJYAGPe6B2EVH3Kqn46tSjzBifI3eV/z0CnRy0JMrjjO0/1P+lIGNEMnvy8ESX6GPZcU+phhKqfWeGY4xfwOjBLBBs1O1iy90TeKABPwbOq2mbg3btjj4fpBsJ0VHe+s05snobl6PhpI4GA4P88NezXzVpdKS/YnLZq8AYyJXJ root@onlyoffice-test

scripts/createAccount.sh

deleted100755 → 0
+0 −33
Original line number Diff line number Diff line
#!/bin/bash
if (("$#" != 1)) 
then
  echo "1: internal error"
  exit 1
fi

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
  DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
  SOURCE="$(readlink "$SOURCE")"
  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"

email="$1"
prefix=$(echo "$email" | awk -F@ '{ print $1 }')
forbidden=$(grep "^$prefix\$" $DIR/exclude_names | wc -l)
if [ "$forbidden" = "1" ]
then
  echo "3: account $email not allowed"
  exit 3
fi
ACCOUNT_EXISTS=$(curl -kH "Host: $DOMAINS" http://localhost/users.php 2>&1 | grep -e "$email" -e "$prefix@eelo.io" -e "$prefix@eelo.me" | wc -l)

if [ "$ACCOUNT_EXISTS" = "0" ]
then
  echo "0"
  exit 0
else
  echo "2: account $email already taken"
  exit 2
fi