Ejemplo n.º 1
0
    async def __anit__(self, certdir=None):

        await s_base.Base.__anit__(self)

        self._shareLoopTasks = set()

        self.certdir = s_certdir.CertDir(path=certdir)

        self.televers = s_telepath.televers

        self.addr = None  # our main listen address
        self.cells = {}  # all cells are shared.  not all shared are cells.
        self.shared = {}  # objects provided by daemon
        self.listenservers = []  # the sockets we're listening on
        self.links = set()

        self.sessions = {}

        self.mesgfuncs = {
            'tele:syn': self._onTeleSyn,
            'task:init': self._onTaskInit,
            'share:fini': self._onShareFini,

            # task version 2 API
            't2:init': self._onTaskV2Init,
        }

        self.onfini(self._onDmonFini)
Ejemplo n.º 2
0
    async def test_storm_http_inject_ca(self):

        with self.getTestDir() as dirn:
            cdir = s_common.gendir(dirn, 'certs')
            cadir = s_common.gendir(cdir, 'cas')
            tdir = s_certdir.CertDir(cdir)
            tdir.genCaCert('somelocalca')
            tdir.genHostCert('localhost', signas='somelocalca')

            localkeyfp = tdir.getHostKeyPath('localhost')
            localcertfp = tdir.getHostCertPath('localhost')
            shutil.copyfile(localkeyfp, s_common.genpath(dirn, 'sslkey.pem'))
            shutil.copyfile(localcertfp, s_common.genpath(dirn, 'sslcert.pem'))

            tlscadir = s_common.gendir(dirn, 'cadir')
            for fn in os.listdir(cadir):
                if fn.endswith('.crt'):
                    shutil.copyfile(os.path.join(cadir, fn),
                                    os.path.join(tlscadir, fn))

            async with self.getTestCore(dirn=dirn) as core:

                root = await core.auth.getUserByName('root')
                await root.setPasswd('root')

                addr, port = await core.addHttpsPort(0)
                core.addHttpApi('/api/v0/test', s_test.HttpReflector,
                                {'cell': core})
                url = f'https://*****:*****@localhost:{port}/api/v0/test'
                opts = {'vars': {'url': url}}
                q = '''
                $params=((foo, bar), (key, valu))
                $resp = $lib.inet.http.get($url, params=$params)
                return ( ($resp.code, $resp.err) )
                '''
                code, (errname, _) = await core.callStorm(q, opts=opts)
                self.eq(code, -1)
                self.eq('ClientConnectorCertificateError', errname)

            conf = {'tls:ca:dir': tlscadir}
            async with self.getTestCore(dirn=dirn, conf=conf) as core:
                addr, port = await core.addHttpsPort(0)
                core.addHttpApi('/api/v0/test', s_test.HttpReflector,
                                {'cell': core})
                url = f'https://*****:*****@localhost:{port}/api/v0/test'
                opts = {'vars': {'url': url}}
                q = '''
                $params=((foo, bar), (key, valu))
                $resp = $lib.inet.http.get($url, params=$params)
                return ( $resp.json() )
                '''
                resp = await core.callStorm(q, opts=opts)
                data = resp.get('result')
                self.eq(data.get('params'), {
                    'key': ('valu', ),
                    'foo': ('bar', )
                })
Ejemplo n.º 3
0
    def getCertDir(self):
        '''
        Get a test CertDir object.

        Yields:
            s_certdir.CertDir: A certdir object based out of a temp directory.
        '''
        # create a temp folder and make it a cert dir
        with self.getTestDir() as dirname:
            yield s_certdir.CertDir(path=dirname)
