1
2
3
4 import socket
5 import mdinterface
6 import time
7 from mdinterface import CommandException, MDInterface
8
9 DEBUG = False
10
11 try:
12 import tlslite
13 USE_TLSLITE = True
14 from tlslite.api import *
15 if DEBUG: print "Using tlslite"
16 except ImportError, e:
17 USE_TLSLITE = False
18
19
21 - def __init__(self, host, port,
22 login='anonymous', password = '',
23 keepalive = True):
24 self.connected = 0
25 self.host = host
26 self.port = port
27 self.login = login
28 self.password = password
29 self.keepalive = keepalive
30 self.buffer = ''
31 self.reqSSL = False
32 self.sslSock = 0
33 self.sslOptions = None
34 self.sessionID = 0
35 self.session = None
36 self.greetings = ''
37 self.protocolVersion = 0
38 self.currentCommand = ""
39
41 self.reqSSL=True
42 self.keyFile=key
43 self.certFile=cert
44 if USE_TLSLITE:
45 self.sslOptions = tlslite.HandshakeSettings.HandshakeSettings
46 self.sslOptions.minVersion = (3,0)
47 self.sslOptions.maxVersion = (3,1)
48
49
51 if USE_TLSLITE:
52 self.sslSock=TLSConnection(self.s)
53 if session:
54 if DEBUG: print "Doing SSL resuming session using TLSLite"
55 self.sslSock.handshakeClientCert(session=session)
56 return
57
58 if DEBUG: print "Doing SSL handshake using TLSLite"
59 cert = None
60 key = None
61 if self.certFile:
62 s = open(self.certFile).read()
63 x509 = X509()
64 x509.parse(s)
65 cert = X509CertChain([x509])
66 if self.keyFile:
67 s = open(self.keyFile).read()
68 key = parsePEMKey(s, private=True)
69 self.sslSock.handshakeClientCert(cert, key,
70 self.session, None, None, False)
71 self.sslSock.closeSocket = False
72 else:
73 if DEBUG: print "Doing SSL handshake using builtin SSL"
74 self.sslSock=socket.ssl(self.s, self.keyFile, self.certFile)
75
76
78 self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
79 TCP_NODELAY = 1
80 self.s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
81 self.s.connect((self.host, self.port))
82
83 self.greetings = ""
84
85 while self.greetings.count('\n') < 3:
86 line=self.s.recv(1024)
87 if not line:
88 raise CommandException(-1, "Cannot connect")
89 self.greetings += line
90
91 pos = self.greetings.find('\nProtocol ')
92 if pos > -1:
93 self.protocolVersion = int(self.greetings[pos+10])
94
95 if self.sessionID:
96 if DEBUG: print "Trying to resume session ", self.sessionID
97
98 if self.reqSSL:
99 self.s.send('resumeSSL%u\n\n' % self.sessionID)
100 line = self.s.recv(1024)
101 self.__doSSLHandshake(self.session)
102 else:
103 self.s.send('resume%d\n\n' % self.sessionID)
104 self.connected=True
105 self.buffer=''
106 self.attr=0
107 return 0
108 else:
109 if self.reqSSL:
110 self.s.send('ssl\n\n')
111 line = self.s.recv(1024)
112 self.__doSSLHandshake()
113 else:
114 self.s.send('plain\n\n')
115 line = self.s.recv(1024)
116
117
118 context = '0 '+self.login + '\n5 ' + self.password + '\n\n'
119 if not self.sessionID:
120 if self.sslSock:
121 self.sslSock.write(context)
122 else:
123 self.s.send(context)
124
125 self.connected=True
126 self.buffer=''
127 self.attr=0
128
129
131 if saveSession and self.sslSock:
132 if USE_TLSLITE:
133 self.session = self.sslSock.session
134 else:
135 self.session = None
136
137 if self.connected:
138 if self.sslSock and USE_TLSLITE:
139 self.sslSock.close()
140 self.s.close()
141 self.connected = False
142
143
150
155
156
171
172
174 self.EOT = 0
175 self.buffer = "";
176 line = self.__fetchRow()
177 if line == None:
178 raise IOError("Server sent empty response")
179 pos=line.find(' ')
180 msg = ""
181 if(pos>-1):
182 retValue, msg=int(line[:pos]), line[pos+1:]
183 else:
184 retValue = int(line)
185 if retValue != 0:
186
187
188 while not self.EOT:
189 if self.__fetchData()<0:
190 break
191 self.buffer = ""
192 msg = msg + ". Command was: " + self.currentCommand
193 raise CommandException(retValue, msg)
194
195
214
215
218
220
221 pos=self.buffer.find('\n')
222 if pos>-1:
223 line=self.buffer[:pos]
224 self.buffer=self.buffer[pos+1:]
225 if not len(self.buffer) and not self.EOT:
226 if self.__fetchData() < 0: return None
227 return line
228 if self.EOT:
229 return None
230 if self.__fetchData() <=0:
231 return None
232 return self.__fetchRow()
233
234
236 while 1:
237
238 pos = self.buffer.find('\004')
239 if pos >-1:
240
241 while self.protocolVersion >1 and self.buffer.find('\004', pos + 1) <0:
242 if self.sslSock:
243 line=self.sslSock.read(1024)
244 else:
245 line=self.s.recv(1024)
246 if not line: break
247 self.buffer += line
248 break
249
250
251 pos = self.buffer.find('\n')
252 if pos>-1 and pos<len(self.buffer)-1: break
253
254
255 if self.sslSock:
256 line=self.sslSock.read(1024)
257 else:
258 line=self.s.recv(1024)
259 if not line: break
260 self.buffer += line
261
262 pos=self.buffer.find('\004')
263 if pos>-1:
264 self.sessionID = 0
265 if pos < len(self.buffer)-8 and self.buffer[pos+1:pos+8] == 'session':
266 pos2 = self.buffer.find('\004', pos+1)
267 self.sessionID = long(self.buffer[pos+8:pos2])
268 self.disconnect(True)
269 if DEBUG: print "Session ID", self.sessionID
270 self.buffer=self.buffer[:pos]
271 self.EOT=1
272 if not line:
273 return -1
274 return len(line)
275
276
278 gotSomething=1
279 self.s.setblocking(0)
280 try:
281 self.s.recv(1, MSG_PEEK)
282 except Exception, e:
283 gotSomething=0
284 self.s.setblocking(1)
285 return gotSomething
286
287
289 if type(value) == type(str()):
290 value = value.replace('\'', '\\\'')
291 value = "'" + value + "'"
292 return value
293
294
296 if len(self.buffer): return 0
297 if self.EOT: return 1
298 if self.__fetchData() <=0: return 1
299 return not len(self.buffer)
300
301
302 - def getattr(self, file, attributes):
308
309
310 - def getEntry(self):
311 file = self.__fetchRow()
312 attributes=[]
313 for i in range(0, self.nattrs):
314 attribute=self.__fetchRow()
315 attributes.append(attribute)
316 return file, attributes
317
318
319 - def setAttr(self, file, keys, values):
326
327
328 - def addEntry(self, file, keys, values):
329 command='addentry '+file
330 for i in range(len(keys)):
331 command += ' '+keys[i]
332 values[i] = self.__quoteValue(str(values[i]))
333 command += ' ' +values[i]
334 self.execute(command)
335
336
342
343
347
348
352
353
357
358
363
364
368
369
381
382
386
390
394
395
396 - def rm(self, path):
399
400
401 - def find(self, pattern, query):
406
407
415
416
418 attributes=[]
419 for i in range(0, self.nattrs):
420 attribute=self.__fetchRow()
421 attributes.append(attribute)
422 return attributes
423
424
425 - def updateAttr(self, pattern, updateExpr, condition):
432
433
434 - def upload(self, collection, attributes):
440
441
442 - def put(self, file, values):
449
450
454
455
459
460
465
466
471
472
476
477
481
485
489
494
498
502
504 command='constraint_list '+directory
505 self.execute(command)
506 constraints=[]
507 while not self.eot():
508 constraint = self.__fetchRow()
509 constraints.append(constraint)
510 return constraints
511
515