13 import threading, select
15 CRLURINEW = "/var/lib/3gates/crlurinew"
16 CRLURI = "/var/lib/3gates/crluri"
17 CRL = "/var/lib/3gates/crl"
18 CA_PATH = "/var/lib/3gates/ca"
24 # openssl crl -in CRL15 -inform der -hash -noout
27 # openssl crl -in CRL15 -inform der -CApath /etc/apache2/ssl/ca/ -noout
34 class command_output_processor(threading.Thread):
35 def __init__(self, subproc, sout, serr):
36 threading.Thread.__init__(self)
38 self.lock = threading.Lock()
48 ctrlrd, ctrlwr = os.pipe()
49 self.ctrlrd = os.fdopen(ctrlrd, "rb")
50 self.ctrlwr = os.fdopen(ctrlwr, "wb")
52 self.output = subproc.fromchild
53 self.error = subproc.childerr
60 while (not self.shutdown) and ((not self.output.closed) or (not self.error.closed)):
62 intrig = [ self.ctrlrd ]
63 if not self.output.closed:
64 intrig.append(self.output)
66 if not self.error.closed:
67 intrig.append(self.error)
70 retsel = select.select( intrig, [ ], [ ], 5)
73 if len(retsel[0]) == 0:
77 # print "len range", len(retsel[0])
78 for i in range(0,len(retsel[0])):
79 # print "LOOP %d: %d\n" % (i, len(retsel[0]))
80 if retsel[0][i] == self.ctrlrd:
83 elif retsel[0][i] == self.output:
84 data = self.output.read()
89 pass # print "Stdout data len", len(data)
91 if self.sout != False:
94 elif retsel[0][i] == self.error:
95 data = self.error.read()
99 pass # print "Stderr data len", len(data)
101 if self.serr != False:
106 if not self.ctrlrd.closed:
108 if not self.ctrlwr.closed:
111 print "exception at ctrl close"
120 if not self.shutdown:
121 self.ctrlwr.write("w")
126 def execute_command(cmd, input, with_output, with_error, wait):
128 subproc = popen2.Popen3(cmd, True)
130 th = command_output_processor(subproc, with_output, with_error)
135 poin = subproc.tochild
139 print "exception at poin close", e
142 for i in range(1, wait * 10):
144 subret = subproc.poll()
149 # FIXME: kill procedure here
151 print "prima della stop ", subret
155 return (subret, th.sout, th.serr)
160 def crlurinew_mustupdate(crluri, crlurinew):
161 ldir = os.listdir(crlurinew)
163 # find all new .cont files
164 if re.match("^[a-f0-9]{8}\.cont$", cf) == None:
166 # TODO verify if the name it's really the hash of the content (anti-tampering)
168 acc = os.access(crluri+"/"+cf, os.F_OK | os.R_OK | os.W_OK)
175 def crluri_fromnew(crluri, crlurinew):
176 ldir = os.listdir(crlurinew)
178 # find all new .cont files
179 if re.match("^[a-f0-9]{8}\.cont$", cf) == None:
181 # TODO verify if the name it's really the hash of the content (anti-tampering)
183 acc = os.access(crluri+"/"+cf, os.F_OK | os.R_OK | os.W_OK)
186 print("copy file [%s]\n from dir:[%s]\n to dir: [%s]" % (cf, crlurinew, crluri))
187 shutil.copyfile(crlurinew+"/"+cf, crluri+"/"+cf)
189 print "WARNING: File %s just exists in %s." % (cf, crluri)
191 os.remove(crlurinew+"/"+cf)
196 sout = re.sub('^.*= *', '', s).strip("\n")
197 t = time.strptime(sout, "%b %d %H:%M:%S %Y %Z")
198 ts = int(time.strftime("%s", t))
202 # Se non esiste l'expire o se esiste ed in scadenza rende True, altrimenti False
204 def crl_needverify(cu_name, crl, exptime, lcrldir):
205 c_name = cu_name.replace(".cont", ".crl")
207 acc = os.access(crl+"/"+c_name, os.F_OK | os.R_OK | os.W_OK)
211 for cfcrl in lcrldir:
212 if re.match( ("^[0-9]+\.%s$" % c_name), cfcrl) != None:
213 if ((float(re.sub("\.[a-f0-9]{8}\.crl$", "", cfcrl)) - time.time()) < exptime):
214 print " expire link expired"
218 print " expire link not found"
221 # print " expire link verified"
224 def crl_update(contfile, crluripath, crlpath, expiresym):
227 crl_file = re.sub("\.cont$", ".crl", contfile)
228 print "crl_update contfile: %s crl file %s" % (contfile, crl_file)
230 f = file(crluripath+"/"+contfile, "r")
233 # FIMXME: modo migliore di looppare ?
242 if (re.match("^[hH][tT][tT][pP]://", uri) != None):
244 uri = re.sub("^[hH][tT][tT][pP]://", "", uri)
245 site = re.sub("/.*", "", uri)
246 page = re.sub("^[^/]*/", "/", uri)
248 print "HTTP URI [%s] HOST [%s] PAGE [%s]" % (uri, site, page)
249 conn = httplib.HTTPConnection(site)
250 conn.request("GET", page)
251 r1 = conn.getresponse()
259 elif (re.match("^[lL][dD][aA][pP]://", uri) != None):
260 print "LDAP Path: [%s]" % uri
267 # openssl crl -inform der -CApath /etc/apache2/ssl/ca/ -noout
269 subret, sout, serr = execute_command("/usr/bin/openssl crl -inform pem -CApath %s -noout" % CA_PATH ,
270 crl_data, False, False, 20)
273 subret, sout, serr = execute_command("/usr/bin/openssl crl -inform der -CApath %s -noout" % CA_PATH ,
274 crl_data, False, False, 20)
277 print "CRL verify FAILED!"
280 print "CRL verified!"
285 subret, sout, serr = execute_command("/usr/bin/openssl crl -inform der -outform pem" ,
286 crl_data, True, False, 20)
290 # verify that lastupdate was in the past
291 subret, sout, serr = execute_command("/usr/bin/openssl crl -inform pem -lastupdate -noout",
292 crl_data, True, False, 20)
294 print "lastupdate: [%s]" % sout
295 ts_last = ssltime2int(sout)
296 print "lastupdate2: [%d]" % ts_last
297 print "start_time: [%d]" % start_time
298 if ts_last > start_time:
299 print "ERROR: lastupdate is in the future"
302 # verify that nextupdate was in the past
303 subret, sout, serr = execute_command("/usr/bin/openssl crl -inform pem -nextupdate -noout",
304 crl_data, True, False, 20)
306 ts_next = ssltime2int(sout)
307 print "TS_NEXT: ", ts_next
308 if ts_next < start_time:
309 print "WARNING: nextupdate is in the past"
311 # verify if exists an old copy of the crl and if is the same
312 acc = os.access(CRL+"/"+crl_file, os.F_OK | os.R_OK | os.W_OK)
317 print "execute 4: /usr/bin/openssl crl -inform pem -in %s -noout -fingerprint" % (CRL+"/"+crl_file)
318 subret, finger_old, serr = execute_command("/usr/bin/openssl crl -inform pem -in %s -noout -fingerprint" % (CRL+"/"+crl_file),
319 False, True, False, 20)
322 print "acquiring CRL fingerprint FAILED!", subret
325 subret, finger_new, serr = execute_command("/usr/bin/openssl crl -inform pem -noout -fingerprint",
326 crl_data, True, False, 20)
328 if finger_old == finger_new:
332 # update the crl file
333 print "UPDATE::save new file to: ", crl_file
334 newf = file(CRL+"/"+crl_file+"_new", "w")
337 os.rename(CRL+"/"+crl_file+"_new", CRL+"/"+crl_file)
339 print "UPDATE:expiretime file:", expiresym
340 # update the expiretime symlink
341 if expiresym != None:
342 os.unlink(CRL+"/"+expiresym)
344 print "UPDATE:symlinking(%s, %s)" % (CRL+"/"+crl_file, CRL+"/"+str(ts_next)+"."+crl_file)
347 os.symlink(crl_file, str(ts_next)+"."+crl_file)
350 subret, crl_hash, serr = execute_command("/usr/bin/openssl crl -inform pem -noout -hash",
351 crl_data, True, False, 20)
353 crl_hash = crl_hash.strip("\n")
354 print "hash: [%s]" % crl_hash
356 new_st = os.stat(CRL+"/"+crl_file)
357 print "NEW_ST: ", new_st.st_ino
359 lcrldir = os.listdir(crlpath)
360 print "lcrldir: ", lcrldir
361 print "preemp: ", [ x for x in lcrldir if re.match(crl_hash+".r[0-9]+", x) ]
362 for crl_cur in [ x for x in lcrldir if re.match(crl_hash+".r[0-9]+", x) ]:
363 st = os.stat(crlpath+"/"+crl_cur)
364 print "CMP: ", st.st_ino
365 if new_st.st_ino == st.st_ino:
368 for i in range(0, 1000):
369 acc = os.access(CRL+"/"+crl_hash+".r"+str(i), os.F_OK | os.R_OK | os.W_OK)
373 os.symlink(crl_file, crl_hash+".r"+str(i))
383 if __name__=='__main__':
385 start_time = time.time()
389 # print "\n--- VERIFY ---\n"
391 old_umask = os.umask(0002)
392 fl = file(CRLURINEW + "/certgate.lck", "w+")
395 fcntl.flock(fl, fcntl.LOCK_SH)
399 # verify for new .cont files
400 update = crlurinew_mustupdate(CRLURI, CRLURINEW)
404 ldir = os.listdir(CRLURI)
405 lcrldir = os.listdir(CRL)
407 # for each .cont file verify existence of associated .crl file and it's expire time
408 if re.match("[a-f0-9]{8}\.cont$", cf) != None:
409 need, expiresym = crl_needverify(cf, CRL, CRLCHKTIME, lcrldir)
417 fcntl.flock(fl, fcntl.LOCK_UN)
426 # We lock in EX mode before continue.
428 print "\n--- UPDATE ---\n"
430 fcntl.flock(fl, fcntl.LOCK_EX)
432 # try to copy new crluri from DMZ dir to working dir
433 crluri_fromnew(CRLURI, CRLURINEW)
435 ldir = os.listdir(CRLURI)
436 lcrldir = os.listdir(CRL)
438 # if .cont file verify existance of associated .crl file
439 if re.match("^[a-f0-9]{8}\.cont$", cf) != None:
440 need, expiresym = crl_needverify(cf, CRL, CRLCHKTIME, lcrldir)
442 # download and check update
443 crl_update(cf, CRLURI, CRL, expiresym)
446 fcntl.flock(fl, fcntl.LOCK_UN)
453 # s = f.readline(1024)