示例#1
0
 def test__2(self):
     ''' Verify that append() unquotes the path, if requested to do so '''
     self.assertEqual(
         utils_path.append('/foobar', 'foo%2fbaz', False),
         "/foobar/foo%2fbaz",
     )
     self.assertEqual(
         utils_path.append('/foobar', 'foo%2fbaz', True),
         "/foobar/foo/baz",
     )
示例#2
0
 def test__4(self):
     ''' Verify that append() ASCII-fies the path in any case '''
     self.assertEqual(
         utils_path.append("/foobar",
             six.u("'/cio\xe8'"), True),
         None
     )
     self.assertEqual(
         utils_path.append("/foobar",
             six.u("'/cio%e8'"), True),
         None
     )
示例#3
0
 def test__1(self):
     ''' Make sure that append() fails when it can't decode
         the prefix or the path '''
     # Note: '/cio\xc3a8' is wrong on purpose here
     self.assertEqual(
         utils_path.append(six.b('/cio\xc3a8'), '/foobar', False),
         None
     )
     self.assertEqual(
         utils_path.append('/foobar', six.b('/cio\xc3\xa8'), False),
         None
     )
示例#4
0
def api_results(stream, request, query):
    ''' Populates www/results.html page '''

    dictionary = cgi.parse_qs(query)
    test = CONFIG['www_default_test_to_show']
    if 'test' in dictionary:
        test = str(dictionary['test'][0])

    # Read the directory each time, so you don't need to restart the daemon
    # after you have changed the description of a test.
    available_tests = {}
    for filename in os.listdir(TESTDIR):
        if filename.endswith('.json'):
            index = filename.rfind('.json')
            if index == -1:
                raise RuntimeError('api_results: internal error')
            name = filename[:index]
            available_tests[name] = filename
    if not test in available_tests:
        raise NotImplementedTest('Test not implemented')

    # Allow power users to customize results.html heavily, by creating JSON
    # descriptions with local modifications.
    filepath = utils_path.append(TESTDIR, available_tests[test], False)
    if not filepath:
        raise RuntimeError("api_results: append() path failed")
    localfilepath = filepath + '.local'
    if os.path.isfile(localfilepath):
        filep = open(localfilepath, 'rb')
    else:
        filep = open(filepath, 'rb')
    response_body = json.loads(filep.read())
    filep.close()

    # Add extra information needed to populate results.html selection that
    # allows to select which test results must be shown.
    response_body['available_tests'] = available_tests.keys()
    response_body['selected_test'] = test

    descrpath = filepath.replace('.json', '.html')
    if os.path.isfile(descrpath):
        filep = open(descrpath, 'rb')
        response_body['description'] = filep.read()
        filep.close()

    # Provide the web user interface some settings it needs, but only if they
    # were not already provided by the `.local` file.
    for variable in COPY_CONFIG_VARIABLES:
        if not variable in response_body:
            response_body[variable] = CONFIG[variable]

    # Note: DO NOT sort keys here: order MUST be preserved
    indent, mimetype = None, 'application/json'
    if 'debug' in dictionary and utils.intify(dictionary['debug'][0]):
        indent, mimetype = 4, 'text/plain'

    response = Message()
    body = json.dumps(response_body, indent=indent)
    response.compose(code='200', reason='Ok', body=body, mimetype=mimetype)
    stream.send_response(request, response)
示例#5
0
def signature_path(basedir, vinfo):
    ''' Return signature path '''
    name = '.'.join([vinfo, 'tar', 'gz', 'sig'])
    path = utils_path.append(basedir, name, False)
    if not path:
        raise RuntimeError("updater_utils: append() path failed")
    return path
示例#6
0
 def test__3(self):
     ''' Verify that append() does not allow to go above the rootdir '''
     self.assertEqual(
         utils_path.append('/foobar', '../etc/passwd', False),
         None
     )
     self.assertEqual(
         utils_path.append('/foobar',
             six.b('\x2e\x2e\x2fetc\x2fpasswd'),
             False),
         None
     )
     self.assertEqual(
         utils_path.append('/foobar',
             six.b('..%2fetc%2fpasswd'),
             True),
         None
     )
示例#7
0
    def install(self, ctx, body):
        ''' Install new version on Windows '''

        # Make file names

        versiondir = utils_path.append(self.basedir, ctx['vinfo'], False)
        if not versiondir:
            raise RuntimeError("updater_win32: append() path failed")

        exefile = utils_path.join(versiondir, 'neubotw.exe')
        uninst = utils_path.join(versiondir, 'uninstall.exe')

        cmdline = '"%s" start' % exefile
        cmdline_k = '"%s" start -k' % exefile

        #
        # Overwrite the version of Neubot that is executed when
        # the user logs in.
        #
        regkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
          "Software\Microsoft\Windows\CurrentVersion\Run", 0,
          _winreg.KEY_WRITE)
        _winreg.SetValueEx(regkey, "Neubot", 0, _winreg.REG_SZ, cmdline)
        _winreg.CloseKey(regkey)

        # Update the registry to reference the new uninstaller
        regkey = _winreg.OpenKey(_winreg.HKEY_CURRENT_USER,
          "Software\Microsoft\Windows\CurrentVersion\Uninstall\Neubot", 0,
          _winreg.KEY_WRITE)
        _winreg.SetValueEx(regkey, "DisplayName", 0, _winreg.REG_SZ,
          "Neubot " + utils_version.to_canonical(ctx['vinfo']))
        _winreg.SetValueEx(regkey, "UninstallString", 0, _winreg.REG_SZ,
          uninst)
        _winreg.CloseKey(regkey)

        logging.info('updater_win32: updated win32 registry')

        #
        # Run the new version of Neubot and tell it that this
        # version should be stopped before proceeding with normal
        # startup.
        #
        # We need to close_fds, because the child process must
        # not inherit the parent handles.  If it did, the listening
        # socket is inherited, and the child process cannot open
        # its own listening socket.  The ``-k`` argument on the
        # command line instructs the child process to request this
        # process to exit.  Of course the child does that before
        # attempting to listen a new socket.
        #
        logging.info('updater_win32: about to exec: %s', cmdline_k)
        subprocess.Popen(cmdline_k, close_fds=True)