Ejemplo n.º 4
0
    async def test_axon_tlscapath(self):

        with self.getTestDir() as dirn:
            cdir = s_common.gendir(dirn, 'certs')
            cadir = s_common.gendir(cdir, 'cas')
            tdir = s_certdir.CertDir(cdir)
            tdir.genCaCert('somelocalca')
            tdir.genHostCert('localhost', signas='somelocalca')

            localkeyfp = tdir.getHostKeyPath('localhost')
            localcertfp = tdir.getHostCertPath('localhost')
            shutil.copyfile(localkeyfp, s_common.genpath(dirn, 'sslkey.pem'))
            shutil.copyfile(localcertfp, s_common.genpath(dirn, 'sslcert.pem'))

            tlscadir = s_common.gendir(dirn, 'cadir')
            for fn in os.listdir(cadir):
                if fn.endswith('.crt'):
                    shutil.copyfile(os.path.join(cadir, fn), os.path.join(tlscadir, fn))

            conf = {'auth:passwd': 'root'}
            async with self.getTestAxon(dirn=dirn, conf=conf) as axon:
                host, port = await axon.addHttpsPort(0, host='127.0.0.1')
                url = f'https://*****:*****@127.0.0.1:{port}/api/v1/active'
                resp = await axon.wget(url)
                self.false(resp.get('ok'))
                self.isin('unable to get local issuer certificate', resp.get('mesg'))

                retn = await axon.put(abuf)
                self.eq(retn, asdfretn)
                axon.addHttpApi('/api/v1/pushfile', HttpPushFile, {'cell': axon})
                url = f'https://*****:*****@127.0.0.1:{port}/api/v1/pushfile'
                resp = await axon.wput(asdfhash, url)
                self.false(resp.get('ok'))
                self.isin('unable to get local issuer certificate', resp.get('mesg'))

                resp = await axon.postfiles(fields, url)
                self.false(resp.get('ok'))
                self.isin('unable to get local issuer certificate', resp.get('err'))

            conf = {'auth:passwd': 'root', 'tls:ca:dir': tlscadir}
            async with self.getTestAxon(dirn=dirn, conf=conf) as axon:
                host, port = await axon.addHttpsPort(0, host='127.0.0.1')
                url = f'https://*****:*****@localhost:{port}/api/v1/active'
                resp = await axon.wget(url)
                self.true(resp.get('ok'))

                retn = await axon.put(abuf)
                self.eq(retn, asdfretn)
                axon.addHttpApi('/api/v1/pushfile', HttpPushFile, {'cell': axon})
                url = f'https://*****:*****@localhost:{port}/api/v1/pushfile'
                resp = await axon.wput(asdfhash, url)
                self.true(resp.get('ok'))

                resp = await axon.postfiles(fields, url)
                self.true(resp.get('ok'))
Ejemplo n.º 5
0
    def _listen(self):

        host = self.link[1].get('host')
        port = self.link[1].get('port')

        sock = socket.socket()
        sock.bind((host, port))

        sock.listen(100)

        self.link[1]['port'] = sock.getsockname()[1]

        certdir = self.link[1].get('certdir')
        cdir = s_certdir.CertDir(path=certdir)

        hostname = socket.gethostname()

        cafile = self.link[1].get('cafile')
        if cafile is None:
            caname = self.link[1].get('ca')
            if caname is not None:
                cafile = cdir.getCaCertPath(caname)

        certfile = self.link[1].get('certfile')
        if certfile is None:
            certfile = cdir.getHostCertPath(hostname)

        keyfile = self.link[1].get('keyfile')
        if keyfile is None:
            keyfile = cdir.getHostKeyPath(hostname)

        sslopts = dict(
            server_side=True,
            ca_certs=cafile,
            keyfile=keyfile,
            certfile=certfile,
            cert_reqs=ssl.CERT_NONE,
            do_handshake_on_connect=False,
            ssl_version=ssl.PROTOCOL_TLSv1,
        )

        # if they give a cafile to the server, require client certs
        if cafile is not None:
            sslopts['cert_reqs'] = ssl.CERT_REQUIRED

        wrap = ssl.wrap_socket(sock, **sslopts)

        sock = s_socket.Socket(wrap)
        sock.on('link:sock:accept', self._onSslAccept)

        return sock
Ejemplo n.º 6
0
    def _connect(self):
        sock = socket.socket()

        host = self.link[1].get('host')
        port = self.link[1].get('port')

        cafile = None
        keyfile = None
        certfile = None

        user = self.link[1].get('user')
        certdir = self.link[1].get('certdir')

        cdir = s_certdir.CertDir(path=certdir)
        certuser = cdir.getUserForHost(user, host)

        if certuser is not None:
            cafile = cdir.getUserCaPath(certuser)
            keyfile = cdir.getUserKeyPath(certuser)
            certfile = cdir.getUserCertPath(certuser)

        cafile = self.link[1].get('cafile', cafile)
        keyfile = self.link[1].get('keyfile', keyfile)
        certfile = self.link[1].get('certfile', certfile)

        sslopts = dict(ca_certs=cafile,
                       keyfile=keyfile,
                       certfile=certfile,
                       cert_reqs=ssl.CERT_REQUIRED,
                       ssl_version=ssl.PROTOCOL_TLSv1)

        if self.link[1].get('nocheck'):
            sslopts['cert_reqs'] = ssl.CERT_NONE

        try:
            sock.connect((host, port))
        except s_common.sockerrs as e:
            sock.close()
            raiseSockError(self.link, e)

        try:
            wrap = ssl.wrap_socket(sock, **sslopts)
        except ssl.SSLError as e:
            sock.close()
            raise s_common.LinkErr(self.link, str(e))

        return s_socket.Socket(wrap)
