Example #1
0
 def __init__(self, environ, start_response):
     self.ca = CertAuthority(CONFIG['ca'])
     self.environ = environ
     self.resp = start_response
     self.action = self.environ.get('REQUEST_URI').split('/')[2]
     if not self.action.isalnum():
         raise
     # parse params
     tmp = environ.get('REQUEST_URI').split('?')
     self.params = {}
     if len(tmp) > 1:
         for exp in '?'.join(tmp[1:]).split('&'):
             tmp2 = exp.split('=')
             self.params[tmp2[0]] = '='.join(tmp2[1:])
Example #2
0
    def submitcsr(self):
        msg = ''
        if self.environ.get('REQUEST_METHOD') == 'POST':
            if int(self.environ.get('CONTENT_LENGTH', 0)) != 0:
                fd = self.environ['wsgi.input']
                params = {}
                for exp in fd.readline().split('&'):
                    tmp2 = exp.split('=')
                    params[tmp2[0]] = urllib.unquote('='.join(
                        tmp2[1:])).strip()
                if not csrf(params):
                    msg = "Try again from our fine server please."
                elif params.get('csr'):
                    ca = CertAuthority(CONFIG['ca'])
                    tmp = params['csr'].split('\n')
                    csr = '\n'.join([
                        urllib.unquote_plus(tmp[0]), '\n'.join(tmp[1:-1]),
                        urllib.unquote_plus(tmp[-1])
                    ])
                    try:
                        self.ca.submit(csr)
                    except:
                        msg = "Fail<br />please submit a valid Certificate Signing Request containing your email."
                    else:
                        msg = "Success<br />Your request will be reviewed soon."

        return send_template(self.resp,
                             'certify.html',
                             isadmin=authorized(self.environ,
                                                CONFIG['admins']),
                             csrf=getcsrf(),
                             msg=msg)
Example #3
0
File: stash.py Project: stef/stash
 def __init__(self,environ, start_response):
     self.ca=CertAuthority(CONFIG['ca'])
     self.environ=environ
     self.resp=start_response
     self.action = self.environ.get('REQUEST_URI').split('/')[2]
     if not self.action.isalnum():
         raise
     # parse params
     tmp = environ.get('REQUEST_URI').split('?')
     self.params = {}
     if len(tmp)>1:
         for exp in '?'.join(tmp[1:]).split('&'):
             tmp2 = exp.split('=')
             self.params[tmp2[0]]='='.join(tmp2[1:])
Example #4
0
#!/usr/bin/env python

import shutil, os
from tlsauth import CertAuthority, mailsigned, genkeycsr, pkcs12

# DEMO code
# initialize your own CA by running
# createca.sh CA
if os.path.exists('test-ca'): shutil.rmtree('test-ca')
ca = CertAuthority.createca('test-ca',
                            'http://www.example.com/crl.pem',
                            'example CA',
                            '*****@*****.**',
                            valid=5)

# do not try this at home.
# warning: irresponsible blind trust in 3rd parties
# warning: will be ignored anyway.
ca.gencert('joe', '*****@*****.**', 'ACME Inc.')
print "dropped correct pkcs12 cert"

# even worse (and intentionally ugly)
#mail(ca.gencert('s', '*****@*****.**', 'ctrlc'),
#     "Howdy.\n\n" \
#     "Your login certificate from %s is attached.\n\n" \
#     "You should import this into your browser, keep a safe\n" \
#     "copy and delete this mail and other copies containing it.\n\n" \
#     "Have fun and respect",
#     {'emailAddress': '*****@*****.**', 'CN': 's', 'O': 'ctrlc'},
#     ca.dn,
#     ext='p12')
Example #5
0
from cryptography.fernet import Fernet
from functools import wraps

BASE_PATH = os.path.dirname(os.path.realpath(__file__))
DB_PATH = os.path.join(BASE_PATH, "db.db")
UPLOAD_FOLDER = os.path.join(BASE_PATH, "upload")

application = Flask(__name__)
application.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
application.secret_key = 'CHANGE THIS IN PRODUCTION'
application.debug = True

from tlsauth import CertAuthority
import flask_tlsauth as tlsauth

ca = CertAuthority('sub-ca')

users = ["Users"]

