Exemple #1
0
    def sendGlobalRequest(self, request, data, wantReply=0):
        """
        Send a global request for this connection.  Current this is only used
        for remote->local TCP forwarding.

        @type request:      L{bytes}
        @type data:         L{bytes}
        @type wantReply:    L{bool}
        @rtype              C{Deferred}/L{None}
        """
        self.transport.sendPacket(
            MSG_GLOBAL_REQUEST,
            common.NS(request) + (wantReply and b'\xff' or b'\x00') + data)
        if wantReply:
            d = defer.Deferred()
            self.deferreds['global'].append(d)
            return d
Exemple #2
0
    def test_CHANNEL_REQUEST_failure(self):
        """
        Test that channel requests that fail send MSG_CHANNEL_FAILURE.
        """
        channel = TestChannel()
        self._openChannel(channel)
        d = self.conn.ssh_CHANNEL_REQUEST('\x00\x00\x00\x00' +
                                          common.NS('test') + '\xff')

        def check(result):
            self.assertEqual(
                self.transport.packets,
                [(connection.MSG_CHANNEL_FAILURE, '\x00\x00\x00\xff')])

        d.addCallback(self.fail)
        d.addErrback(check)
        return d
Exemple #3
0
    def test_fromPrivateBlobDSA(self):
        """
        A private DSA key is correctly generated from a private key blob.
        """
        dsaBlob = (
            common.NS(b'ssh-dss') +
            common.MP(keydata.DSAData['p']) +
            common.MP(keydata.DSAData['q']) +
            common.MP(keydata.DSAData['g']) +
            common.MP(keydata.DSAData['y']) +
            common.MP(keydata.DSAData['x'])
            )

        dsaKey = keys.Key._fromString_PRIVATE_BLOB(dsaBlob)

        self.assertFalse(dsaKey.isPublic())
        self.assertEqual(keydata.DSAData, dsaKey.data())
Exemple #4
0
    def sendExtendedData(self, channel, dataType, data):
        """
        Send extended data to a channel.  This should not normally be used:
        instead use channel.writeExtendedData(data, dataType) as it manages
        the window automatically.

        @type channel:  subclass of L{SSHChannel}
        @type dataType: L{int}
        @type data:     L{bytes}
        """
        if channel.localClosed:
            return  # we're already closed
        self.transport.sendPacket(
            MSG_CHANNEL_EXTENDED_DATA,
            struct.pack(">2L", self.channelsToRemoteChannel[channel], dataType)
            + common.NS(data),
        )
Exemple #5
0
 def test_lookupSubsystemDoesNotNeedISession(self):
     """
     Previously, if one only wanted to implement a subsystem, an ISession
     adapter wasn't needed because subsystems were looked up using the
     lookupSubsystem method on the avatar.
     """
     s = session.SSHSession(avatar=SubsystemOnlyAvatar(),
                            conn=StubConnection())
     ret = s.request_subsystem(common.NS('subsystem') + 'data')
     self.assertTrue(ret)
     self.assertIsNot(s.client, None)
     self.assertIs(s.conn.closes.get(s), None)
     s.eofReceived()
     self.assertTrue(s.conn.closes.get(s))
     # these should not raise errors
     s.loseConnection()
     s.closed()
Exemple #6
0
 def test_requestExecWithData(self):
     """
     When a client executes a command, it should be able to give pass data
     back and forth.
     """
     ret = self.session.requestReceived('exec', common.NS('repeat hello'))
     self.assertTrue(ret)
     self.assertSessionIsStubSession()
     self.session.dataReceived('some data')
     self.assertEquals(self.session.session.execTransport.data, 'some data')
     self.assertEquals(self.session.conn.data[self.session],
                       ['hello', 'some data', '\r\n'])
     self.session.eofReceived()
     self.session.closeReceived()
     self.session.closed()
     self.assertTrue(self.session.session.execTransport.closed)
     self.assertEquals(self.session.conn.requests[self.session],
                       [('exit-status', '\x00\x00\x00\x00', False)])
Exemple #7
0
    def test_fromPrivateBlobRSA(self):
        """
        A private RSA key is correctly generated from a private key blob.
        """
        rsaBlob = (
            common.NS(b'ssh-rsa') +
            common.MP(keydata.RSAData['n']) +
            common.MP(keydata.RSAData['e']) +
            common.MP(keydata.RSAData['d']) +
            common.MP(keydata.RSAData['u']) +
            common.MP(keydata.RSAData['p']) +
            common.MP(keydata.RSAData['q'])
            )

        rsaKey = keys.Key._fromString_PRIVATE_BLOB(rsaBlob)

        self.assertFalse(rsaKey.isPublic())
        self.assertEqual(keydata.RSAData, rsaKey.data())