Ejemplo n.º 7
0
async def _main(argv, outp):
    pars = getArgParser()
    opts = pars.parse_args(argv)

    cdir = s_certdir.CertDir(path=opts.certdir)

    async with await s_telepath.openurl(opts.aha) as prox:

        # try:
        #     s_version.reqVersion(prox._getSynVers(), reqver)
        # except s_exc.BadVersion as e:  # pragma: no cover
        #     valu = s_version.fmtVersion(*e.get('valu'))
        #     outp.printf(f'Proxy version {valu} is outside of the aha supported range ({reqver}).')
        #     return 1

        name = opts.name

        if opts.ca:
            # A User may only have get permissions; so try get first
            # before attempting to generate a new CA.
            certbyts = await prox.getCaCert(name)
            if not certbyts:
                certbyts = await prox.genCaCert(name)
            cert = crypto.load_certificate(crypto.FILETYPE_PEM, certbyts)
            path = cdir._saveCertTo(cert, 'cas', f'{name}.crt')
            outp.printf(f'Saved CA cert to {path}')
            return 0
        elif opts.server:
            csr = cdir.genHostCsr(name, outp=outp)
            certbyts = await prox.signHostCsr(csr.decode(),
                                              signas=opts.network,
                                              sans=opts.server_sans)
            cert = crypto.load_certificate(crypto.FILETYPE_PEM, certbyts)
            path = cdir._saveCertTo(cert, 'hosts', f'{name}.crt')
            outp.printf(f'crt saved: {path}')
            return 0
        else:
            csr = cdir.genUserCsr(name, outp=outp)
            certbyts = await prox.signUserCsr(csr.decode(),
                                              signas=opts.network)
            cert = crypto.load_certificate(crypto.FILETYPE_PEM, certbyts)
            path = cdir._saveCertTo(cert, 'users', f'{name}.crt')
            outp.printf(f'crt saved: {path}')
            return 0
Ejemplo n.º 8
0
    async def __anit__(self, dirn=None, conf=None):

        await s_base.Base.__anit__(self)

        self.dirn = None
        if dirn is not None:
            self.dirn = s_common.gendir(dirn)

        self._shareLoopTasks = set()

        yaml = self._loadDmonYaml()
        if conf is not None:
            yaml.update(conf)

        self.conf = s_common.config(yaml, self.confdefs)
        self.certdir = s_certdir.CertDir(os.path.join(dirn, 'certs'))

        self.mods = {}  # keep refs to mods we load ( mostly for testing )
        self.televers = s_telepath.televers

        self.addr = None  # our main listen address
        self.cells = {}  # all cells are shared.  not all shared are cells.
        self.shared = {}  # objects provided by daemon
        self.listenservers = []  # the sockets we're listening on
        self.connectedlinks = []  # the links we're currently connected on

        self.sessions = {}

        self.mesgfuncs = {
            'tele:syn': self._onTeleSyn,
            'task:init': self._onTaskInit,
            'share:fini': self._onShareFini,

            # task version 2 API
            't2:init': self._onTaskV2Init,
        }

        self.onfini(self._onDmonFini)

        await self._loadDmonConf()
        await self._loadDmonCells()
Ejemplo n.º 9
0
    async def addHttpsPort(self, port, host='0.0.0.0', sslctx=None):

        addr = socket.gethostbyname(host)

        if sslctx is None:

            pkeypath = os.path.join(self.dirn, 'sslkey.pem')
            certpath = os.path.join(self.dirn, 'sslcert.pem')

            if not os.path.isfile(certpath):
                logger.warning('NO CERTIFICATE FOUND! generating self-signed certificate.')
                with s_common.getTempDir() as dirn:
                    cdir = s_certdir.CertDir(dirn)
                    pkey, cert = cdir.genHostCert('cortex')
                    cdir.savePkeyPem(pkey, pkeypath)
                    cdir.saveCertPem(cert, certpath)

            sslctx = self.initSslCtx(certpath, pkeypath)

        serv = self.wapp.listen(port, address=addr, ssl_options=sslctx)
        self.httpds.append(serv)
        return list(serv._sockets.values())[0].getsockname()
