source: branches/2.3/security/classes/CertificadoB.php @ 5822

Revision 5822, 12.1 KB checked in by rafaelraymundo, 12 years ago (diff)

Ticket #2568 - Logon com token eToken Pro 32K, remove limite de cyphertext.

Line 
1<?php
2require_once('funcoes_auxiliares.php');
3require_once('Verifica_Certificado_conf.php');
4require_once('Verifica_Certificado.php');
5
6//  Pre-requisito: A extensao openssl deve estar disponivel no PHP ....
7class certificadoB
8{
9  public $dados = array();        # Area para armazenar os dados recuperados do certificado.
10  public $apresentado = false;    # Deve ser testado para verificar se no certificado processado foi localizado o CPF
11  public $erros_ssl = array();
12  public $cert_assinante = '';
13  public $msg_sem_assinatura = '';  #conteï¿œdo da mensagem sem assinatura, que retorna da funᅵᅵo verify do openssl
14  public $arquivos_para_deletar = array();
15
16  public function __construct()
17  {
18    if(!extension_loaded('openssl'))
19    {
20      #PHP sem suporte ao openssl.....
21      return false;
22    }
23    $this->dados = array();
24    $this->dados_xml = '';
25    $this->apresentado = false;
26    $this->erros_ssl = array();
27    $this->cert_assinante = '';
28    $this->msg_sem_assinatura = '';
29    $this->arquivos_para_deletar = array();
30  }
31
32public function __destruct()
33  {
34    #Remover arquivos temporarios.....
35    deleta_arquivos_temporarios($this->arquivos_para_deletar);
36  }
37
38# Recupera dados de um certificado no formato pem
39  function certificado($certificado_pem)
40  {
41      if (!$certificado_pem)
42    {
43        $this->apresentado = False;
44        return False;    # Sem parametro ...
45    }
46   $this->dados = recupera_dados_do_ceritificado_digital($certificado_pem);
47   $this->dados_xml = gera_xml_com_dados_do_certificado($this->dados);
48     # Certificado foi processado, as informacoes obtidas estao em $this->dados.
49  $this->apresentado = true;
50  }
51
52# Encriptar senha ......
53        public function encriptar_senha($s,$c)
54        {
55                if($s == '')    return false;
56                if($c == '')    return false;
57                $senha_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
58                //echo $senha_arquivo_temporario.'<br>';
59                if(!grava_arquivo($senha_arquivo_temporario,$s))
60                {
61                        return false;
62                }
63                $cert_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
64                //echo $cert_arquivo_temporario.'<br>';
65                if(!grava_arquivo($cert_arquivo_temporario,$c))
66                {
67                        return false;
68                }
69                $senha_criptografada_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
70                //echo $senha_criptografada_arquivo_temporario.'<br>';
71
72                $w = exec('openssl rsautl -in ' . $senha_arquivo_temporario . ' -out ' . $senha_criptografada_arquivo_temporario . ' -inkey ' . $cert_arquivo_temporario . ' -certin -pkcs -keyform PEM -encrypt',$saida);
73
74                if(!file_exists($senha_criptografada_arquivo_temporario))
75                {
76                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
77                        $this->arquivos_para_deletar = array();
78                        return false;
79                }
80
81                # Recupera a senha criptada, binario.....
82                $retorno = file_get_contents($senha_criptografada_arquivo_temporario);
83
84                deleta_arquivos_temporarios($this->arquivos_para_deletar);
85                $this->arquivos_para_deletar = array();
86
87                //if(strlen($retorno) != 128) return false;
88
89                return base64_encode($retorno);
90        }
91
92
93# Encriptar uma msg($m) para o(s) destinatario(s) $c(array com certificados)com os headers passados em $h.
94        public function encriptar($m,$c,$h)
95        {
96                if($m == '')    return false;
97                if(!is_array($c))       return false;
98                $aux = count($c);
99                if($aux < 1)    return false;
100                if(!is_array($h) )      return false;
101                # Tem de verificar todos os certificados que serao utilizados para criptografar a msg..
102                # Inserir a rotina aqui....
103                $m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
104                //echo $m_arquivo_temporario.'<br>';
105                if(!grava_arquivo($m_arquivo_temporario,$m))
106                {
107                        return false;
108                }
109                $enc_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
110                //echo $enc_arquivo_temporario.'<br>';
111
112                // LIMPA ERROS ... Pode ser um problema para outras aplicacoes que usam openssl(fonte de erros unica).
113                while ($erro = openssl_error_string()); //  Limpa buffer de erros anteriores......
114                $this->erros_ssl = array();
115                // Se he PHP 5.4 , ou maior, usar "OPENSSL_CIPHER_AES_256_CBC" .
116                $cipher_id = ((double)phpversion() >= 5.4 ? OPENSSL_CIPHER_AES_256_CBC : OPENSSL_CIPHER_DES);
117                $resultado = openssl_pkcs7_encrypt($m_arquivo_temporario,$enc_arquivo_temporario,$c,$h,$flags=0,$cipherid=$cipher_id);
118                //$resultado = openssl_pkcs7_encrypt($m_arquivo_temporario,$enc_arquivo_temporario,$c,$h);
119                if(!$resultado)
120                {
121                        // Guarda msgs de erro ...
122                        while ($erro = openssl_error_string())
123                        {
124                                $this->erros_ssl[] = $erro;
125                        }
126                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
127                        $this->arquivos_para_deletar = array();
128                        return false;
129                }
130                # Recupera a msg criptada......
131                $retorno = file_get_contents($enc_arquivo_temporario);
132                deleta_arquivos_temporarios($this->arquivos_para_deletar);
133                $this->arquivos_para_deletar = array();
134                return $retorno;
135        }
136
137
138# Verifica uma msg($m) assinada...
139        public function verificar($m)
140        {
141                if($m == '')
142                {
143                    $this->erros_ssl[] = 'Não foi possível verificar a assinatura gerada. Contate o administrador';
144                    return false;
145                }
146                if(!$m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar))
147                    {
148                        $this->erros_ssl[] = 'Não foi possível verificar a assinatura gerada. Contate o administrador';
149                        $this->arquivos_para_deletar = array();
150                        return false;
151                    }
152                if(!grava_arquivo($m_arquivo_temporario,$m))
153                {
154                        $this->erros_ssl[] = 'Não foi possível verificar a assinatura gerada. Contate o administrador';
155                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
156                        $this->arquivos_para_deletar = array();
157                        return false;
158                }
159                if(!$vrf_cert_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar))
160                    {
161                        $this->erros_ssl[] = 'Não foi possível verificar a assinatura gerada. Contate o administrador';
162                        $this->arquivos_para_deletar = array();
163                        return false;
164                    }
165                if(!$vrf_msg_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar))
166                    {
167                        $this->erros_ssl[] = 'Não foi possível verificar a assinatura gerada. Contate o administrador';
168                        $this->arquivos_para_deletar = array();
169                        return false;
170                    }
171                $this->erros_ssl = array();
172                while ($erro = openssl_error_string()); //  Limpa buffer de erros anteriores......
173                $resultado = openssl_pkcs7_verify($m_arquivo_temporario,0, $vrf_cert_arquivo_temporario,array($GLOBALS['CAs']),$GLOBALS['CAs'],$vrf_msg_arquivo_temporario);
174                if($resultado === -1)
175                {
176                    $this->erros_ssl[] = 'Erro verificando assinatura. Contate o administrador';
177                    while ($erro = openssl_error_string())
178                        {
179                                $this->erros_ssl[] = $erro;
180                        }
181                    $retorno = false;
182                }
183                if($resultado === False)
184                    {
185                        while ($erro = openssl_error_string())
186                            {
187                                if(substr($erro, 0,20) === 'error:21075075:PKCS7')
188                                    {
189                                        $this->erros_ssl = array();
190                                        while ($erro = openssl_error_string()); //  Limpa buffer de erros anteriores......
191                                        $resultado = openssl_pkcs7_verify($m_arquivo_temporario,PKCS7_NOVERIFY, $vrf_cert_arquivo_temporario,array($GLOBALS['CAs']),$GLOBALS['CAs'],$vrf_msg_arquivo_temporario);
192                                        break;
193                                    }
194                                $this->erros_ssl[] = $erro;
195                            }
196                    }
197                $retorno = true;
198
199                if($resultado === False)
200                {
201                        # Indica ocorrencia de erro ...
202                        $this->erros_ssl[] = 'Erro. ';
203                        $retorno = false;
204                        // Guarda msgs de erro ...
205                        while ($erro = openssl_error_string())
206                        {
207                                $this->erros_ssl[] = $erro;
208                        }
209                        If(file_exists($vrf_msg_arquivo_temporario))
210                                {
211                                        $this->msg_sem_assinatura =  file_get_contents($vrf_msg_arquivo_temporario);
212                                }
213                        else
214                                {
215                                        $this->msg_sem_assinatura =  'Nao pode exibir a msg(CD-1)';
216                                        $this->erros_ssl[] = 'Nao pode exibir a msg(CD-1)';
217                                }
218                        # Reexecuta o comando com um nivel menor de criticas.
219                        $this->cert_assinante = $this->extrai_certificado_da_msg_assinada($m);
220                        if(!$this->cert_assinante)
221                        {
222                                # Se nao foi possivel obter o certificado retorna com falso .....
223                                If(file_exists($vrf_msg_arquivo_temporario))
224                                        {
225                                                $this->msg_sem_assinatura =  file_get_contents($vrf_msg_arquivo_temporario);
226                                        }
227                                else
228                                        {
229                                                $this->msg_sem_assinatura =  'Nao pode exibir a msg(CD-2)';
230                                                $this->erros_ssl[] = 'Nao pode exibir a msg(CD-2)';
231                                        }
232                                deleta_arquivos_temporarios($this->arquivos_para_deletar);
233                                $this->arquivos_para_deletar = array();
234                                return false;
235                        }
236                }
237                else
238                {
239                        # Guarda o certificado usado para assinar a msg
240                        $this->cert_assinante  =   file_get_contents($vrf_cert_arquivo_temporario);
241                 }
242                If(file_exists($vrf_msg_arquivo_temporario))  $this->msg_sem_assinatura =  file_get_contents($vrf_msg_arquivo_temporario);
243                $this->certificado($this->cert_assinante);
244                if (!$this->apresentado)
245                {
246                        $this->erros_ssl[] = 'Certificado da Msg nao pode ser tratado.';
247                        $retorno = false;
248                }
249                else
250                {
251                        while ($erro = openssl_error_string()); //  Limpa buffer de erros anteriores......
252                        # Certificado poderia ter assinado um email??
253                        if(!($this->dados['KEYUSAGE']['digitalSignature']))
254                        {
255                                $this->erros_ssl[] = 'Certificado nao poderia ter sido utilizado para assinar email.';
256                                while ($erro = openssl_error_string())
257                                        {
258                                                $this->erros_ssl[] = $erro;
259                                        }
260                                $retorno = false;
261                        }
262                        $revogado = new Verifica_Certificado($this->dados,$this->cert_assinante);
263                        $this->dados['REVOGADO'] = false;
264                        if(!$revogado->status){
265                                $this->erros_ssl[] = $revogado->msgerro;
266                                foreach ($revogado->erros_ssl as $item)
267                                        {
268                                                $this->erros_ssl[] = $item;
269                                        }
270                                if ($revogado->revogado)
271                                        $this->dados['REVOGADO'] = true;
272                                $retorno  = false;
273                        }
274                }
275                deleta_arquivos_temporarios($this->arquivos_para_deletar);
276                $this->arquivos_para_deletar = array();
277                return $retorno;
278        }
279
280        public function extrai_certificado_da_msg_assinada($m)
281        {
282                $retorno = false;
283                if(!$m)
284                {
285                        return $retorno;
286                }
287                $m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
288                if(!grava_arquivo($m_arquivo_temporario,$m))
289                {
290                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
291                        $this->arquivos_para_deletar = array();
292                        return $retorno;
293                }
294                $w='';
295                $saida = array();
296                $w = exec('cat ' . $m_arquivo_temporario . ' | openssl smime -pk7out | openssl pkcs7 -print_certs',$saida);
297                if(!$w=='')
298                {
299                        deleta_arquivos_temporarios($this->arquivos_para_deletar);
300                        $this->arquivos_para_deletar = array();
301                        return $retorno;
302                }
303                $aux1 = '';
304                // gera uma unica string com o conteudo retornado pelo comando...
305                foreach($saida as $linha)
306                {
307                        $aux1 .= $linha.chr(0x0A);
308                }
309                // cria um array com os certificados retornados..
310                $aux2 = explode('-----BEGIN CERTIFICATE-----',$aux1);
311                array_shift($aux2);
312                // isolando certificados..
313                $aux5 = array();
314                foreach($aux2 as $item)
315                {
316                        $aux3 = explode('-----END CERTIFICATE-----',$item);
317                        $aux4 = '-----BEGIN CERTIFICATE-----' . $aux3[0] . '-----END CERTIFICATE-----';
318                        $aux5[] = $aux4;
319                }
320                // Testa qual dos certificados nao he uma CA ....
321                foreach($aux5 as $item)
322                {
323                        $Dados_cert = recupera_dados_do_ceritificado_digital($item);
324                        if(!$Dados_cert['CA'])
325                                {
326                                        $retorno = $item;
327                                        break;
328                                }
329                }
330                deleta_arquivos_temporarios($this->arquivos_para_deletar);
331                $this->arquivos_para_deletar = array();
332                return $retorno;
333        }
334}
335?>
Note: See TracBrowser for help on using the repository browser.