arquivos_para_deletar);
}
#--------------------------------------------------------------------------------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------------------------------------------------------------------------
# Recupera dados de um certificado no formato pem
#--------------------------------------------------------------------------------------------------------------------------------------------------------
function certificado($certificado_pem)
{
if (!$certificado_pem)
{
$this->apresentado = False;
return False; # Sem parametro ...
}
$this->dados = recupera_dados_do_ceritificado_digital($certificado_pem);
# Certificado foi processado, as informacoes obtidas estao em $this->dados.
$this->apresentado = true;
}
#--------------------------------------------------------------------------------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------------------------------------------------------------------------
# Encriptar uma msg($m) para o(s) destinatario(s) $c(array com certificados)com os headers passados em $h.
#--------------------------------------------------------------------------------------------------------------------------------------------------------
public function encriptar($m,$c,$h)
{
if($m == '') return false;
if(!is_array($c)) return false;
$aux = count($c);
if($aux < 1) return false;
if(!is_array($h) ) return false;
# Tem de verificar todos os certificados que serao utilizados para criptografar a msg..
# Inserir a rotina aqui....
$m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
//echo $m_arquivo_temporario.'
';
if(!grava_arquivo($m_arquivo_temporario,$m))
{
return false;
}
$enc_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
//echo $enc_arquivo_temporario.'
';
// LIMPA ERROS ... Pode ser um problema para outras aplicacoes que usam openssl(fonte de erros unica).
while ($erro = openssl_error_string()); // Limpa buffer de erros anteriores......
$this->erros_ssl = array();
$resultado = openssl_pkcs7_encrypt($m_arquivo_temporario,$enc_arquivo_temporario,$c,$h);
if(!$resultado)
{
// Guarda msgs de erro ...
while ($erro = openssl_error_string())
{
$this->erros_ssl[] = $erro;
}
deleta_arquivos_temporarios($this->arquivos_para_deletar);
$this->arquivos_para_deletar = array();
return false;
}
# Recupera a msg criptada......
$retorno = file_get_contents($enc_arquivo_temporario);
//$aux = explode(chr(0x0A),file_get_contents($enc_arquivo_temporario));
//$retorno='';
/*
$flag = false;
for ($i = 0; $i < count($aux); $i++)
{
if(!$aux[$i])
{
if(!$flag)
{
//$retorno .= '-----BEGIN PKCS7-----'.chr(0x0A);
$flag = true;
}
}
else
{
$retorno .= $aux[$i].chr(0x0A);
}
}
//$retorno .= '-----END PKCS7-----'.chr(0x0A);
*/
deleta_arquivos_temporarios($this->arquivos_para_deletar);
$this->arquivos_para_deletar = array();
return $retorno;
}
#--------------------------------------------------------------------------------------------------------------------------------------------------------
#--------------------------------------------------------------------------------------------------------------------------------------------------------
# Verifica uma msg($m) assinada...
#--------------------------------------------------------------------------------------------------------------------------------------------------------
public function verificar($m)
{
if($m == '') return false;
$m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
if(!grava_arquivo($m_arquivo_temporario,$m))
{
deleta_arquivos_temporarios($this->arquivos_para_deletar);
$this->arquivos_para_deletar = array();
return false;
}
$vrf_cert_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
$vrf_msg_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
// LIMPA ERROS ... Pode ser um problema para outras aplicacoes que usam openssl(fonte de erros unica).
while ($erro = openssl_error_string()); // Limpa buffer de erros anteriores......
$this->erros_ssl = array();
$resultado = openssl_pkcs7_verify($m_arquivo_temporario,0, $vrf_cert_arquivo_temporario,array($GLOBALS['CAs']),$GLOBALS['CAs'],$vrf_msg_arquivo_temporario);
$retorno = true;
if(!$resultado)
{
# Indica ocorrencia de erro ...
$retorno = false;
// Guarda msgs de erro ...
while ($erro = openssl_error_string())
{
$this->erros_ssl[] = $erro;
}
# Reexecuta o comando com um nivel menor de criticas.
$this->cert_assinante = $this->extrai_certificado_da_msg_assinada($m);
if(!$this->cert_assinante)
{
# Se nao foi possivel obter o certificado retorna com falso .....
deleta_arquivos_temporarios($this->arquivos_para_deletar);
$this->arquivos_para_deletar = array();
return false;
}
}
else
{
# Guarda o certificado usado para assinar a msg
$this->cert_assinante = file_get_contents($vrf_cert_arquivo_temporario);
}
$this->msg_sem_assinatura = file_get_contents($vrf_msg_arquivo_temporario);
$this->certificado($this->cert_assinante);
if (!$this->apresentado)
{
$this->erros_ssl[] = 'Certificado da Msg nao pode ser tratado.';
$retorno = false;
}
else
{
while ($erro = openssl_error_string()); // Limpa buffer de erros anteriores......
# Certificado poderia ter assinado um email??
if(!openssl_x509_checkpurpose($vrf_cert_arquivo_temporario,X509_PURPOSE_SMIME_SIGN))
{
$this->erros_ssl[] = 'Certificado nao poderia ter sido utilizado para assinar email.';
while ($erro = openssl_error_string())
{
$this->erros_ssl[] = $erro;
}
$retorno = false;
}
// Isto esta codificado assim antecipando nova versao do parseador....
$this->dados['KEYUSAGE']['digitalSignature'] =TRUE;
$this->dados['EXTKEYUSAGE']['emailProtection'] = '1.3.6.1.5.5.7.3.4';
//testa se certificado revogado
$revogado = new Verifica_Certificado($this->dados,$this->cert_assinante);
$this->dados['REVOGADO'] = false;
if(!$revogado->status){
$this->erros_ssl[] = $revogado->msgerro;
foreach ($revogado->erros_ssl as $item)
{
$this->erros_ssl[] = $item;
}
if ($revogado->revogado)
$this->dados['REVOGADO'] = true;
$retorno = false;
}
}
deleta_arquivos_temporarios($this->arquivos_para_deletar);
$this->arquivos_para_deletar = array();
return $retorno;
}
public function extrai_certificado_da_msg_assinada($m)
{
$retorno = false;
if(!$m)
{
return $retorno;
}
$m_arquivo_temporario = gera_nome_arquivo_temporario(&$this->arquivos_para_deletar);
if(!grava_arquivo($m_arquivo_temporario,$m))
{
deleta_arquivos_temporarios($this->arquivos_para_deletar);
$this->arquivos_para_deletar = array();
return $retorno;
}
$w='';
$saida = array();
$w = exec('cat ' . $m_arquivo_temporario . ' | openssl smime -pk7out | openssl pkcs7 -print_certs',$saida);
if(!$w=='')
{
deleta_arquivos_temporarios($this->arquivos_para_deletar);
$this->arquivos_para_deletar = array();
return $retorno;
}
$aux1 = '';
// gera uma unica string com o conteudo retornado pelo comando...
foreach($saida as $linha)
{
$aux1 .= $linha.chr(0x0A);
}
// cria um array com os certificados retornados..
$aux2 = explode('-----BEGIN CERTIFICATE-----',$aux1);
array_shift($aux2);
// isolando certificados..
$aux5 = array();
foreach($aux2 as $item)
{
$aux3 = explode('-----END CERTIFICATE-----',$item);
$aux4 = '-----BEGIN CERTIFICATE-----' . $aux3[0] . '-----END CERTIFICATE-----';
$aux5[] = $aux4;
}
// Gera array com as CAs que assinaram os certificados encontrados na msg....
$aux5_ACs = array();
foreach($aux5 as $item)
{
$cert = openssl_x509_parse($item);
$aux5_ACs[$cert[issuer][CN]] = $cert[issuer][CN];
}
// Verifica qual certificado tem no subject um CN que nao he uma CA.
foreach($aux5 as $item)
{
$cert = openssl_x509_parse($item);
if(!$aux5_ACs[$cert[subject][CN]])
{
$retorno = $item;
break;
}
}
deleta_arquivos_temporarios($this->arquivos_para_deletar);
$this->arquivos_para_deletar = array();
return $retorno;
}
}
?>