Ejemplo n.º 10
0
def main(argv, outp=None):

    if outp is None:
        outp = s_output.OutPut()

    pars = argparse.ArgumentParser(prog='easycert', description=descr)

    pars.add_argument('--certdir',
                      default='~/.syn/certs',
                      help='Directory for certs/keys')
    pars.add_argument('--signas',
                      help='sign the new cert with the given cert name')
    pars.add_argument('--ca',
                      default=False,
                      action='store_true',
                      help='mark the certificate as a CA/CRL signer')
    pars.add_argument('--server',
                      default=False,
                      action='store_true',
                      help='mark the certificate as a server')
    pars.add_argument('--server-sans',
                      help='server cert subject alternate names')
    pars.add_argument('--csr',
                      default=False,
                      action='store_true',
                      help='generate a cert signing request')
    pars.add_argument('--sign-csr',
                      default=False,
                      action='store_true',
                      help='sign a cert signing request')
    pars.add_argument(
        'name',
        help='common name for the certificate (or filename for CSR signing)')

    opts = pars.parse_args(argv)

    cdir = s_certdir.CertDir(path=opts.certdir)

    try:

        if opts.sign_csr:

            if opts.signas is None:
                outp.printf('--sign-csr requires --signas')
                return -1

            xcsr = cdir._loadCsrPath(opts.name)
            if xcsr is None:
                outp.printf('csr not found: %s' % (opts.name, ))
                return -1

            if opts.server:
                cdir.signHostCsr(xcsr, opts.signas, outp=outp)
                return 0

            cdir.signUserCsr(xcsr, opts.signas, outp=outp)
            return 0

        if opts.csr:

            if opts.ca:
                cdir.genCaCsr(opts.name, outp=outp)
                raise Exception('CSR for CA cert not supported (yet)')

            if opts.server:
                cdir.genHostCsr(opts.name, outp=outp)
                return 0

            cdir.genUserCsr(opts.name, outp=outp)
            return 0

        if opts.ca:
            cdir.genCaCert(opts.name, signas=opts.signas, outp=outp)
            return 0

        if opts.server:
            cdir.genHostCert(opts.name,
                             signas=opts.signas,
                             outp=outp,
                             sans=opts.server_sans)
            return 0

        cdir.genUserCert(opts.name, signas=opts.signas, outp=outp)
        return 0

    except s_common.DupFileName as e:
        outp.printf('file exists: %s' % (e.errinfo.get('path'), ))
        return -1
Ejemplo n.º 11
0
    def test_webapp_ssl(self):

        # tornado does not support windows (yet)
        self.thisHostMustNot(platform='windows')

        foo = Foo()

        with self.getTestDir() as dirname:

            cdir = s_certdir.CertDir(path=dirname)

            cdir.genCaCert('syntest')  # Generate a new CA
            cdir.genUserCert(
                '*****@*****.**', signas='syntest'
            )  # Generate a new user cert and key, signed by the new CA
            cdir.genHostCert(
                'localhost', signas='syntest'
            )  # Generate a new server cert and key, signed by the new CA

            ca_cert = cdir.getCaCertPath('syntest')
            host_key = cdir.getHostKeyPath('localhost')
            host_cert = cdir.getHostCertPath('localhost')

            ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
            ssl_ctx.verify_mode = ssl.CERT_REQUIRED
            ssl_ctx.load_cert_chain(host_cert, host_key)
            ssl_ctx.load_verify_locations(ca_cert)

            conf = {'server': {'ssl_options': ssl_ctx}}
            wapp = s_webapp.WebApp(**conf)
            wapp.listen(0, host='127.0.0.1')
            wapp.addApiPath('/v1/bar', foo.bar)

            client = AsyncHTTPClient(self.io_loop)
            port = wapp.getServBinds()[0][1]
            http_url = 'http://127.0.0.1:%d/v1/bar' % port
            https_url = 'https://127.0.0.1:%d/v1/bar' % port
            user_key = cdir.getUserKeyPath('*****@*****.**')
            user_cert = cdir.getUserCertPath('*****@*****.**')
            client_opts = {
                'ca_certs': ca_cert,
                'client_key': user_key,
                'client_cert': user_cert
            }

            # Assert that the request fails w/ http protocol
            with self.raises(TstSSLConnectionResetErr):
                resp = yield client.fetch(http_url)

            # Assert that the request fails w/ no client SSL config
            with self.raises(ssl.SSLError):
                resp = yield client.fetch(https_url)

            # Assert that the request fails w/ no client SSL config, even if client does not validate cert
            # (server must also validate client cert)
            with self.raises(TstSSLInvalidClientCertErr):
                resp = yield client.fetch(https_url, validate_cert=False)

            resp = yield client.fetch(https_url, **client_opts)
            resp = json.loads(resp.body.decode('utf-8'))

            self.eq(resp.get('ret'), 'baz')
            self.eq(resp.get('status'), 'ok')

            wapp.fini()