Exemple #8
0
    def test_fromBlobRSA(self):
        """
        A public RSA key is correctly generated from a public key blob.
        """
        rsaPublicData = {
            'n': keydata.RSAData['n'],
            'e': keydata.RSAData['e'],
            }
        rsaBlob = (
            common.NS(b'ssh-rsa') +
            common.MP(rsaPublicData['e']) +
            common.MP(rsaPublicData['n'])
            )

        rsaKey = keys.Key.fromString(rsaBlob)

        self.assertTrue(rsaKey.isPublic())
        self.assertEqual(rsaPublicData, rsaKey.data())
Exemple #9
0
    def channelOpen(self, data):
        self.data = []
        self.running = True

        if self.start_defer:
            log.debug("Channel %s is open, calling deferred", self.id)
            self.start_defer.callback(self)
            self.conn.sendRequest(self,
                                  'exec',
                                  common.NS(self.command),
                                  wantReply=True).addCallback(
                                      self._cbExecSendRequest)
        else:
            # A missing start defer means that we are no longer expected to do anything when the channel opens
            # It probably means we gave up on this connection and failed the job, but later the channel opened up
            # correctly.
            log.warning("Channel open delayed, giving up and closing")
            self.loseConnection()
Exemple #10
0
    def openChannel(self, channel, extra=''):
        """
        Open a new channel on this connection.

        @type channel:  subclass of C{SSHChannel}
        @type extra:    C{str}
        """
        log.msg('opening channel %s with %s %s' %
                (self.localChannelID, channel.localWindowSize,
                 channel.localMaxPacket))
        self.transport.sendPacket(
            MSG_CHANNEL_OPEN,
            common.NS(channel.name) +
            struct.pack('>3L', self.localChannelID, channel.localWindowSize,
                        channel.localMaxPacket) + extra)
        channel.id = self.localChannelID
        self.channels[self.localChannelID] = channel
        self.localChannelID += 1
Exemple #11
0
 def test_sendExtendedData(self):
     """
     Test that channel extended data messages are sent in the right format.
     """
     channel = TestChannel()
     self._openChannel(channel)
     self.conn.sendExtendedData(channel, 1, b"test")
     channel.localClosed = True
     self.conn.sendExtendedData(channel, 2, b"test2")
     self.assertEqual(
         self.transport.packets,
         [
             (
                 connection.MSG_CHANNEL_EXTENDED_DATA,
                 b"\x00\x00\x00\xff" + b"\x00\x00\x00\x01" + common.NS(b"test"),
             )
         ],
     )
Exemple #12
0
 def test_openChannel(self):
     """
     Test that open channel messages are sent in the right format.
     """
     channel = TestChannel()
     self.conn.openChannel(channel, b"aaaa")
     self.assertEqual(
         self.transport.packets,
         [
             (
                 connection.MSG_CHANNEL_OPEN,
                 common.NS(b"TestChannel")
                 + b"\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x80\x00aaaa",
             )
         ],
     )
     self.assertEqual(channel.id, 0)
     self.assertEqual(self.conn.localChannelID, 1)
Exemple #13
0
 def test_privateBlobRSA(self):
     """
     L{keys.Key.privateBlob} returns the SSH protocol-level format of an
     RSA private key.
     """
     from cryptography.hazmat.primitives.asymmetric import rsa
     numbers = self.rsaObj.private_numbers()
     u = rsa.rsa_crt_iqmp(numbers.q, numbers.p)
     self.assertEqual(
         keys.Key(self.rsaObj).privateBlob(),
         common.NS(b'ssh-rsa') +
         common.MP(self.rsaObj.private_numbers().public_numbers.n) +
         common.MP(self.rsaObj.private_numbers().public_numbers.e) +
         common.MP(self.rsaObj.private_numbers().d) +
         common.MP(u) +
         common.MP(self.rsaObj.private_numbers().p) +
         common.MP(self.rsaObj.private_numbers().q)
         )
