| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
| 2 # See LICENSE for details. | |
| 3 | |
| 4 # | |
| 5 """ | |
| 6 Implements the old SSHv1 key agent protocol. | |
| 7 | |
| 8 Maintainer: U{Paul Swartz<mailto:z3p@twistedmatrix.com>} | |
| 9 """ | |
| 10 | |
| 11 import struct | |
| 12 from common import NS, getNS | |
| 13 from twisted.conch.error import ConchError | |
| 14 from twisted.internet import defer, protocol | |
| 15 | |
| 16 class SSHAgentClient(protocol.Protocol): | |
| 17 | |
| 18 def __init__(self): | |
| 19 self.buf = '' | |
| 20 self.deferreds = [] | |
| 21 | |
| 22 def dataReceived(self, data): | |
| 23 self.buf += data | |
| 24 while 1: | |
| 25 if len(self.buf) <= 4: return | |
| 26 packLen = struct.unpack('!L', self.buf[:4])[0] | |
| 27 if len(self.buf) < 4+packLen: return | |
| 28 packet, self.buf = self.buf[4:4+packLen], self.buf[4+packLen:] | |
| 29 reqType = ord(packet[0]) | |
| 30 d = self.deferreds.pop(0) | |
| 31 if reqType == AGENT_FAILURE: | |
| 32 d.errback(ConchError('agent failure')) | |
| 33 elif reqType == AGENT_SUCCESS: | |
| 34 d.callback('') | |
| 35 else: | |
| 36 d.callback(packet) | |
| 37 | |
| 38 def sendRequest(self, reqType, data): | |
| 39 pack = struct.pack('!LB',len(data)+1, reqType)+data | |
| 40 self.transport.write(pack) | |
| 41 d = defer.Deferred() | |
| 42 self.deferreds.append(d) | |
| 43 return d | |
| 44 | |
| 45 def requestIdentities(self): | |
| 46 return self.sendRequest(AGENTC_REQUEST_IDENTITIES, '').addCallback(self.
_cbRequestIdentities) | |
| 47 | |
| 48 def _cbRequestIdentities(self, data): | |
| 49 if ord(data[0]) != AGENT_IDENTITIES_ANSWER: | |
| 50 return ConchError('unexpected respone: %i' % ord(data[0])) | |
| 51 numKeys = struct.unpack('!L', data[1:5])[0] | |
| 52 keys = [] | |
| 53 data = data[5:] | |
| 54 for i in range(numKeys): | |
| 55 blobLen = struct.unpack('!L', data[:4])[0] | |
| 56 blob, data = data[4:4+blobLen], data[4+blobLen:] | |
| 57 commLen = struct.unpack('!L', data[:4])[0] | |
| 58 comm, data = data[4:4+commLen], data[4+commLen:] | |
| 59 keys.append((blob, comm)) | |
| 60 return keys | |
| 61 | |
| 62 def addIdentity(self, blob, comment = ''): | |
| 63 req = blob | |
| 64 req += NS(comment) | |
| 65 co | |
| 66 return self.sendRequest(AGENTC_ADD_IDENTITY, req) | |
| 67 | |
| 68 def signData(self, blob, data): | |
| 69 req = NS(blob) | |
| 70 req += NS(data) | |
| 71 req += '\000\000\000\000' # flags | |
| 72 return self.sendRequest(AGENTC_SIGN_REQUEST, req).addCallback(self._cbSi
gnData) | |
| 73 | |
| 74 def _cbSignData(self, data): | |
| 75 if data[0] != chr(AGENT_SIGN_RESPONSE): | |
| 76 return ConchError('unexpected data: %i' % ord(data[0])) | |
| 77 signature = getNS(data[1:])[0] | |
| 78 return signature | |
| 79 | |
| 80 def removeIdentity(self, blob): | |
| 81 req = NS(blob) | |
| 82 return self.sendRequest(AGENTC_REMOVE_IDENTITY, req) | |
| 83 | |
| 84 def removeAllIdentities(self): | |
| 85 return self.sendRequest(AGENTC_REMOVE_ALL_IDENTITIES, '') | |
| 86 | |
| 87 class SSHAgentServer(protocol.Protocol): | |
| 88 | |
| 89 def __init__(self): | |
| 90 self.buf = '' | |
| 91 | |
| 92 def dataReceived(self, data): | |
| 93 self.buf += data | |
| 94 while 1: | |
| 95 if len(self.buf) <= 4: return | |
| 96 packLen = struct.unpack('!L', self.buf[:4])[0] | |
| 97 if len(self.buf) < 4+packLen: return | |
| 98 packet, self.buf = self.buf[4:4+packLen], self.buf[4+packLen:] | |
| 99 reqType = ord(packet[0]) | |
| 100 reqName = messages.get(reqType, None) | |
| 101 if not reqName: | |
| 102 print 'bad request', reqType | |
| 103 f = getattr(self, 'agentc_%s' % reqName) | |
| 104 f(packet[1:]) | |
| 105 | |
| 106 def sendResponse(self, reqType, data): | |
| 107 pack = struct.pack('!LB', len(data)+1, reqType) + data | |
| 108 self.transport.write(pack) | |
| 109 | |
| 110 def agentc_REQUEST_IDENTITIES(self, data): | |
| 111 assert data == '' | |
| 112 numKeys = len(self.keys) | |
| 113 s = struct.pack('!L', numKeys) | |
| 114 for k in self.keys: | |
| 115 s += struct.pack('!L', len(k)) + k | |
| 116 s += struct.pack('!L', len(self.keys[k][1])) + self.keys[k][1] | |
| 117 self.sendResponse(AGENT_IDENTITIES_ANSWER, s) | |
| 118 | |
| 119 def agentc_SIGN_REQUEST(self, data): | |
| 120 blob, data = common.getNS(data) | |
| 121 if blob not in self.keys: | |
| 122 return self.sendResponse(AGENT_FAILURE, '') | |
| 123 signData, data = common.getNS(data) | |
| 124 assert data == '\000\000\000\000' | |
| 125 self.sendResponse(AGENT_SIGN_RESPONSE, common.NS(keys.signData(self.keys
[blob][0], signData))) | |
| 126 | |
| 127 def agentc_ADD_IDENTITY(self, data): pass | |
| 128 def agentc_REMOVE_IDENTITY(self, data): pass | |
| 129 def agentc_REMOVE_ALL_IDENTITIES(self, data): pass | |
| 130 | |
| 131 AGENT_FAILURE = 5 | |
| 132 AGENT_SUCCESS = 6 | |
| 133 AGENTC_REQUEST_IDENTITIES = 11 | |
| 134 AGENT_IDENTITIES_ANSWER = 12 | |
| 135 AGENTC_SIGN_REQUEST = 13 | |
| 136 AGENT_SIGN_RESPONSE = 14 | |
| 137 AGENTC_ADD_IDENTITY = 17 | |
| 138 AGENTC_REMOVE_IDENTITY = 18 | |
| 139 AGENTC_REMOVE_ALL_IDENTITIES = 19 | |
| 140 | |
| 141 messages = {} | |
| 142 import agent | |
| 143 for v in dir(agent): | |
| 144 if v.startswith('AGENTC_'): | |
| 145 messages[getattr(agent, v)] = v[7:] | |
| OLD | NEW |