Example #1
0
 def auth(commands, user_session):
     if user_session:
         if user_session.is_expired():
             mailpile.auth.SESSION_CACHE.delete_expired()
             user_session = None
         else:
             user_session.update_ts()
         if user_session and method == 'POST':
             if isinstance(post_data, cgi.FieldStorage):
                 try:
                     csrf = post_data['csrf'].value
                 except KeyError:
                     csrf = ''
             else:
                 csrf = post_data.get('csrf', [''])[0]
             if not security.valid_csrf_token(request, sid, csrf):
                 user_session = None
     if not user_session or not user_session.auth:
         for c in commands:
             if (c.HTTP_AUTH_REQUIRED is True or
                    (c.HTTP_AUTH_REQUIRED == 'Maybe' and
                     self.session.config.prefs.gpg_recipient)):
                 if is_async or is_api:
                     raise AccessError()
                 self.redirect_to_auth_or_setup(method, path,
                                                query_data)
     return commands
Example #2
0
 def auth(commands, user_session):
     if user_session:
         if user_session.is_expired():
             mailpile.auth.SESSION_CACHE.delete_expired()
             user_session = None
         else:
             user_session.update_ts()
         if user_session and method == 'POST':
             if isinstance(post_data, cgi.FieldStorage):
                 try:
                     csrf = post_data['csrf'].value
                 except KeyError:
                     csrf = ''
             else:
                 csrf = post_data.get('csrf', [''])[0]
             if not security.valid_csrf_token(
                     request.server.secret, sid, csrf):
                 user_session = None
     if not user_session or not user_session.auth:
         for c in commands:
             if (c.HTTP_AUTH_REQUIRED is True or
                 (c.HTTP_AUTH_REQUIRED == 'Maybe'
                  and self.session.config.prefs.gpg_recipient)):
                 if is_async or is_api:
                     raise AccessError()
                 self.redirect_to_auth_or_setup(
                     method, path, query_data)
     return commands
Example #3
0
    def command(self):
        html_variables = self.session.ui.html_variables
        request = html_variables['http_request']

        if not (html_variables and
                security.valid_csrf_token(request,
                                          html_variables['http_session'],
                                          self.data.get('csrf', [''])[0])):
            raise AccessError('Invalid CSRF token')

        url = self.data['url'][0]
        timeout = float(self.data.get('timeout', ['10'])[0])

        conn_reject = []  # FIXME: reject ConnBroker.OUTGOING_TRACKABLE ?
        if url[:6].lower() == 'https:':
            conn_need = [ConnBroker.OUTGOING_HTTP]
        elif url[:5].lower() == 'http:':
            conn_need = [ConnBroker.OUTGOING_HTTPS]
        else:
            raise AccessError('Invalid URL scheme')

        try:
            with ConnBroker.context(need=conn_need, reject=conn_reject) as ctx:
                self.session.ui.mark('Getting: %s' % url)
                response = urlopen(url, data=None, timeout=timeout)
        except HTTPError, e:
            response = e
Example #4
0
    def command(self):
        html_variables = self.session.ui.html_variables
        request = html_variables["http_request"]

        if not (
            html_variables
            and security.valid_csrf_token(request, html_variables["http_session"], self.data.get("csrf", [""])[0])
        ):
            raise AccessError("Invalid CSRF token")

        url = self.data["url"][0]
        timeout = float(self.data.get("timeout", ["10"])[0])

        conn_reject = []  # FIXME: reject ConnBroker.OUTGOING_TRACKABLE ?
        if url[:6].lower() == "https:":
            conn_need = [ConnBroker.OUTGOING_HTTP]
        elif url[:5].lower() == "http:":
            conn_need = [ConnBroker.OUTGOING_HTTPS]
        else:
            raise AccessError("Invalid URL scheme")

        try:
            with ConnBroker.context(need=conn_need, reject=conn_reject) as ctx:
                self.session.ui.mark("Getting: %s" % url)
                response = urlopen(url, data=None, timeout=timeout)
        except HTTPError, e:
            response = e