Exemple #14
0
 def test_CHANNEL_OPEN(self):
     """
     Test that open channel packets cause a channel to be created and
     opened or a failure message to be returned.
     """
     del self.transport.avatar
     self.conn.ssh_CHANNEL_OPEN(
         common.NS(b"TestChannel") + b"\x00\x00\x00\x01" * 4)
     self.assertTrue(self.conn.channel.gotOpen)
     self.assertEqual(self.conn.channel.conn, self.conn)
     self.assertEqual(self.conn.channel.data, b"\x00\x00\x00\x01")
     self.assertEqual(self.conn.channel.specificData, b"\x00\x00\x00\x01")
     self.assertEqual(self.conn.channel.remoteWindowLeft, 1)
     self.assertEqual(self.conn.channel.remoteMaxPacket, 1)
     self.assertEqual(
         self.transport.packets,
         [(
             connection.MSG_CHANNEL_OPEN_CONFIRMATION,
             b"\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02\x00\x00"
             b"\x00\x00\x80\x00",
         )],
     )
     self.transport.packets = []
     self.conn.ssh_CHANNEL_OPEN(
         common.NS(b"BadChannel") + b"\x00\x00\x00\x02" * 4)
     self.flushLoggedErrors()
     self.assertEqual(
         self.transport.packets,
         [(
             connection.MSG_CHANNEL_OPEN_FAILURE,
             b"\x00\x00\x00\x02\x00\x00\x00\x03" +
             common.NS(b"unknown channel") + common.NS(b""),
         )],
     )
     self.transport.packets = []
     self.conn.ssh_CHANNEL_OPEN(
         common.NS(b"ErrorChannel") + b"\x00\x00\x00\x02" * 4)
     self.flushLoggedErrors()
     self.assertEqual(
         self.transport.packets,
         [(
             connection.MSG_CHANNEL_OPEN_FAILURE,
             b"\x00\x00\x00\x02\x00\x00\x00\x02" +
             common.NS(b"unknown failure") + common.NS(b""),
         )],
     )
    def test_fromBlobDSA(self):
        """
        A public DSA key is correctly generated from a public key blob.
        """
        dsaPublicData = {
            'p': keydata.DSAData['p'],
            'q': keydata.DSAData['q'],
            'g': keydata.DSAData['g'],
            'y': keydata.DSAData['y'],
        }
        dsaBlob = (common.NS(b'ssh-dss') + common.MP(dsaPublicData['p']) +
                   common.MP(dsaPublicData['q']) +
                   common.MP(dsaPublicData['g']) +
                   common.MP(dsaPublicData['y']))

        dsaKey = keys.Key.fromString(dsaBlob)

        self.assertTrue(dsaKey.isPublic())
        self.assertEqual(dsaPublicData, dsaKey.data())
Exemple #16
0
    def test_sessionClose(self):
        """
        Closing a session should notify an SFTP subsystem launched by that
        session.
        """
        # make a session
        testSession = session.SSHSession(conn=FakeConn(), avatar=self.avatar)

        # start an SFTP subsystem on the session
        testSession.request_subsystem(common.NS(b'sftp'))
        sftpServer = testSession.client.transport.proto

        # intercept connectionLost so we can check that it's called
        self.interceptConnectionLost(sftpServer)

        # close session
        testSession.closeReceived()

        self.assertSFTPConnectionLost()
Exemple #17
0
    def openChannel(self, channel, extra=b''):
        """
        Open a new channel on this connection.

        @type channel:  subclass of C{SSHChannel}
        @type extra:    L{bytes}
        """
        self._log.info(
            'opening channel {id} with {localWindowSize} {localMaxPacket}',
            id=self.localChannelID,
            localWindowSize=channel.localWindowSize,
            localMaxPacket=channel.localMaxPacket)
        self.transport.sendPacket(
            MSG_CHANNEL_OPEN,
            common.NS(channel.name) +
            struct.pack('>3L', self.localChannelID, channel.localWindowSize,
                        channel.localMaxPacket) + extra)
        channel.id = self.localChannelID
        self.channels[self.localChannelID] = channel
        self.localChannelID += 1
Exemple #18
0
 def test_requestExecWithData(self):
     """
     When a client executes a command, it should be able to give pass data
     back and forth.
     """
     ret = self.session.requestReceived(b"exec", common.NS(b"repeat hello"))
     self.assertTrue(ret)
     self.assertSessionIsStubSession()
     self.session.dataReceived(b"some data")
     self.assertEqual(self.session.session.execTransport.data, b"some data")
     self.assertEqual(self.session.conn.data[self.session],
                      [b"hello", b"some data", b"\r\n"])
     self.session.eofReceived()
     self.session.closeReceived()
     self.session.closed()
     self.assertTrue(self.session.session.execTransport.closed)
     self.assertEqual(
         self.session.conn.requests[self.session],
         [(b"exit-status", b"\x00\x00\x00\x00", False)],
     )