示例#8
0
def __verify(basedir, member):
    ''' Verify one member of the tarfile '''

    #
    # Make sure that the combination of basedir and member
    # name falls below basedir.
    #
    utils_path.append(basedir, member.name)

    #
    # The tar archive should contain directories and
    # regular files only.
    #
    if not member.isdir() and not member.isreg():
        raise RuntimeError('updater_install: %s: invalid type' % member.name)

    #
    # Make sure that the owner and group of the file is
    # root, as it should be.
    #
    if member.uid != 0 or member.gid != 0:
        raise RuntimeError('updater_install: %s: invalid uid/gid' % member.name)
示例#9
0
    def walk_generic(self, test, index):
        """ Walk over the results of a generic test """

        filename = "%s.pickle" % test
        if index != None:
            filename += "." + str(int(index))

        fullpath = utils_path.append(self.proxy.datadir, filename, False)
        if not fullpath:
            return []

        if not os.path.isfile(fullpath):
            return []

        filep = open(fullpath, "rb")
        content = filep.read()
        filep.close()

        if not content:
            return []

        return pickle.loads(content)
示例#10
0
def tarball_path(basedir, vinfo):
    ''' Return tarball path '''
    name = '.'.join([vinfo, 'tar', 'gz'])
    path = utils_path.append(basedir, name)
    return path
示例#11
0
    def process_request(self, stream, request):
        ''' Process a request and generate the response '''

        response = Message()

        if not request.uri.startswith("/"):
            response.compose(code="403", reason="Forbidden",
                             body="403 Forbidden")
            stream.send_response(request, response)
            return

        for prefix, child in self.childs.items():
            if request.uri.startswith(prefix):
                child.process_request(stream, request)
                return

        rootdir = self.conf.get("http.server.rootdir", "")
        if not rootdir:
            response.compose(code="403", reason="Forbidden",
                             body="403 Forbidden")
            stream.send_response(request, response)
            return

        if request.uri == "/":
            response.compose_redirect(stream, "/api/index")
            stream.send_response(request, response)
            return

        if '?' in request.uri:
            request_uri = request.uri.split('?')[0]
        else:
            request_uri = request.uri

        fullpath = utils_path.append(rootdir, request_uri, True)
        if not fullpath:
            response.compose(code="403", reason="Forbidden",
                             body="403 Forbidden")
            stream.send_response(request, response)
            return

        try:
            filep = open(fullpath, "rb")
        except (IOError, OSError):
            logging.error("HTTP: Not Found: %s (WWWDIR: %s)",
                          fullpath, rootdir)
            response.compose(code="404", reason="Not Found",
                             body="404 Not Found")
            stream.send_response(request, response)
            return

        if self.conf.get("http.server.mime", True):
            mimetype, encoding = mimetypes.guess_type(fullpath)

            # Do not attempt SSI if the resource is, say, gzipped
            if not encoding:
                if mimetype == "text/html":
                    ssi = self.conf.get("http.server.ssi", False)
                    if ssi:
                        body = ssi_replace(rootdir, filep)
                        filep = StringIO.StringIO(body)

                #XXX Do we need to enforce the charset?
                if mimetype in ("text/html", "application/x-javascript"):
                    mimetype += "; charset=UTF-8"
            else:
                response["content-encoding"] = encoding

        else:
            mimetype = "text/plain"

        response.compose(code="200", reason="Ok", body=filep,
                         mimetype=mimetype)
        if request.method == "HEAD":
            utils.safe_seek(filep, 0, os.SEEK_END)
        stream.send_response(request, response)
示例#12
0
def ssi_open(rootdir, path, mode):
    ''' Wrapper for open() that makes security checks '''
    path = utils_path.append(rootdir, path, False)
    if not path:
        raise ValueError("ssi: Path name above root directory")
    return open(path, mode)
示例#13
0
import cgi
import os

from neubot.compat import json
from neubot.config import CONFIG
from neubot.http.message import Message
from neubot.utils_api import NotImplementedTest

from neubot import utils_hier
from neubot import utils_path
from neubot import utils

# Directory that contains the description of each test, which consists of
# two files per test: a JSON file and an HTML file.
TESTDIR = utils_path.append(utils_hier.WWWDIR, "test")

# Config variables to be copied to output: they allow ordinary users to
# configure the appearance of results.html.
COPY_CONFIG_VARIABLES = (
    "www_no_description",
    "www_no_legend",
    "www_no_plot",
    "www_no_split_by_ip",
    "www_no_table",
    "www_no_title",
)


def api_results(stream, request, query):
    """ Populates www/results.html page """
示例#14
0
 def test__5(self):
     ''' Test append() squeezes after-join() multiple slashes '''
     self.assertEqual(utils_path.append('/foo', '/bar'), '/foo/bar')
def signature_path(basedir, vinfo):
    ''' Return signature path '''
    name = '.'.join([vinfo, 'tar', 'gz', 'sig'])
    path = utils_path.append(basedir, name)
    return path