application.jinja_loader = jinja2.ChoiceLoader([
    application.jinja_loader,
    jinja2.FileSystemLoader(os.path.join(BASE_PATH,'templates')),
    ])

application.add_url_rule('/tlsauth/cert/', 'cert', tlsauth.renderCert(ca))
application.add_url_rule('/tlsauth/test/', 'test', tlsauth.testAuth)

def connect_to_database():
    return sqlite3.connect(DB_PATH, detect_types=sqlite3.PARSE_DECLTYPES)

def get_db():
Example #6
0
#!/usr/bin/env python

# run with
# env/bin/uwsgi --socket 127.0.0.1:8080 --chdir $PWD/demo -pp $PWD -w tlsauth_wsgi -p 1 --virtualenv $PWD/env --py-autoreload 1
# also create a ca in ../../x509-ca - for more info see tlsauth README

from flask import Flask, Response
import os
app = Flask(__name__)
app.secret_key = 'zxcvzxcvz'
#app.debug = True

from tlsauth import CertAuthority
import flask_tlsauth as tlsauth

ca=CertAuthority('../../x509-ca')

app.debug = True
adminOs=['CA admins']
tlsauth.tlsauth_init(app, ca, groups=adminOs)

@app.route('/hello')
@tlsauth.tlsauth(groups=adminOs)
def hello():
    return Response("hello world")
Example #7
0
#!/usr/bin/env python

import shutil, os
from tlsauth import CertAuthority, mailsigned, genkeycsr, pkcs12

# DEMO code
# initialize your own CA by running
# createca.sh CA
if os.path.exists('test-ca'): shutil.rmtree('test-ca')
ca=CertAuthority.createca('test-ca', 'http://www.example.com/crl.pem', 'example CA', '*****@*****.**', valid=5)

# do not try this at home.
# warning: irresponsible blind trust in 3rd parties
# warning: will be ignored anyway.
ca.gencert('joe', '*****@*****.**', 'ACME Inc.')
print "dropped correct pkcs12 cert"

# even worse (and intentionally ugly)
#mail(ca.gencert('s', '*****@*****.**', 'ctrlc'),
#     "Howdy.\n\n" \
#     "Your login certificate from %s is attached.\n\n" \
#     "You should import this into your browser, keep a safe\n" \
#     "copy and delete this mail and other copies containing it.\n\n" \
#     "Have fun and respect",
#     {'emailAddress': '*****@*****.**', 'CN': 's', 'O': 'ctrlc'},
#     ca.dn,
#     ext='p12')