Exemple #19
0
    def sendRequest(self, channel, requestType, data, wantReply=0):
        """
        Send a request to a channel.

        @type channel:      subclass of C{SSHChannel}
        @type requestType:  C{str}
        @type data:         C{str}
        @type wantReply:    C{bool}
        @rtype              C{Deferred}/C{None}
        """
        if channel.localClosed:
            return
        log.msg('sending request %s' % requestType)
        self.transport.sendPacket(
            MSG_CHANNEL_REQUEST,
            struct.pack('>L', self.channelsToRemoteChannel[channel]) +
            common.NS(requestType) + chr(wantReply) + data)
        if wantReply:
            d = defer.Deferred()
            self.deferreds.setdefault(channel.id, []).append(d)
            return d
Exemple #20
0
    def test_lookupSubsystem_data(self):
        """
        After having looked up a subsystem, data should be passed along to the
        client.  Additionally, subsystems were passed the entire request packet
        as data, instead of just the additional data.

        We check for the additional tidle to verify that the data passed
        through the client.
        """
        #self.session.dataReceived('1')
        # subsystems didn't get extended data
        #self.session.extReceived(connection.EXTENDED_DATA_STDERR, '2')

        self.session.requestReceived('subsystem',
                                     common.NS('TestSubsystem') + 'data')

        self.assertEquals(self.session.conn.data[self.session],
                          ['\x00\x00\x00\x0dTestSubsystemdata~'])
        self.session.dataReceived('more data')
        self.assertEquals(self.session.conn.data[self.session][-1],
                          'more data~')
Exemple #21
0
    def _fromString_PRIVATE_LSH(cls, data):
        """
        Return a private key corresponding to this LSH private key string.
        The LSH private key string format is::
            <s-expression: ('private-key', (<key type>, (<name>, <value>)+))>

        The names for a RSA (key type 'rsa-pkcs1-sha1') key are: n, e, d, p, q.
        The names for a DSA (key type 'dsa') key are: y, g, p, q, x.

        @type data: L{bytes}
        @param data: The key data.

        @return: A new key.
        @rtype: L{twisted.conch.ssh.keys.Key}
        @raises BadKeyError: if the key type is unknown
        """
        sexp = sexpy.parse(data)
        assert sexp[0] == b'private-key'
        kd = {}
        for name, data in sexp[1][1:]:
            kd[name] = common.getMP(common.NS(data))[0]
        if sexp[1][0] == b'dsa':
            assert len(kd) == 5, len(kd)
            return cls._fromDSAComponents(y=kd[b'y'],
                                          g=kd[b'g'],
                                          p=kd[b'p'],
                                          q=kd[b'q'],
                                          x=kd[b'x'])
        elif sexp[1][0] == b'rsa-pkcs1':
            assert len(kd) == 8, len(kd)
            if kd[b'p'] > kd[b'q']:  # Make p smaller than q
                kd[b'p'], kd[b'q'] = kd[b'q'], kd[b'p']
            return cls._fromRSAComponents(n=kd[b'n'],
                                          e=kd[b'e'],
                                          d=kd[b'd'],
                                          p=kd[b'p'],
                                          q=kd[b'q'])

        else:
            raise BadKeyError('unknown lsh key type %s' % (sexp[1][0], ))
Exemple #22
0
    def sendRequest(self, channel, requestType, data, wantReply=0):
        """
        Send a request to a channel.

        @type channel:      subclass of C{SSHChannel}
        @type requestType:  L{bytes}
        @type data:         L{bytes}
        @type wantReply:    L{bool}
        @rtype              C{Deferred}/L{None}
        """
        if channel.localClosed:
            return
        self._log.debug('sending request {requestType}',
                        requestType=requestType)
        self.transport.sendPacket(
            MSG_CHANNEL_REQUEST,
            struct.pack('>L', self.channelsToRemoteChannel[channel]) +
            common.NS(requestType) + (b'\1' if wantReply else b'\0') + data)
        if wantReply:
            d = defer.Deferred()
            self.deferreds.setdefault(channel.id, []).append(d)
            return d
