+++ /dev/null
-#! /usr/bin/env python
-import os
-import time
-import popen2
-import sys
-import filecmp
-import shutil
-import fcntl
-import re
-import time
-import zlib
-import httplib
-import threading, select
-
-CRLURINEW = "/var/lib/3gates/crlurinew"
-CRLURI = "/var/lib/3gates/crluri"
-CRL = "/var/lib/3gates/crl"
-CA_PATH = "/var/lib/3gates/ca"
-CRLCHKTIME = 1800.0
-
-start_time = 0
-
-# hash of the CA:
-# openssl crl -in CRL15 -inform der -hash -noout
-#
-# verify of the CRL:
-# openssl crl -in CRL15 -inform der -CApath /etc/apache2/ssl/ca/ -noout
-
-
-#
-# Functions
-#
-
-class command_output_processor(threading.Thread):
- def __init__(self, subproc, sout, serr):
- threading.Thread.__init__(self)
-
- self.lock = threading.Lock()
- if sout:
- self.sout = ''
- else:
- self.sout = False
- if serr:
- self.serr = ''
- else:
- self.serr = False
-
- ctrlrd, ctrlwr = os.pipe()
- self.ctrlrd = os.fdopen(ctrlrd, "rb")
- self.ctrlwr = os.fdopen(ctrlwr, "wb")
- self.shutdown = True
- self.output = subproc.fromchild
- self.error = subproc.childerr
-
- def run(self):
- self.lock.acquire()
- self.shutdown = False
- self.lock.release()
-
- while (not self.shutdown) and ((not self.output.closed) or (not self.error.closed)):
- # print "main loop"
- intrig = [ self.ctrlrd ]
- if not self.output.closed:
- intrig.append(self.output)
-
- if not self.error.closed:
- intrig.append(self.error)
-
- # print "pre select"
- retsel = select.select( intrig, [ ], [ ], 5)
- # print "post select"
-
- if len(retsel[0]) == 0:
- # print "no data"
- continue
-
- # print "len range", len(retsel[0])
- for i in range(0,len(retsel[0])):
- # print "LOOP %d: %d\n" % (i, len(retsel[0]))
- if retsel[0][i] == self.ctrlrd:
- self.ctrlrd.read()
-
- elif retsel[0][i] == self.output:
- data = self.output.read()
-
- if (len(data) == 0):
- self.output.close()
- else:
- pass # print "Stdout data len", len(data)
-
- if self.sout != False:
- self.sout += data
-
- elif retsel[0][i] == self.error:
- data = self.error.read()
- if (len(data) == 0):
- self.error.close()
- else:
- pass # print "Stderr data len", len(data)
-
- if self.serr != False:
- self.serr += data
-
- self.lock.acquire()
- try:
- if not self.ctrlrd.closed:
- self.ctrlrd.close()
- if not self.ctrlwr.closed:
- self.ctrlwr.close()
- except:
- print "exception at ctrl close"
- pass
-
- self.shutdown = True
- self.lock.release()
-
-
- def stop(self):
- self.lock.acquire()
- if not self.shutdown:
- self.ctrlwr.write("w")
- self.shutdown = True
- self.lock.release()
-
-
-def execute_command(cmd, input, with_output, with_error, wait):
- subret = -1
- subproc = popen2.Popen3(cmd, True)
-
- th = command_output_processor(subproc, with_output, with_error)
- th.start()
-
- if input:
- try:
- poin = subproc.tochild
- poin.write(input)
- poin.close()
- except Exception, e:
- print "exception at poin close", e
- pass
-
- for i in range(1, wait * 10):
- # print "loop ", i
- subret = subproc.poll()
- if (subret != -1):
- break
- time.sleep(0.1)
- else:
- # FIXME: kill procedure here
- print "NON ESCE"
- print "prima della stop ", subret
- th.stop()
- ret = th.join()
-
- return (subret, th.sout, th.serr)
-
-
-
-
-def crlurinew_mustupdate(crluri, crlurinew):
- ldir = os.listdir(crlurinew)
- for cf in ldir:
- # find all new .cont files
- if re.match("^[a-f0-9]{8}\.cont$", cf) == None:
- continue
- # TODO verify if the name it's really the hash of the content (anti-tampering)
-
- acc = os.access(crluri+"/"+cf, os.F_OK | os.R_OK | os.W_OK)
-
- if (acc == False):
- return True
-
- return False
-
-def crluri_fromnew(crluri, crlurinew):
- ldir = os.listdir(crlurinew)
- for cf in ldir:
- # find all new .cont files
- if re.match("^[a-f0-9]{8}\.cont$", cf) == None:
- continue
- # TODO verify if the name it's really the hash of the content (anti-tampering)
-
- acc = os.access(crluri+"/"+cf, os.F_OK | os.R_OK | os.W_OK)
-
- if (acc == False):
- print("copy file [%s]\n from dir:[%s]\n to dir: [%s]" % (cf, crlurinew, crluri))
- shutil.copyfile(crlurinew+"/"+cf, crluri+"/"+cf)
- else:
- print "WARNING: File %s just exists in %s." % (cf, crluri)
-
- os.remove(crlurinew+"/"+cf)
-
- return True
-
-def ssltime2int(s):
- sout = re.sub('^.*= *', '', s).strip("\n")
- t = time.strptime(sout, "%b %d %H:%M:%S %Y %Z")
- ts = int(time.strftime("%s", t))
- return ts
-
-#
-# Se non esiste l'expire o se esiste ed in scadenza rende True, altrimenti False
-#
-def crl_needverify(cu_name, crl, exptime, lcrldir):
- c_name = cu_name.replace(".cont", ".crl")
-
- acc = os.access(crl+"/"+c_name, os.F_OK | os.R_OK | os.W_OK)
- if acc == False:
- return (True, None)
-
- for cfcrl in lcrldir:
- if re.match( ("^[0-9]+\.%s$" % c_name), cfcrl) != None:
- if ((float(re.sub("\.[a-f0-9]{8}\.crl$", "", cfcrl)) - time.time()) < exptime):
- print " expire link expired"
- return (True, cfcrl)
- break
- else:
- print " expire link not found"
- return (True, None)
-
- # print " expire link verified"
- return (False, None)
-
-def crl_update(contfile, crluripath, crlpath, expiresym):
- ret = False
-
- crl_file = re.sub("\.cont$", ".crl", contfile)
- print "crl_update contfile: %s crl file %s" % (contfile, crl_file)
-
- f = file(crluripath+"/"+contfile, "r")
-
-
- # FIMXME: modo migliore di looppare ?
- while True:
- s = f.readline(1024)
- if s == '':
- break
-
- uri = s.strip("\n")
-
- # verify proto
- if (re.match("^[hH][tT][tT][pP]://", uri) != None):
- # get http file
- uri = re.sub("^[hH][tT][tT][pP]://", "", uri)
- site = re.sub("/.*", "", uri)
- page = re.sub("^[^/]*/", "/", uri)
-
- print "HTTP URI [%s] HOST [%s] PAGE [%s]" % (uri, site, page)
- conn = httplib.HTTPConnection(site)
- conn.request("GET", page)
- r1 = conn.getresponse()
- if r1.status != 200:
- continue
-
- crl_data = r1.read()
- conn.close()
- break
-
- elif (re.match("^[lL][dD][aA][pP]://", uri) != None):
- print "LDAP Path: [%s]" % uri
- # get ldap file
- continue
-
- f.close()
-
- # verify the crl
- # openssl crl -inform der -CApath /etc/apache2/ssl/ca/ -noout
- # print "execute 1"
- subret, sout, serr = execute_command("/usr/bin/openssl crl -inform pem -CApath %s -noout" % CA_PATH ,
- crl_data, False, False, 20)
- if (subret != 0):
- # print "execute 2"
- subret, sout, serr = execute_command("/usr/bin/openssl crl -inform der -CApath %s -noout" % CA_PATH ,
- crl_data, False, False, 20)
-
- if (subret != 0):
- print "CRL verify FAILED!"
- return False
- else:
- print "CRL verified!"
-
-
- sout = ""
- # print "execute 3"
- subret, sout, serr = execute_command("/usr/bin/openssl crl -inform der -outform pem" ,
- crl_data, True, False, 20)
- crl_data = sout
-
-
- # verify that lastupdate was in the past
- subret, sout, serr = execute_command("/usr/bin/openssl crl -inform pem -lastupdate -noout",
- crl_data, True, False, 20)
-
- print "lastupdate: [%s]" % sout
- ts_last = ssltime2int(sout)
- print "lastupdate2: [%d]" % ts_last
- print "start_time: [%d]" % start_time
- if ts_last > start_time:
- print "ERROR: lastupdate is in the future"
- return False
-
- # verify that nextupdate was in the past
- subret, sout, serr = execute_command("/usr/bin/openssl crl -inform pem -nextupdate -noout",
- crl_data, True, False, 20)
-
- ts_next = ssltime2int(sout)
- print "TS_NEXT: ", ts_next
- if ts_next < start_time:
- print "WARNING: nextupdate is in the past"
-
- # verify if exists an old copy of the crl and if is the same
- acc = os.access(CRL+"/"+crl_file, os.F_OK | os.R_OK | os.W_OK)
- if acc != False:
- sout = ""
- print "CRL verify:"
-
- print "execute 4: /usr/bin/openssl crl -inform pem -in %s -noout -fingerprint" % (CRL+"/"+crl_file)
- subret, finger_old, serr = execute_command("/usr/bin/openssl crl -inform pem -in %s -noout -fingerprint" % (CRL+"/"+crl_file),
- False, True, False, 20)
-
- if (subret != 0):
- print "acquiring CRL fingerprint FAILED!", subret
- return False
-
- subret, finger_new, serr = execute_command("/usr/bin/openssl crl -inform pem -noout -fingerprint",
- crl_data, True, False, 20)
-
- if finger_old == finger_new:
- return True
-
-
- # update the crl file
- print "UPDATE::save new file to: ", crl_file
- newf = file(CRL+"/"+crl_file+"_new", "w")
- newf.write(crl_data)
- newf.close()
- os.rename(CRL+"/"+crl_file+"_new", CRL+"/"+crl_file)
-
- print "UPDATE:expiretime file:", expiresym
- # update the expiretime symlink
- if expiresym != None:
- os.unlink(CRL+"/"+expiresym)
-
- print "UPDATE:symlinking(%s, %s)" % (CRL+"/"+crl_file, CRL+"/"+str(ts_next)+"."+crl_file)
- oldcwd = os.getcwd()
- os.chdir(CRL)
- os.symlink(crl_file, str(ts_next)+"."+crl_file)
- os.chdir(oldcwd)
-
- subret, crl_hash, serr = execute_command("/usr/bin/openssl crl -inform pem -noout -hash",
- crl_data, True, False, 20)
-
- crl_hash = crl_hash.strip("\n")
- print "hash: [%s]" % crl_hash
-
- new_st = os.stat(CRL+"/"+crl_file)
- print "NEW_ST: ", new_st.st_ino
-
- lcrldir = os.listdir(crlpath)
- print "lcrldir: ", lcrldir
- print "preemp: ", [ x for x in lcrldir if re.match(crl_hash+".r[0-9]+", x) ]
- for crl_cur in [ x for x in lcrldir if re.match(crl_hash+".r[0-9]+", x) ]:
- st = os.stat(crlpath+"/"+crl_cur)
- print "CMP: ", st.st_ino
- if new_st.st_ino == st.st_ino:
- break
- else:
- for i in range(0, 1000):
- acc = os.access(CRL+"/"+crl_hash+".r"+str(i), os.F_OK | os.R_OK | os.W_OK)
- if acc == False:
- oldcwd = os.getcwd()
- os.chdir(CRL)
- os.symlink(crl_file, crl_hash+".r"+str(i))
- os.chdir(oldcwd)
- break
-
-
- return ret
-
-#
-# MAIN
-#
-if __name__=='__main__':
-
- start_time = time.time()
- #
- # VERIFY
- #
- # print "\n--- VERIFY ---\n"
- update = False
- old_umask = os.umask(0002)
- fl = file(CRLURINEW + "/certgate.lck", "w+")
- os.umask(old_umask)
- # print "lock SH"
- fcntl.flock(fl, fcntl.LOCK_SH)
-
-
- while True:
- # verify for new .cont files
- update = crlurinew_mustupdate(CRLURI, CRLURINEW)
- if update == True:
- break
-
- ldir = os.listdir(CRLURI)
- lcrldir = os.listdir(CRL)
- for cf in ldir:
- # for each .cont file verify existence of associated .crl file and it's expire time
- if re.match("[a-f0-9]{8}\.cont$", cf) != None:
- need, expiresym = crl_needverify(cf, CRL, CRLCHKTIME, lcrldir)
- if need:
- update = True
- break
-
- # end of while True
- break
-
- fcntl.flock(fl, fcntl.LOCK_UN)
- # print "unlock SH"
-
- if update == False:
- sys.exit(0)
-
- #
- # UPDATE
- #
- # We lock in EX mode before continue.
- #
- print "\n--- UPDATE ---\n"
- print "lock EX"
- fcntl.flock(fl, fcntl.LOCK_EX)
-
- # try to copy new crluri from DMZ dir to working dir
- crluri_fromnew(CRLURI, CRLURINEW)
-
- ldir = os.listdir(CRLURI)
- lcrldir = os.listdir(CRL)
- for cf in ldir:
- # if .cont file verify existance of associated .crl file
- if re.match("^[a-f0-9]{8}\.cont$", cf) != None:
- need, expiresym = crl_needverify(cf, CRL, CRLCHKTIME, lcrldir)
- if need:
- # download and check update
- crl_update(cf, CRLURI, CRL, expiresym)
-
-
- fcntl.flock(fl, fcntl.LOCK_UN)
- print "unlock EX"
-
- fl.close()
- sys.exit(111)
-
-# while True:
-# s = f.readline(1024)
-# if s == '':
-# break
-# print s
-# print len(s)
-
-
-# f.close()
-
- exit
-
-# main()
-