# this is the correct - but less automagic - procedure
sec, pub, csr = genkeycsr('joe', '*****@*****.**', 'ACME Inc.')
Example #8
0
File: stash.py Project: stef/stash
class AdminHandler(object):
    """ class for handling user registration, and creating new stashes over the web
        provides similar urls as Flask-TLSAuth

        /settings/register           - using keygen tag
        /settings/request            - submit your own CSR
        /settings/requests           - list all user account requests (admin only)
        /settings/newstash           - create a new stash (admin only)
        /settings/accept/<certhash>  - accept a new user request (admin only)
        /settings/reject/<certhash>  - reject a new user request (admin only)
    """
    def __init__(self,environ, start_response):
        self.ca=CertAuthority(CONFIG['ca'])
        self.environ=environ
        self.resp=start_response
        self.action = self.environ.get('REQUEST_URI').split('/')[2]
        if not self.action.isalnum():
            raise
        # parse params
        tmp = environ.get('REQUEST_URI').split('?')
        self.params = {}
        if len(tmp)>1:
            for exp in '?'.join(tmp[1:]).split('&'):
                tmp2 = exp.split('=')
                self.params[tmp2[0]]='='.join(tmp2[1:])

    def handle(self):
        """ main dispatcher of AdminHandler
        """
        if self.action == 'newstash':
            return self.newstash()
        elif self.action == 'register':
            return self.register()
        elif self.action == 'request':
            return self.submitcsr()
        elif self.action == 'requests':
            return self.showcsrs()
        elif self.action == 'accept':
            return self.accept()
        elif self.action == 'reject':
            return self.reject()
        elif self.action == 'stashes':
            return self.stashes()
        elif self.action == 'delete':
            return self.delete()
        return _404(self.environ,self.resp)

    def register(self):
        msg=''
        if self.environ.get('REQUEST_METHOD') == 'POST':
            if int(self.environ.get('CONTENT_LENGTH', 0)) != 0:
                fd=self.environ['wsgi.input']
                params={}
                for exp in fd.readline().split('&'):
                    tmp2 = exp.split('=')
                    params[tmp2[0]]=urllib.unquote('='.join(tmp2[1:]))
                if not csrf(params):
                    msg="Try again from our fine server please."
                elif params.get('email') and params.get('key'):
                    csr=spkac2cert(''.join(params['key']),
                                   params['email'],
                                   name=params.get('name'))
                    self.ca.submit(csr)
                    msg="Success<br />Your request will be reviewed soon."
                else:
                    msg="Sorry but you must supply an email address"

        return send_template(self.resp,
                             'register.html',
                             isadmin=authorized(self.environ, CONFIG['admins']),
                             csrf=getcsrf(),
                             msg=msg)

    def submitcsr(self):
        msg=''
        if self.environ.get('REQUEST_METHOD') == 'POST':
            if int(self.environ.get('CONTENT_LENGTH', 0)) != 0:
                fd=self.environ['wsgi.input']
                params={}
                for exp in fd.readline().split('&'):
                    tmp2 = exp.split('=')
                    params[tmp2[0]]=urllib.unquote('='.join(tmp2[1:])).strip()
                if not csrf(params):
                    msg="Try again from our fine server please."
                elif params.get('csr'):
                    ca=CertAuthority(CONFIG['ca'])
                    tmp=params['csr'].split('\n')
                    csr='\n'.join([urllib.unquote_plus(tmp[0]),
                                   '\n'.join(tmp[1:-1]),
                                   urllib.unquote_plus(tmp[-1])])
                    try:
                        self.ca.submit(csr)
                    except:
                        msg="Fail<br />please submit a valid Certificate Signing Request containing your email."
                    else:
                        msg="Success<br />Your request will be reviewed soon."

        return send_template(self.resp, 'certify.html',
                             isadmin=authorized(self.environ, CONFIG['admins']),
                             csrf=getcsrf(),
                             msg=msg)

    def showcsrs(self):
        email=authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)
        return send_template(self.resp,
                               'csrs.html',
                               isadmin=authorized(self.environ, CONFIG['admins']),
                               certs=[(todn(cert.get_subject()),
                                       datetime.datetime.fromtimestamp(os.stat(path).st_mtime),
                                       os.path.basename(path))
                                      for cert, path
                                      in self.ca.incoming()])

    def accept(self):
        """ provides facility for users belonging to `groups` to sign incoming CSRs
        """
        email=authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)
        path=self.ca._incoming+'/'+self.environ.get('REQUEST_URI').split('/')[3]
        print "certifying", path
        cert=self.ca.signcsr(load(path))
        mailsigned([cert])
        os.unlink(path)
        status = '302 Found'
        response_headers = [('Location', '/settings/requests')]
        self.resp(status, response_headers)
        return []

    def reject(self):
        """ provides facility for users belonging to `groups` to reject incoming CSRs
        """
        email=authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)
        path=self.ca._incoming+'/'+self.environ.get('REQUEST_URI').split('/')[3]
        os.unlink(path)
        status = '302 Found'
        response_headers = [('Location', '/settings/requests')]
        self.resp(status, response_headers)
        return []

    def newstash(self):
        msg=''
        email=authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)

        gpg = gnupg.GPG(gnupghome=CONFIG['gpghome'])
        knownkeys={x['uids'][0][ x['uids'][0].rfind('<')+1: x['uids'][0].rfind('>')]:x for x in gpg.list_keys()}
        keyid=knownkeys.get(email, {}).get('keyid')
        if self.environ.get('REQUEST_METHOD') == 'POST':
            if int(self.environ.get('CONTENT_LENGTH', 0)) != 0:
                fd=self.environ['wsgi.input']
                params=defaultdict(list)
                for exp in fd.readline().split('&'):
                    tmp2 = exp.split('=')
                    params[tmp2[0]]=urllib.unquote('='.join(tmp2[1:])).strip()
                if not csrf(params):
                    msg="Try again from our fine server please."
                elif keyid or params.get('keyid') or params.get('pk'):
                    if params.get('pk'):
                        gpg.import_keys(params.get('pk'))
                        knownkeys={x['uids'][0][ x['uids'][0].rfind('<')+1: x['uids'][0].rfind('>')]:x for x in gpg.list_keys()}
                    elif params.get('keyid'):
                        f = urllib.urlopen('http://pool.sks-keyservers.net:11371/pks/lookup?op=get&search=%s' % params.get('keyid'))
                        key = f.read()
                        gpg.import_keys(key)
                        knownkeys={x['uids'][0][ x['uids'][0].rfind('<')+1: x['uids'][0].rfind('>')]:x for x in gpg.list_keys()}
                    keyid=knownkeys.get(email)['keyid']
                    if not keyid:
                        msg="Couldn't locate PGP key for owner, try uploading one"
                    elif not params.get('invited'):
                        msg="You must invite someone to share this stash with"
                    else:
                        stashid=Dropper.newstash([knownkeys[email]['keyid']],
                                                 urllib.unquote_plus(params['invited']).split('\n'),
                                                 urllib.unquote_plus(params.get('name')))
                        # todo sent invitation mail to uploaders
                        status = '302 Found'
                        response_headers = [('Location', '/%s/' % stashid )]
                        self.resp(status, response_headers)
                        return []
                else:
                    msg="You must supply a PGP public key for enabling encryption of stored data"

        return send_template(self.resp, 'newstash.html',
                             isadmin=authorized(self.environ, CONFIG['admins']),
                             msg=msg,
                             csrf=getcsrf(),
                             knownkey=keyid)

    def stashes(self):
        """ lists all stashes for admins
        """
        email=authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)
        gpg = gnupg.GPG(gnupghome=CONFIG['gpghome'])
        knownkeys={x['keyid']: x['uids'][0][ x['uids'][0].rfind('<')+1: x['uids'][0].rfind('>')]
                   for x in gpg.list_keys()}
        stashes=[]
        for fname in os.listdir(CONFIG['root']+'/drop'):
            if not fname.endswith('.cfg'):
                continue
            with open(CONFIG['root']+'/drop/'+fname,'r') as fd:
                owner=[knownkeys[kid] for kid in fd.readline().strip().split()]
                friends=[x.strip() for x in fd.readlines()]
            files=[os.stat(CONFIG['root']+'/drop/'+fname[:-4]+'/'+f).st_size
                   for f in os.listdir(CONFIG['root']+'/drop/'+fname[:-4])
                   if not f.endswith('.meta')]
            stashes.append((fname[:-4],
                            owner,
                            friends,
                            sizeof_fmt(sum(files)),
                            len(files)))
        return send_template(self.resp,
                               'stashes.html',
                               isadmin=authorized(self.environ, CONFIG['admins']),
                               stashes=stashes)

    def delete(self):
        """ provides facility for users belonging to `groups` to reject incoming CSRs
        """
        email=authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)
        stashid=self.environ.get('REQUEST_URI').split('/')[3]
        if stashid.isalnum():
            path=CONFIG['root']+'/drop/'+stashid
            os.unlink(path+'.cfg')
            shutil.rmtree(path)
        status = '302 Found'
        response_headers = [('Location', '/settings/stashes')]
        self.resp(status, response_headers)
        return []