Exemple #23
0
    def channelOpen(self, unused):
        """
        Initialize the channel and send our command to the device.

        @param unused: unused (unused)
        @type unused: string
        @return: Twisted channel
        @rtype: Twisted channel
        """

        log.debug(
            "%s channel %s Opening command channel for %s",
            self.targetIp,
            self.id,
            self.command,
        )
        self.data = ""
        self.stderr = ""

        #  Notes for sendRequest:
        # 'exec'      - execute the following command and exit
        # common.NS() - encodes the command as a length-prefixed string
        # wantReply   - reply to let us know the process has been started
        try:
            result = yield self.conn.sendRequest(self,
                                                 "exec",
                                                 common.NS(self.command),
                                                 wantReply=1)
        except Exception as e:
            log.warn(
                "%s channel %s failed during command execution with error: %s",
                self.targetIp,
                self.id,
                e,
            )
            defer.returnValue([])
        defer.returnValue(result)
Exemple #24
0
    def verify(self, signature, data):
        """
        Returns true if the signature for data is valid for this Key.

        @type signature: C{str}
        @type data: C{str}
        @rtype: C{bool}
        """
        if len(signature) == 40:
            # DSA key with no padding
            signatureType, signature = 'ssh-dss', common.NS(signature)
        else:
            signatureType, signature = common.getNS(signature)
        if signatureType != self.sshType():
            return False
        if self.type() == 'RSA':
            numbers = common.getMP(signature)
            digest = pkcs1Digest(data, self.keyObject.size() / 8)
        elif self.type() == 'DSA':
            signature = common.getNS(signature)[0]
            numbers = [Util.number.bytes_to_long(n) for n in signature[:20],
                       signature[20:]]
            digest = sha1(data).digest()
        return self.keyObject.verify(digest, numbers)
Exemple #25
0
    def channelOpen(self, unused):
        """
        Initialize the channel and send our command to the device.

        @param unused: unused (unused)
        @type unused: string
        @return: Twisted channel
        @rtype: Twisted channel
        """

        log.debug('%s channel %s Opening command channel for %s',
                  self.targetIp, self.conn.localChannelID, self.command)
        self.data = ''
        self.stderr = ''

        #  Notes for sendRequest:
        # 'exec'      - execute the following command and exit
        # common.NS() - encodes the command as a length-prefixed string
        # wantReply   - reply to let us know the process has been started
        d = self.conn.sendRequest(self,
                                  'exec',
                                  common.NS(self.command),
                                  wantReply=1)
        return d
Exemple #26
0
    def _fromString_PUBLIC_LSH(Class, data):
        """
        Return a public key corresponding to this LSH public key string.
        The LSH public key string format is::
            <s-expression: ('public-key', (<key type>, (<name, <value>)+))>

        The names for a RSA (key type 'rsa-pkcs1-sha1') key are: n, e.
        The names for a DSA (key type 'dsa') key are: y, g, p, q.

        @type data: C{str}
        @return: a C{Crypto.PublicKey.pubkey.pubkey} object
        @raises BadKeyError: if the key type is unknown
        """
        sexp = sexpy.parse(base64.decodestring(data[1:-1]))
        assert sexp[0] == 'public-key'
        kd = {}
        for name, data in sexp[1][1:]:
            kd[name] = common.getMP(common.NS(data))[0]
        if sexp[1][0] == 'dsa':
            return Class(DSA.construct((kd['y'], kd['g'], kd['p'], kd['q'])))
        elif sexp[1][0] == 'rsa-pkcs1-sha1':
            return Class(RSA.construct((kd['n'], kd['e'])))
        else:
            raise BadKeyError('unknown lsh key type %s' % sexp[1][0])
Exemple #27
0
 def cbChannel(channel):
     self.channel = channel
     return channel.conn.sendRequest(channel, 'exec',
                                     common.NS('echo hello'), 1)
Exemple #28
0
 def cbChannel(channel):
     self.channel = channel
     return self.assertFailure(
         channel.conn.sendRequest(channel, 'exec',
                                  common.NS('jumboliah'), 1), Exception)
Exemple #29
0
 def cbNotCrazyFailed(ignored):
     channel = self.channel
     return channel.conn.sendRequest(channel, 'subsystem',
                                     common.NS('crazy'), 1)
Exemple #30
0
 def cbSubsystem(channel):
     self.channel = channel
     return self.assertFailure(
         channel.conn.sendRequest(channel, 'subsystem',
                                  common.NS('not-crazy'), 1), Exception)