Example #5
0
    def _real_do_GET(self, post_data={}, suppress_body=False, method='GET'):
        (scheme, netloc, path, params, query, frag) = urlparse(self.path)
        query_data = parse_qs(query)
        opath = path = unquote(path)

        # HTTP is stateless, so we create a new session for each request.
        self.session, config = self.server.session, self.server.session.config
        server_session = self.server.session

        # Debugging...
        if 'httpdata' in config.sys.debug:
            self.wfile = DebugFileWrapper(sys.stderr, self.wfile)

        # Path manipulation...
        if path == '/favicon.ico':
            path = '%s/static/favicon.ico' % (config.sys.http_path or '')
        if config.sys.http_path:
            if not path.startswith(config.sys.http_path):
                self.send_full_response(_("File not found (invalid path)"),
                                        code=404,
                                        mimetype='text/plain')
                return None
            path = path[len(config.sys.http_path):]
        if path.startswith('/_/'):
            path = path[2:]
        for static in ('/static/', '/bower_components/'):
            if path.startswith(static):
                return self.send_file(config,
                                      path[len(static):],
                                      suppress_body=suppress_body)

        self.session = session = Session(config)
        session.ui = HttpUserInteraction(self,
                                         config,
                                         log_parent=server_session.ui)
        if 'context' in post_data:
            session.load_context(post_data['context'][0])
        elif 'context' in query_data:
            session.load_context(query_data['context'][0])

        mark_name = 'Processing HTTP API request at %s' % time.time()
        session.ui.start_command(mark_name, [], {})

        if 'http' in config.sys.debug:
            session.ui.warning = server_session.ui.warning
            session.ui.notify = server_session.ui.notify
            session.ui.error = server_session.ui.error
            session.ui.debug = server_session.ui.debug
            session.ui.debug('%s: %s qs = %s post = %s' %
                             (method, opath, query_data, post_data))

        idx = session.config.index
        if session.config.loaded_config:
            name = session.config.get_profile().get('name', 'Chelsea Manning')
        else:
            name = 'Chelsea Manning'

        http_headers = []
        http_session = self.http_session()
        csrf_token = security.make_csrf_token(self.server.secret, http_session)
        session.ui.html_variables = {
            'csrf_token':
            csrf_token,
            'csrf_field':
            ('<input type="hidden" name="csrf" value="%s">' % csrf_token),
            'http_host':
            self.headers.get('host', 'localhost'),
            'http_hostname':
            self.http_host(),
            'http_method':
            method,
            'http_session':
            http_session,
            'http_request':
            self,
            'http_response_headers':
            http_headers,
            'message_count': (idx and len(idx.INDEX) or 0),
            'name':
            name,
            'title':
            'Mailpile dummy title',
            'url_protocol':
            self.headers.get('x-forwarded-proto', 'http'),
            'mailpile_size':
            idx and len(idx.INDEX) or 0
        }
        session.ui.valid_csrf_token = lambda token: security.valid_csrf_token(
            self.server.secret, http_session, token)

        try:
            try:
                need_auth = not (mailpile.util.TESTING
                                 or session.config.sys.http_no_auth)
                commands = UrlMap(session).map(self,
                                               method,
                                               path,
                                               query_data,
                                               post_data,
                                               authenticate=need_auth)
            except UsageError:
                if (not path.endswith('/') and not session.config.sys.debug
                        and method == 'GET'):
                    commands = UrlMap(session).map(self, method, path + '/',
                                                   query_data, post_data)
                    url = quote(path) + '/'
                    if query:
                        url += '?' + query
                    return self.send_http_redirect(url)
                else:
                    raise

            cachectrl = None
            if 'http' not in config.sys.debug:
                etag_data = []
                max_ages = []
                have_ed = 0
                for c in commands:
                    max_ages.append(c.max_age())
                    ed = c.etag_data()
                    have_ed += 1 if ed else 0
                    etag_data.extend(ed)
                if have_ed == len(commands):
                    etag = self._mk_etag(*etag_data)
                    conditional = self.headers.get('if-none-match')
                    if conditional == etag:
                        self.send_full_response('OK',
                                                code=304,
                                                msg='Unmodified')
                        return None
                    else:
                        http_headers.append(('ETag', etag))
                max_age = min(max_ages) if max_ages else 10
                if max_age:
                    cachectrl = 'must-revalidate, max-age=%d' % max_age
                else:
                    cachectrl = 'must-revalidate, no-store, max-age=0'

            global LIVE_HTTP_REQUESTS
            hang_fix = 1 if ([1 for c in commands
                              if c.IS_HANGING_ACTIVITY]) else 0
            try:
                LIVE_HTTP_REQUESTS -= hang_fix

                session.ui.mark('Running %d commands' % len(commands))
                results = [cmd.run() for cmd in commands]

                session.ui.mark('Displaying final result')
                session.ui.display_result(results[-1])
            finally:
                LIVE_HTTP_REQUESTS += hang_fix

            session.ui.mark('Rendering response')
            mimetype, content = session.ui.render_response(session.config)

            session.ui.mark('Sending response')
            self.send_full_response(content,
                                    mimetype=mimetype,
                                    header_list=http_headers,
                                    cachectrl=cachectrl)

        except UrlRedirectException as e:
            return self.send_http_redirect(e.url)
        except SuppressHtmlOutput:
            return None
        except AccessError:
            self.send_full_response(_('Access Denied'),
                                    code=403,
                                    mimetype='text/plain')
            return None
        except:
            e = traceback.format_exc()
            session.ui.debug(e)
            if not session.config.sys.debug:
                e = _('Internal Error')
            self.send_full_response(e, code=500, mimetype='text/plain')
            return None

        finally:
            session.ui.report_marks(
                details=('timing' in session.config.sys.debug))
            session.ui.finish_command(mark_name)