Example #9
0
class AdminHandler(object):
    """ class for handling user registration, and creating new stashes over the web
        provides similar urls as Flask-TLSAuth

        /settings/register           - using keygen tag
        /settings/request            - submit your own CSR
        /settings/requests           - list all user account requests (admin only)
        /settings/newstash           - create a new stash (admin only)
        /settings/accept/<certhash>  - accept a new user request (admin only)
        /settings/reject/<certhash>  - reject a new user request (admin only)
    """
    def __init__(self, environ, start_response):
        self.ca = CertAuthority(CONFIG['ca'])
        self.environ = environ
        self.resp = start_response
        self.action = self.environ.get('REQUEST_URI').split('/')[2]
        if not self.action.isalnum():
            raise
        # parse params
        tmp = environ.get('REQUEST_URI').split('?')
        self.params = {}
        if len(tmp) > 1:
            for exp in '?'.join(tmp[1:]).split('&'):
                tmp2 = exp.split('=')
                self.params[tmp2[0]] = '='.join(tmp2[1:])

    def handle(self):
        """ main dispatcher of AdminHandler
        """
        if self.action == 'newstash':
            return self.newstash()
        elif self.action == 'register':
            return self.register()
        elif self.action == 'request':
            return self.submitcsr()
        elif self.action == 'requests':
            return self.showcsrs()
        elif self.action == 'accept':
            return self.accept()
        elif self.action == 'reject':
            return self.reject()
        elif self.action == 'stashes':
            return self.stashes()
        elif self.action == 'delete':
            return self.delete()
        return _404(self.environ, self.resp)

    def register(self):
        msg = ''
        if self.environ.get('REQUEST_METHOD') == 'POST':
            if int(self.environ.get('CONTENT_LENGTH', 0)) != 0:
                fd = self.environ['wsgi.input']
                params = {}
                for exp in fd.readline().split('&'):
                    tmp2 = exp.split('=')
                    params[tmp2[0]] = urllib.unquote('='.join(tmp2[1:]))
                if not csrf(params):
                    msg = "Try again from our fine server please."
                elif params.get('email') and params.get('key'):
                    csr = spkac2cert(''.join(params['key']),
                                     params['email'],
                                     name=params.get('name'))
                    self.ca.submit(csr)
                    msg = "Success<br />Your request will be reviewed soon."
                else:
                    msg = "Sorry but you must supply an email address"

        return send_template(self.resp,
                             'register.html',
                             isadmin=authorized(self.environ,
                                                CONFIG['admins']),
                             csrf=getcsrf(),
                             msg=msg)

    def submitcsr(self):
        msg = ''
        if self.environ.get('REQUEST_METHOD') == 'POST':
            if int(self.environ.get('CONTENT_LENGTH', 0)) != 0:
                fd = self.environ['wsgi.input']
                params = {}
                for exp in fd.readline().split('&'):
                    tmp2 = exp.split('=')
                    params[tmp2[0]] = urllib.unquote('='.join(
                        tmp2[1:])).strip()
                if not csrf(params):
                    msg = "Try again from our fine server please."
                elif params.get('csr'):
                    ca = CertAuthority(CONFIG['ca'])
                    tmp = params['csr'].split('\n')
                    csr = '\n'.join([
                        urllib.unquote_plus(tmp[0]), '\n'.join(tmp[1:-1]),
                        urllib.unquote_plus(tmp[-1])
                    ])
                    try:
                        self.ca.submit(csr)
                    except:
                        msg = "Fail<br />please submit a valid Certificate Signing Request containing your email."
                    else:
                        msg = "Success<br />Your request will be reviewed soon."

        return send_template(self.resp,
                             'certify.html',
                             isadmin=authorized(self.environ,
                                                CONFIG['admins']),
                             csrf=getcsrf(),
                             msg=msg)

    def showcsrs(self):
        email = authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)
        return send_template(self.resp,
                             'csrs.html',
                             isadmin=authorized(self.environ,
                                                CONFIG['admins']),
                             certs=[(todn(cert.get_subject()),
                                     datetime.datetime.fromtimestamp(
                                         os.stat(path).st_mtime),
                                     os.path.basename(path))
                                    for cert, path in self.ca.incoming()])

    def accept(self):
        """ provides facility for users belonging to `groups` to sign incoming CSRs
        """
        email = authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)
        path = self.ca._incoming + '/' + self.environ.get('REQUEST_URI').split(
            '/')[3]
        print "certifying", path
        cert = self.ca.signcsr(load(path))
        mailsigned([cert])
        os.unlink(path)
        status = '302 Found'
        response_headers = [('Location', '/settings/requests')]
        self.resp(status, response_headers)
        return []

    def reject(self):
        """ provides facility for users belonging to `groups` to reject incoming CSRs
        """
        email = authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)
        path = self.ca._incoming + '/' + self.environ.get('REQUEST_URI').split(
            '/')[3]
        os.unlink(path)
        status = '302 Found'
        response_headers = [('Location', '/settings/requests')]
        self.resp(status, response_headers)
        return []

    def newstash(self):
        msg = ''
        email = authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)

        gpg = gnupg.GPG(gnupghome=CONFIG['gpghome'])
        knownkeys = {
            x['uids'][0][x['uids'][0].rfind('<') + 1:x['uids'][0].rfind('>')]:
            x
            for x in gpg.list_keys()
        }
        keyid = knownkeys.get(email, {}).get('keyid')
        if self.environ.get('REQUEST_METHOD') == 'POST':
            if int(self.environ.get('CONTENT_LENGTH', 0)) != 0:
                fd = self.environ['wsgi.input']
                params = defaultdict(list)
                for exp in fd.readline().split('&'):
                    tmp2 = exp.split('=')
                    params[tmp2[0]] = urllib.unquote('='.join(
                        tmp2[1:])).strip()
                if not csrf(params):
                    msg = "Try again from our fine server please."
                elif keyid or params.get('keyid') or params.get('pk'):
                    if params.get('pk'):
                        gpg.import_keys(params.get('pk'))
                        knownkeys = {
                            x['uids'][0][x['uids'][0].rfind('<') +
                                         1:x['uids'][0].rfind('>')]: x
                            for x in gpg.list_keys()
                        }
                    elif params.get('keyid'):
                        f = urllib.urlopen(
                            'http://pool.sks-keyservers.net:11371/pks/lookup?op=get&search=%s'
                            % params.get('keyid'))
                        key = f.read()
                        gpg.import_keys(key)
                        knownkeys = {
                            x['uids'][0][x['uids'][0].rfind('<') +
                                         1:x['uids'][0].rfind('>')]: x
                            for x in gpg.list_keys()
                        }
                    keyid = knownkeys.get(email)['keyid']
                    if not keyid:
                        msg = "Couldn't locate PGP key for owner, try uploading one"
                    elif not params.get('invited'):
                        msg = "You must invite someone to share this stash with"
                    else:
                        stashid = Dropper.newstash(
                            [knownkeys[email]['keyid']],
                            urllib.unquote_plus(params['invited']).split('\n'),
                            urllib.unquote_plus(params.get('name')))
                        # todo sent invitation mail to uploaders
                        status = '302 Found'
                        response_headers = [('Location', '/%s/' % stashid)]
                        self.resp(status, response_headers)
                        return []
                else:
                    msg = "You must supply a PGP public key for enabling encryption of stored data"

        return send_template(self.resp,
                             'newstash.html',
                             isadmin=authorized(self.environ,
                                                CONFIG['admins']),
                             msg=msg,
                             csrf=getcsrf(),
                             knownkey=keyid)

    def stashes(self):
        """ lists all stashes for admins
        """
        email = authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)
        gpg = gnupg.GPG(gnupghome=CONFIG['gpghome'])
        knownkeys = {
            x['keyid']:
            x['uids'][0][x['uids'][0].rfind('<') + 1:x['uids'][0].rfind('>')]
            for x in gpg.list_keys()
        }
        stashes = []
        for fname in os.listdir(CONFIG['root'] + '/drop'):
            if not fname.endswith('.cfg'):
                continue
            with open(CONFIG['root'] + '/drop/' + fname, 'r') as fd:
                owner = [
                    knownkeys[kid] for kid in fd.readline().strip().split()
                ]
                friends = [x.strip() for x in fd.readlines()]
            files = [
                os.stat(CONFIG['root'] + '/drop/' + fname[:-4] + '/' +
                        f).st_size
                for f in os.listdir(CONFIG['root'] + '/drop/' + fname[:-4])
                if not f.endswith('.meta')
            ]
            stashes.append((fname[:-4], owner, friends, sizeof_fmt(sum(files)),
                            len(files)))
        return send_template(self.resp,
                             'stashes.html',
                             isadmin=authorized(self.environ,
                                                CONFIG['admins']),
                             stashes=stashes)

    def delete(self):
        """ provides facility for users belonging to `groups` to reject incoming CSRs
        """
        email = authorized(self.environ, CONFIG['admins'])
        if not email:
            return _404(self.environ, self.resp)
        stashid = self.environ.get('REQUEST_URI').split('/')[3]
        if stashid.isalnum():
            path = CONFIG['root'] + '/drop/' + stashid
            os.unlink(path + '.cfg')
            shutil.rmtree(path)
        status = '302 Found'
        response_headers = [('Location', '/settings/stashes')]
        self.resp(status, response_headers)
        return []