15 de setembro de 2011

Funcionamento do Certificate Store do Windows

Tenho recebido com frequência dúvidas a respeito do acesso a certificados digitais importados no Certificate Store do Windows. Pela forma com que as dúvidas têm sido colocadas, percebi que faltou nos posts sobre esse assunto dar uma ideia global do que é o Certificate Store e como ele funciona.

Como disse no post sobre acesso ao Certificate Store do Windows com C#, o Certificate Store é um repositório centralizado onde são armazenados os certificados digitais disponíveis em um computador. É possível acessar esse repositório visualmente, acessando o console de gerenciamento pela opção Executar do menu Iniciar do Windows. Na caixa de edição que se abre, digite o comando abaixo:
mmc \windows\system32\certmgr.msc
Normalmente, a tela que aparece é similar à que está reproduzida abaixo:
Certificados Digitais
Com essa aplicação, é possível gerenciar os certificados instalados no computador, fazendo a importando de novos certificados e eliminando aqueles que não são mais desejados. Observe que o painel à esquerda mostra uma organização hierárquica, com uma raiz e diversas pastas embaixo dela. O nó raiz nesse exemplo apresenta o nome Certificates - Current User. Isso significa que todas as pastas sob ele e os certificados listados no painel à direita estão disponíveis apenas para o usuário que atualmente está logado no Windows.

As pastas servem para agrupar os certificados por semelhança na finalidade de uso. Na imagem, a pasta Personal está selecionada, permitindo-nos visualizar à direita os certificados catalogados para uso pessoal do usuário Windows atual. Outro exemplo de pasta é a que contém certificados identificando as Autoridades Certificadoras (CA), que são as entidades responsáveis pela emissão dos certificados.

Do ponto de vista do programador que vai acessar o Store usando a classe X509Store (ou o CAPICOM), essas duas informações - nó raiz e pasta - são imprescindíveis. O construtor da X509Store aceita como parâmetros o Store Name e o Store Location, sendo que o name corresponde à "pasta" onde está o certificado e location é o nó raiz ao qual a pasta está atrelada. A pasta personal é mapeada com o nome "My" para essa função.

Agora, imagine que você construiu um serviço que acessa o Certificate Store. No Windows, cada serviço é executado por um usuário específico que é configurado na guia Log On das propriedades do serviço. Com isso, ele poderá entrar em execução mesmo que ninguém esteja logado no Windows pois o login será feito automaticamente para o usuário que foi associado ao serviço. Portanto, se você importou um certificado para seu usuário mas está executando o serviço com um usuário diferente, esse outro usuário não enxergará o seu certificado.

Isso vale também para aplicações ISAPI - sites construídos em ASP ou ASP.NET se encaixam nessa categoria - uma vez que elas rodam como parte do serviço do IIS (Internet Information Services). O IIS é atrelado normalmente a um usuário padrão do Windows chamado Local System, significando que as credencias desse usuário é que serão utilizadas para acessar os recursos do sistema, tais como o registry e a hierarquia de certificados.

Para resolver esse impasse, podemos importar o certificado num Store Location acessível por todos os usuários. Como a aplicação disponível carrega apenas originalmente o Location "Current User", teremos que adicionar na mão um plugin para o Location com a característica que precisamos. Esse Location é o "Local Computer".

Para isso, execute o MMC.exe sem parâmetros no Iniciar -> Executar do Windows. No menu File da aplicação, clique na opção Add/Remove snap-in e então o botão "Add" para ativar a tela de adição dos plugins. Na lista de plugins que aparece, selecione certificates e novamente clique em "Add". A imagem abaixo mostra a tela de adição do plugin de gerenciamento de certificados com a opção "Computer Account" (o computer local) selecionada.
Add snap-in

Após a adição, o console mostrará uma hierarquia similar à da imagem no início deste post, com a exceção de que o nó raiz será "Local Computer". Agora podemos importar certificados na pasta "Personal" e torná-los disponíveis para os programas, independentemente das credenciais do usuário que está executando esse programa ou serviço.

Certificados importados na pasta "Personal" do "Local Computer" podem, então, ser acessados abrindo-se o Certificate Store com os parâmetros mostrados abaixo:
X509Store lStore = new X509Store (StoreName.My, StoreLocation.LocalComputer);
/* ... */


5 comentários :

Fábio disse...

Olá Luis, Veja se você pode me ajudar.
Fiz os passos sugeridos e pelo MMC vejo o meu certificado instalado, tenho que salvar? Tenho que importar?

Fiz o seguinte:

Dim store As New X509Store(StoreName.My, StoreLocation.LocalMachine)
Dim x509 As X509Certificate2 = Nothing
Dim Key As New RSACryptoServiceProvider()

store.Open(OpenFlags.ReadOnly Or OpenFlags.OpenExistingOnly)
Dim collection As X509Certificate2Collection = CType(store.Certificates, X509Certificate2Collection)
Dim fcollection As X509Certificate2Collection = CType(collection.Find(X509FindType.FindByTimeValid, DateTime.Now, False), X509Certificate2Collection)
Dim scollection As X509Certificate2Collection = X509Certificate2UI.SelectFromCollection(fcollection, Titulo, "Select a certificate from the following list to get information on that certificate", X509SelectionFlag.MultiSelection)

Na ultima linha esta apresentando o erro: The current session is not interactive

Minha aplicação esta em Asp.net

Desde já agradeço

Luís Gustavo Fabbro disse...

Fábio

A função SelectFromCollection do X509Certificate2UI apresenta uma caixa de diálogo para que o usuário escolha um dos certificados da coleção.

Como seu código é parte de um programa Asp.NET, ele será executado no servidor, tornando impossível a interação com o usuário. Além disso, o IIS é um serviço do Windows e, como ele funciona sem interface gráfica, não faz sentido ele interagir com o usuário.

[]s.

Fábio disse...

Olá Luís, Obrigado pela atenção,

Pensei que fazendo a alteração acima resolveria meu problema, e que problema, estou pesquisando muito sobre o assunto e vejo que tem muita gente batendo cabeça.

Já cheguei a abrir o reposítório com Capicom e javascript, mas não consegui progredir, tenho a minha classe de assinatura pronta no Asp.net, pensei algo como copiar os dados para dentro da coleção X509Certificate2. seria possivel?

Abcs

Luís Gustavo Fabbro disse...

Fábio

Nunca trabalhei com o cenário onde é preciso enviar para o servidor um certificado existente no navegador.

Mas fiz uma pesquisa rápida e me pareceu que o próprio navegador inclui tais informações quando envia uma requisição ao servidor. Dê uma olhada na propriedade ClientCertificate da variável Request de sua página ASP.Net.

Não fui a fundo na pesquisa pra levantar se há pré requisitos necessários para que o certificado seja incluído na requisição ...

[]s

Anônimo disse...

Olá Fábio,
Também estou com o mesmo problema.Já fiz muitas coisas:
- Exportei o pfx para base64, converti para byte[] e importei para um X509Certificate. Não funciona: 403 - forbiden.
Fiz o mesmo com a classe X509Certificate2Collection, e .... nada.
A idéia é colocar todos os dados do certificado no servidor e importar para um X509, mas só funciona na máquina local. Talvez se vc tiver acesso ao servidor (eu não tenho, é terceirizado) seja possivel configurar o IIS, como ocorre com as SEFAZs, que abrem normalmente o store de certificados da máquina cliente.
abr,
Manoel Emygdio.

Postar um comentário

OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.

Observação: somente um membro deste blog pode postar um comentário.