Como validar credenciais em cache do usuário em um domínio?

Quando você faz logon no Windows, suas credenciais sãoem cache. Isso permite que você uselogon único. Se você deveria procurar outro computador, por exemplo:

\\hydrogen

você poderianão ser solicitadas credenciais.

O Windows levará seu:

nome de usuário atual(hash) senha

e tente autenticar você automaticamente. O interessante é que isso funciona mesmo se sua estação de trabalho não estiver no domínio. Windows iráautomaticamente use seu nome de usuário e senha ao se conectar ao servidor. E se o seu:

local nome de usuário / senha corresponde adomínio usuário senha

você é deixado automaticamente entrar.

Bonita foto:

Isso é chamadoLogon único. Você entra no Windows uma vez e suas credenciais em cache são usadas para validá-lo conforme você usa outras coisas na rede.

Os navegadores também fazem isso

Chrome, Internet Explorer e Firefox também fazem uma variação disso. Se você precisar fazer login em um site, e o servidor suportarNegociação autorização, o servidor enviará de volta uma indicação de que você deve tentar as credenciais do Windows / Domínio / Kerberos do usuário:

HTTP/1.1 401 Unauthorized
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
Date: Thu, 09 Jul 2015 14:35:58 GMT
Content-Length: 0

O Chrome levará seuem cache credenciais e (após alguma mágica intermediária) encaminhe-as para o servidor da web:

GET http://hr.woodglue.com HTTP/1.1
Host: hr.woodglue.com
Authorization: Negotiate YIIFzwYGKwYBBQUCoIIFwzCCBb....

A Microsoft fala sobre esse mecanismo no Internet Explorer no artigo antigo:

Autenticação de plataforma cruzada baseada em HTTP usando o protocolo de negociação

O cliente chamaAcquireCredentialsHandle() eInitializeSecurityContext() com o SPN para criar o Contexto de Segurança que solicita o ticket de sessão do TGS / KDC.Você valida em um domínio, não em servidores

Um ponto final que quero mencionar é que servidores, servidores Web, estações de trabalho, servidores de arquivos não validam credenciais em relação a umservidor, eles validam em um domíniocontrolador. Você tem um nebulosofloresta de muitos servidores de domínio e um deles lida com sua solicitação.

Em outras palavras, você não valida credenciais contra:

\\uranium (um controlador de domínio nowoodglue.com domínio)

você valida credenciais contra:

awoodglue.com domínio

Temos o conceito importante de que alguém pode:

valide suaem cache credenciaiscontra um domíniosem precisar digitar um nome de usuário ou senhaComo posso fazer isso?

Como posso validar as credenciais em cache de alguém? Como podeI:

validar o usuárioem cache credenciaiscontra umdomíniosem o usuário precisa digitar um nome de usuário ou senha(ou seja, usando as credenciais em cache do Windows)

O ponto importante é que não se sabe (ou se importa):

se a máquina do usuário estiver associada a um domíniose a máquina do usuário estiver associada a um grupo de trabalhose a máquina do usuário estiver associada aowoodglue.com ou algum outro domínio (por exemplo,superglue.com)os nomes dos servidores que alimentam osuperglue.com domínio

Eu não sei como fazer isso.
Não sei quais tecnologias de API estão envolvidas.

Eu sei que existe uma API chamadaInterface do provedor de suporte de segurança (SSPI). É isso que poderesWWW-Authenticate: Negotiate (embora eu não saiba se é isso que habilita o SMB a partir de um PC sem domínio).

O código-fonte aberto do Chromium pode começar com um trecho de códigohttp_auth_sspi_win.cc. Eles usam a função SSPIAcquireCredentialsHandle:

int AcquireDefaultCredentials(CredHandle* cred) 
{
   TimeStamp expiry;
   // Pass the username/password to get the credentials handle.
   // Note: Since the 5th argument is NULL, it uses the default
   // cached credentials for the logged in user, which can be used
   // for a single sign-on.
   SECURITY_STATUS status = library->AcquireCredentialsHandle(
         NULL,  // pszPrincipal
         const_cast<SEC_WCHAR*>(package),  // pszPackage
         SECPKG_CRED_OUTBOUND,  // fCredentialUse
         NULL,  // pvLogonID
         NULL,  // pAuthData
         NULL,  // pGetKeyFn (not used)
         NULL,  // pvGetKeyArgument (not used)
         cred,  // phCredential
         &expiry);  // ptsExpiry
}

Passe o nome de usuário / senha para obter o identificador de credenciais.

Nota: Como o quinto argumento é NULL, ele usa as credenciais em cache padrão para o usuário conectado, que pode ser usado para uma conexão única.

este"saída" ligar paraAcquireCredentialsHandle é seguido por uma chamada paraInitializeSecurityContext. A ideia é queInitializeSecurityContext gera um blob opaco que representa o cliente.

Você pode executar um conjunto paralelo de chamadas:

"entrada" ligar paraAcquireCredentialsHandleligarAcceptSecurityContext, passando o blob retornado anteriormente deInitializeSecurityContext

Pararoubar re-hospedarA excelente imagem de Daniel Doubrovkine:

Nota: Nesse caso"cliente" e"servidor" são usados para se referir ao contexto de produtor e consumidor. No meu caso, o"cliente" e"servidor" estão na mesma máquina.

Mas essa linha de"mostra esforço de pesquisa" desmorona porque eu não vejo em nenhum lugarInitializeSecurityContext onde eu posso especificarwoodglue.com como o domínio para validar.

Eu sei dissoInitializeSecurityContext entra em contato com um servidor kerberos e obtém um"bilhete" blob. Esse blob de ticket é passado para o "servidor" por meio deAcceptSecurityContext. Às vezes, o blob pode ser passado por uma rede; no meu caso, é passado na memória na mesma máquina.

Mas não vejo como especificar o servidor de domínio que ele deve entrar em contatopara esse bilhete.

Não implica que o SSPI seja útil para resolver meu problema. É apenas"esforço de pesquisa".

Esforço de pesquisa mais antigoQual TargetName usar ao chamar InitializeSecurityContext (Negotiate)?Como validar credenciais de domínio (do código nativo)?Validar a senha de um usuário usando o hash?Win32: Como validar credenciais no Active Directory?Como executar a autenticação do Windows?

Obviamente, durante tudo isso, se as credenciais em cache não forem válidas no domínio especificado, eu teria que solicitar ao usuário um nome de usuário e senha. Mas nomes de usuário e senhas são maus, a ruína da computação, e eu quero evitá-los.

eu estou usando código nativo; não c#.

questionAnswers(0)

yourAnswerToTheQuestion