source: branches/2.2/security/crl_admin/crl_admin.py @ 3232

Revision 3232, 7.8 KB checked in by rafaelraymundo, 14 years ago (diff)

Ticket #1237 - Atualizados componentes de suporte ao uso do Certificado Digital.

Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4import os, popen2, fcntl, select, time, sys
5from string import replace
6
7# Lista com as urls das CRLs, e onde colocar(path) os arquivos obtidos ....
8CRL_urls = []
9Confs = {}
10
11#Confs['dirtemp']         # path para a pasta temp para conter arquivos auxiliares....
12#Confs['CAfile']          # Arquivo com cadeia dos certificados das CAs, para verificacao das CRLs.
13#Confs['CRLs']            # path para a pasta onde as CRLs sao salvas
14#Confs['arquivos_crls']   # path para o arquivo de configuracao contendo urls das crls e paths onde serao baixadas...
15#Confs['log']             # Arquivo onde sera grada log de execucao da qtualizacao/verificacao das crls.
16                          # Deixe 'log' igual a vazio para ver as msgs de execucao no terminal.......
17#Confs['lenMax']          # Tamanho maximo do arquivo de log de atualização das crls antes do rotate.....
18#Confs['bkpNum']          # Numero de arquivos de log de atualização das crls mantidos pelo rotate....
19
20def ler_arquivo_com_configuracao():
21    # Esta funcao le o arquivo com configuracao geral(linguagen php) para tratar certs.
22    import os,sys
23    BASE = os.path.realpath(__file__).split(os.sep + 'security')[0] # BASE igual a pasta inicial(raiz) do Expresso
24    os.chdir(BASE + '/security/classes')
25    # Esta funcao le o arquivo com configuracao geral(linguagen php) para tratar certs.
26    conf_file = BASE + '/security/classes/Verifica_Certificado_conf.php'
27    e = open(conf_file)
28    r = e.read()
29    aux1 = r.split('\n')
30    # primeiro recupera BASE ...
31    for linha in aux1:
32        linha = linha.strip()
33        if linha[0:16] == "$GLOBALS['BASE']":
34            Confs['BASE'] = BASE
35            break
36    # Agora os demais ...
37    for linha in aux1:
38        linha = linha.strip()
39        if linha[0:10] == "$GLOBALS['":
40          if linha[0:16] != "$GLOBALS['BASE']":
41            aux2 = linha.split(';')
42            if aux2[0] != '':
43                aux2a = aux2[0].split("'")
44                aux3 = aux2[0].split("=")
45                Confs[aux2a[1]] = aux3[1].replace(' ','')
46    # Finalmente trata as ocorrencias de BASE ...
47    for chave in Confs.keys():
48        if chave != 'BASE':
49            aux = Confs[chave].replace("$GLOBALS['BASE'].",Confs['BASE'])
50            Confs[chave] = aux.replace("'",'')
51    return
52
53def ler_conf():
54    # Esta funcao le o arquivo passado como parametro e gera a lista CRL_urls.
55    # O arquivo he esperado no formato:
56    # url ( url = aponta onde buscar a crl,  uma por linha.
57    e = open(Confs['arquivos_crls'])
58    r = e.read()
59    aux1 = r.split('\n')
60    for linha in aux1:
61        if linha[0:1] != '#':
62            if linha.strip() != '':
63                # Faz split com ';' para manter compatibilidade com arquivos formato antigo ...
64                CRL_urls.append([linha.split(';')[0].strip(),Confs['CRLs']])
65    return
66
67
68theOutput = []
69
70def fazlog(mL,dados):
71    for i in dados:
72        aux = i.split('\n')
73        for x in aux:
74            mL.info(x)
75
76def makeNonBlocking(fd):
77    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
78    try:
79        fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NDELAY)
80    except AttributeError:
81        fcntl.fcntl(fd, fcntl.F_SETFL, fl | fcntl.FNDELAY)
82 
83def ExeCmd(command):
84    theOutput = []
85    child = popen2.Popen3(command, 1)           # Captura a stdout e a stderr do comando...
86    child.tochild.close()                               # Não estamos "falando(escrevendo para a stdin do comando) com o processo filho...
87    outfile = child.fromchild
88    outfd = outfile.fileno()
89    errfile = child.childerr
90    errfd = errfile.fileno()
91    makeNonBlocking(outfd)                              # Não queremos um deadlock !!!!( Dica do Python Cookbook v1)
92    makeNonBlocking(errfd)
93    outdata = errdata = ''
94    outeof = erreof = 0
95    while 1:
96        ready = select.select([outfd,errfd],[],[]) # Aguarda a entrada(saida do comando)
97        if outfd in ready[0]:
98           outchunk = outfile.read()
99           if outchunk == '': outeof = 1
100           outdata = outdata + outchunk
101        if errfd in ready[0]:
102           errchunk = errfile.read()
103           if errchunk == '': erreof = 1
104           errdata = errdata + errchunk
105        if outeof and erreof: break
106        select.select([],[],[],.1)                              #Da um tempo para os buffers serem preenchidosl
107    err = child.wait()
108    #if err != 0:
109    #   raise RuntimeError, '%s failed w/ exit code %d\n%s' % (command, err, errdata)
110    theOutput.append(outdata)
111    theOutput.append(errdata)
112    return theOutput
113
114# No arquivo crl_admin_confg esta o path (arquivo) que aponta para a configuracao das urls(CRL_urls) das crls que devem ser obtidas.
115# Este arquivo tambem informa o arquivo onde sera gravada a log(log), e o arquivo contendo
116# a cadeia de certificados para verificar as crls(CAfile).
117# Apos o import, executar a funcao ler_conf() .....
118#from crl_admin_confg import *
119ler_arquivo_com_configuracao()
120try:
121    ler_arquivo_com_configuracao()
122except:
123    print 'Erro lendo arquivos de configuracao(ERR-01X)';
124    sys.exit(1);
125
126try:
127    # A execucao da funcao a seguir carrega a lista das CRLs (CRL_urls) que devem ser processadas...
128    ler_conf()
129except:
130    print 'Erro lendo arquivos de configuracao(ERR-02X)';
131    sys.exit(1);
132
133CAfile =  Confs['CAs']
134CRLs = Confs['CRLs']
135arquivo = Confs['arquivos_crls']
136log = Confs['log']      # Deixe log = '' para saida da log na console .....
137lenMax = int(Confs['lenMax']) # Tamanho maximo do arquivo de log para iniciar o rotate....
138bkpNum = int(Confs['bkpNum']) # Número de arquivos de log mantidos pelo rotate....
139import logging
140import logging.handlers
141
142# Prepara para fazer a log das atualizações das crls ...
143fm = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
144mL = logging.getLogger('ML')
145mL.setLevel(logging.DEBUG)
146hd = logging.handlers.RotatingFileHandler(log, mode='a', maxBytes=lenMax, backupCount=bkpNum)
147hd.setFormatter(fm)
148mL.addHandler(hd)
149
150if len(sys.argv) > 1:
151    if os.path.isfile(sys.argv[1]):
152        Confs['arquivos_crls'] = sys.argv[1]
153    else:
154        mL.critical('Erro lendo arquivo de configuracao' + sys.argv[1] + ': Nao localizado.\n')
155        sys.exit(2)
156
157mL.info('Processando arquivo de urls para obter crls: ' +Confs['arquivos_crls'] + ' .')
158
159for crl in CRL_urls:
160    arquivo = crl[1].strip() + os.path.split(crl[0])[1].strip()
161    url = crl[0].strip()
162    # Obtendo o arquivo com wget ...
163    mL.info('Buscando a CRL: ' + url)
164    saida_wget = ExeCmd("wget --timeout=10 --tries=1 " + url + " -O " + arquivo)
165    # Abaixo estamos comandando a execucao "openssl crl" passando o arquivo crl .
166    # O resultado esta em saida. Tem de ser 'verify OK' .
167    if os.path.exists(arquivo) and os.path.getsize(arquivo) > 0:
168        mL.info('Verificando ' + arquivo + '(' + str(os.path.getsize(arquivo)) + ' Bytes)')
169        saida = ExeCmd('openssl crl -CAfile ' + CAfile + '  -in ' + arquivo + ' -inform DER -noout')
170        # usa a funcao fazlog porque saida he um array.....
171        fazlog(mL,saida)
172        try:
173            aux1 = replace(saida[1],'\n','')
174            if not aux1 == 'verify OK':
175                mL.critical('Erro verificando a CRL ' + arquivo + '\n')
176                try:
177                    os.remove(arquivo)
178                except:
179                    pass
180                continue
181            # A crl foi verificada e est OK....
182            # Atuaiza a data do arquivo...
183            saida = ExeCmd('touch ' + arquivo)
184        except:
185            mL.critical('Erro processando o status da verificacao da CRL ' + arquivo + '\n')
186            try:
187                os.remove(arquivo)
188            except:
189                pass
190            continue
191    else:
192            # usa a funcao fazlog porque saida_wget he um array.....
193            fazlog(mL,saida_wget)
194            mL.critical('Nao foi possivel obter a CRL ' + url + '\n')
195            try:
196                os.remove(arquivo)
197            except:
198                pass
Note: See TracBrowser for help on using the repository browser.