diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c549557 --- /dev/null +++ b/.gitignore @@ -0,0 +1,155 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# dotenv +.env + +# virtualenv +.venv +venv/ +ENV/ + +# Spyder project settings +.spyderproject + +# Rope project settings +.ropeproject + +# Vagrant +.vagrant + +# cache files for sublime text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# workspace files are user-specific +*.sublime-workspace + +# project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using SublimeText +# *.sublime-project + +# sftp configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + +# macOS +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk diff --git a/README.md b/README.md new file mode 100644 index 0000000..216cc70 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# dropsite diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..ad3d3c1 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,31 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant.configure("2") do |config| + config.vm.guest = :freebsd + config.vm.synced_folder "dropsite", "/vagrant/dropsite", id: "dropsite-root", type: "rsync" + config.vm.synced_folder "os", "/vagrant/os", id: "os-root", type: "rsync" + config.vm.synced_folder ".", "/vagrant", disabled: true + config.ssh.shell = "sh" + config.vm.provision :shell, path: "bootstrap.sh" + config.vm.network :forwarded_port, guest: 80, host: 8081 + config.vm.box = "freebsd/FreeBSD-11.0-RELEASE-p1" + config.vm.base_mac = "" + + config.vm.provider :virtualbox do |vb| + vb.customize ["modifyvm", :id, "--memory", "1024"] + vb.customize ["modifyvm", :id, "--paravirtprovider", "default"] + vb.customize ["modifyvm", :id, "--vram", "16"] + vb.customize ["modifyvm", :id, "--nictype1", "virtio"] + vb.customize ["modifyvm", :id, "--boot2", "none"] + end + + config.push.define "ftp" do |push| + push.host = "" + push.username = "freebsd" + push.secure = "true" + push.destination = "/usr/local/www/dropsite" + push.dir = "dropsite" + end + +end diff --git a/bootstrap.sh b/bootstrap.sh new file mode 100755 index 0000000..45e16e3 --- /dev/null +++ b/bootstrap.sh @@ -0,0 +1,81 @@ +#!/bin/sh + +# Configure PF firewall +cp /vagrant/os/config/pf.conf /etc/pf.conf +sysrc -q pf_enable=YES > /dev/null +sysrc -q pflog_enable=YES > /dev/null + +# Install root CA certificates +pkg install -q --yes ca_root_nss > /dev/null + +# Set the clock +sysrc -q ntpd_enable=YES > /dev/null +service ntpd start > /dev/null + +# Make UTF-8 the default +patch -s --posix /etc/login.conf /vagrant/os/patch/login_conf.patch +cap_mkdb /etc/login.conf + +# Install complete make.conf +cp /vagrant/os/config/make.conf /etc/make.conf + +# Install tmux +pkg install -q --yes tmux > /dev/null + +# Install portmaster +pkg install --yes /vagrant/os/packages/portmaster-3.17.10.txz > /dev/null + +# Install OpenSSH +pkg install --yes /vagrant/os/packages/openssh-portable-7.5.p1,1.txz > /dev/null +patch -s --posix /usr/local/etc/ssh/sshd_config /vagrant/os/patch/sshd_config.patch +#service sshd stop > /dev/null +sysrc -q sshd_enable=NO > /dev/null +sysrc -q openssh_enable=YES > /dev/null +#service openssh start > /dev/null + +# Install NGINX Mainline +pkg install -q --yes nginx-devel > /dev/null +patch -s --posix /usr/local/etc/nginx/nginx.conf /vagrant/os/patch/nginx_conf.patch +sysrc -q nginx_enable=YES > /dev/null +echo -n 'test:' > /usr/local/etc/nginx/.htpasswd +openssl passwd -crypt testtest >> /usr/local/etc/nginx/.htpasswd +service nginx start > /dev/null + +# Install Python3 +pkg install -q --yes python36 > /dev/null +fetch -q -o /root https://bootstrap.pypa.io/get-pip.py +python3.6 /root/get-pip.py > /dev/null +rm /root/get-pip.py + +# Install Flask +pip3 install Flask > /dev/null +pip3 install flask-bootstrap > /dev/null + +# Install requests +pip3 install requests > /dev/null + +# Install uWSGI +pkg install --yes /vagrant/os/packages/py36-setuptools-32.1.0_1.txz > /dev/null +pkg install --yes /vagrant/os/packages/uwsgi-2.0.14_2.txz > /dev/null + +# Cleanup OS configuration +sysrc -q -a -e /etc/rc.conf > /root/rc.conf && mv /root/rc.conf /etc/rc.conf + +# Create socket directory for uWSGI +mkdir /var/run/uwsgi +chown www:www /var/run/uwsgi + +# Create directory for uploaded files +mkdir /uploads +chown www:www /uploads +/vagrant/dropsite/reset.py +chown www:www /uploads/last_run.json + +# Install uWSGI startup file +cp /vagrant/os/config/rc.local /etc/rc.local + +# Launch uWSGI Emperor +/usr/local/bin/uwsgi --emperor /vagrant/dropsite --uid www --gid www --daemonize /var/log/uwsgi-emperor.log + +# Adjust crontab to run webhook +patch -s --posix /etc/crontab /vagrant/os/patch/crontab.patch diff --git a/dropsite/dropsite.py b/dropsite/dropsite.py new file mode 100755 index 0000000..23f63f8 --- /dev/null +++ b/dropsite/dropsite.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3.6 + +import os +import uuid + +from flask import Flask +from flask import flash +from flask import redirect +from flask import render_template +from flask import request +from flask_bootstrap import Bootstrap +from werkzeug.utils import secure_filename + +UPLOAD_FOLDER = '/uploads' + +app = Flask(__name__) +app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER +app.config['MAX_CONTENT_LENGTH'] = 128 * 1024 * 1024 +app.secret_key = '' +bootstrap = Bootstrap(app) + + +@app.route('/', methods=['GET']) +def index(): + return render_template('index.html') + + +@app.route('/email', methods=['GET', 'POST']) +def email(): + if request.method == 'POST': + + # Check if the post request has the text part + if 'text' not in request.form: + flash('No text part', category='error') + return redirect(request.url) + + text = request.form['text'] + + # Flash an error if user does not enter an email + if text == '': + flash('No email text entered', category='error') + return redirect(request.url) + + # Save the uploaded raw email to the upload folder + if text: + filename = 'email_{}'.format(str(uuid.uuid4())) + fh = open(os.path.join(app.config['UPLOAD_FOLDER'], filename), 'w') + fh.write(text) + fh.close() + flash('Raw email uploaded {}'.format(filename), category='info') + return redirect(request.url) + + return render_template('email.html') + + +@app.route('/file', methods=['GET', 'POST']) +def file(): + if request.method == 'POST': + + # Check if the post request has the file part + if 'file' not in request.files: + flash('No file part', category='error') + return redirect(request.url) + + file = request.files['file'] + + # Flash an error if user does not select file + if file.filename == '': + flash('No selected file', category='error') + return redirect(request.url) + + # Save the uploaded file to the upload folder + if file: + filename_base = secure_filename(file.filename) + filename = '{}_{}'.format(str(uuid.uuid4()), filename_base) + file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename)) + flash('File uploaded {}'.format(filename), category='info') + return redirect(request.url) + + return render_template('file.html') + + +@app.route('/help', methods=['GET']) +def help_main(): + return render_template('help.html') + + +@app.route('/help/gmail', methods=['GET']) +def gmail(): + return render_template('gmail.html') + + +@app.route('/help/yahoo', methods=['GET']) +def yahoo(): + return render_template('yahoo.html') + + +@app.route('/help/apple_mail', methods=['GET']) +def apple_mail(): + return render_template('apple_mail.html') + +if __name__ == "__main__": + app.run() diff --git a/dropsite/reset.py b/dropsite/reset.py new file mode 100755 index 0000000..8345623 --- /dev/null +++ b/dropsite/reset.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python3.6 + +import json +import os + +uploads = '/uploads' + +with open(os.path.join(uploads, 'last_run.json'), 'w') as fh: + fh.write(json.dumps(list())) diff --git a/dropsite/static/download_original.png b/dropsite/static/download_original.png new file mode 100644 index 0000000..71a98a3 Binary files /dev/null and b/dropsite/static/download_original.png differ diff --git a/dropsite/static/favicon.ico b/dropsite/static/favicon.ico new file mode 100644 index 0000000..7fa832b Binary files /dev/null and b/dropsite/static/favicon.ico differ diff --git a/dropsite/static/show_original.png b/dropsite/static/show_original.png new file mode 100644 index 0000000..936d8e5 Binary files /dev/null and b/dropsite/static/show_original.png differ diff --git a/dropsite/static/view_message_raw_source.png b/dropsite/static/view_message_raw_source.png new file mode 100644 index 0000000..4e11c1b Binary files /dev/null and b/dropsite/static/view_message_raw_source.png differ diff --git a/dropsite/static/view_raw.png b/dropsite/static/view_raw.png new file mode 100644 index 0000000..892db2c Binary files /dev/null and b/dropsite/static/view_raw.png differ diff --git a/dropsite/templates/apple_mail.html b/dropsite/templates/apple_mail.html new file mode 100644 index 0000000..5a80839 --- /dev/null +++ b/dropsite/templates/apple_mail.html @@ -0,0 +1,15 @@ +{% extends "user.html" %} + +{% block content %} +