Ejemplo n.º 12
0
 def getCertDir(self):
     # create a temp folder and make it a cert dir
     with self.getTestDir() as dirname:
         cdir = s_certdir.CertDir(path=dirname)
         yield cdir
Ejemplo n.º 13
0
 def test_certdir_invalidpath(self):
     with self.raises(s_exc.SynErr):
         s_certdir.CertDir(path=1)
Ejemplo n.º 14
0
async def openurl(url, **opts):
    '''
    Open a URL to a remote telepath object.

    Args:
        url (str): A telepath URL.
        **opts (dict): Telepath connect options.

    Returns:
        (synapse.telepath.Proxy): A telepath proxy object.

    The telepath proxy may then be used for sync or async calls:

        proxy = openurl(url)
        value = proxy.getFooThing()

    ... or ...

        proxy = await openurl(url)
        valu = await proxy.getFooThing()

    ... or ...

        async with await openurl(url) as proxy:
            valu = await proxy.getFooThing()
    '''
    if url.find('://') == -1:
        newurl = alias(url)
        if newurl is None:
            raise s_exc.BadUrl(
                mesg=f':// not found in [{url}] and no alias found!', url=url)
        url = newurl

    info = s_urlhelp.chopurl(url)
    info.update(opts)

    scheme = info.get('scheme')

    if '+' in scheme:
        scheme, disc = scheme.split('+', 1)
        # Discovery protocols modify info dict inband?
        if disc == 'consul':
            await disc_consul(info)

        else:
            raise s_exc.BadUrl(mesg=f'Unknown discovery protocol [{disc}].',
                               disc=disc)

    host = info.get('host')
    port = info.get('port')

    auth = None

    user = info.get('user')
    if user is not None:
        passwd = info.get('passwd')
        auth = (user, {'passwd': passwd})

    if scheme == 'cell':
        # cell:///path/to/celldir:share
        # cell://rel/path/to/celldir:share
        path = info.get('path')
        name = info.get('name', '*')

        # support cell://<relpath>/<to>/<cell>
        # by detecting host...
        host = info.get('host')
        if host:
            path = path.strip('/')
            path = os.path.join(host, path)

        if ':' in path:
            path, name = path.split(':')

        full = os.path.join(path, 'sock')
        link = await s_link.unixconnect(full)

    elif scheme == 'unix':
        # unix:///path/to/sock:share
        name = '*'
        path = info.get('path')
        if ':' in path:
            path, name = path.split(':')
        link = await s_link.unixconnect(path)

    else:

        path = info.get('path')
        name = info.get('name', path[1:])

        sslctx = None
        if scheme == 'ssl':

            certname = None
            certpath = None

            certdir = opts.get('certdir')

            query = info.get('query')
            if query is not None:
                certpath = query.get('certdir')
                certname = query.get('certname')

            if certdir is None:
                certdir = s_certdir.CertDir(certpath)

            sslctx = certdir.getClientSSLContext(certname=certname)

        link = await s_link.connect(host, port, ssl=sslctx)

    prox = await Proxy.anit(link, name)
    prox.onfini(link)

    try:
        await prox.handshake(auth=auth)

    except Exception:
        await prox.fini()
        raise

    return prox
Ejemplo n.º 15
0
async def openurl(url, **opts):
    '''
    Open a URL to a remote telepath object.

    Args:
        url (str): A telepath URL.
        **opts (dict): Telepath connect options.

    Returns:
        (synapse.telepath.Proxy): A telepath proxy object.

    The telepath proxy may then be used for sync or async calls:

        proxy = openurl(url)
        value = proxy.getFooThing()

    ... or ...

        proxy = await openurl(url)
        valu = await proxy.getFooThing()

    ... or ...

        async with await openurl(url) as proxy:
            valu = await proxy.getFooThing()
    '''
    if url.find('://') == -1:
        newurl = alias(url)
        if newurl is None:
            raise s_exc.BadUrl(f':// not found in [{url}] and no alias found!')
        url = newurl

    info = s_urlhelp.chopurl(url)
    info.update(opts)

    host = info.get('host')
    port = info.get('port')
    name = info.get('path')[1:]

    auth = None

    user = info.get('user')
    if user is not None:
        passwd = info.get('passwd')
        auth = (user, {'passwd': passwd})

    sslctx = None
    if info.get('scheme') == 'ssl':
        certpath = info.get('certdir')
        certdir = s_certdir.CertDir(certpath)
        sslctx = certdir.getClientSSLContext()

    link = await s_link.connect(host, port, ssl=sslctx)

    prox = await Proxy.anit(link, name)
    prox.onfini(link)

    try:
        await prox.handshake(auth=auth)

    except Exception as e:
        await prox.fini()
        raise

    return prox