É um nome principal de serviço (SPN) ligado a uma máquina específica?
Pergunta
No momento eu estou recebendo um KrbException: verificação de integridade no campo descriptografado falhou (31) com a minha aplicação de demonstração GSS (no lado do servidor). Agora eu estou procurando a razão para isso. Tenho a suspeita, que se trata do fato de que
- o cliente eo aplicativo de servidor executado na mesma máquina (localhost) e / ou
- o SPN foi gerado por uma outra máquina (computador)
O segundo meio, que o principal de serviço foi gerado por um xxx0815.domain.net máquina, de modo que o SPN é HTTP/xxx0815.domain.net@DOMAIN.NET. E a minha máquina não é essa, mas eu tenho o arquivo keytab para que método de login do servidor bem-sucedido.
Eu suspeito corretamente ou estou fazendo outro erro?
configuração do servidor e código fonte:
server.conf
Server {
com.sun.security.auth.module.Krb5LoginModule
required
isInitiator=false
doNotPrompt=true
useKeyTab=true
keyTab="gssdemo.keytab"
storeKey=true
principal="HTTP/xxx0815.domain.net@DOMAIN.NET"
debug=true;
};
GSSServer.java (omitido o material clichê)
GSSManager manager = GSSManager.getInstance();
GSSName serverName = manager.createName(getServerName(), null);
GSSCredential serverCred = manager.createCredential(serverName,
GSSCredential.INDEFINITE_LIFETIME,
createKerberosOid(),
GSSCredential.ACCEPT_ONLY);
GSSContext context = manager.createContext(serverCred);
System.out.println("Context created successfully. Now incoming tokens could be accepted.");
ServerSocket serverSocket = new ServerSocket(55555);
SocketAdapter ca = new SocketAdapter(serverSocket.accept());
while (!context.isEstablished()) {
byte[] inToken = ca.readToken();
byte[] outToken = context.acceptSecContext(inToken, 0, inToken.length);
if (outToken != null) {
ca.sendToken(outToken);
}
}
System.out.println("Context established");
System.out.println("Connected user is: " + context.getSrcName());
context.dispose();
A configuração do cliente e código fonte:
client.conf
Client {
com.sun.security.auth.module.Krb5LoginModule
required
useTicketCache=true
debug=true;
};
GssClient.java (clichê omitido)
GSSManager manager = GSSManager.getInstance();
GSSName clientName = manager.createName(getClientName(), null);
GSSCredential clientCred = manager.createCredential(clientName,
8 * 3600,
createKerberosOid(),
GSSCredential.INITIATE_ONLY);
GSSName serviceName = manager.createName("HTTP/xxx0815.domain.net@DOMAIN.NET", null);
GSSContext context = manager.createContext(serviceName,
createKerberosOid(),
clientCred,
GSSContext.DEFAULT_LIFETIME);
context.requestMutualAuth(true);
context.requestConf(false);
context.requestInteg(true);
System.out.println("Establishing context");
SocketAdapter ca = new SocketAdapter(new Socket("localhost", 55555));
byte[] inToken = new byte[0];
while (true) {
byte[] outToken = context.initSecContext(inToken, 0, inToken.length);
if (outToken != null) {
ca.sendToken(outToken);
}
if (context.isEstablished()) {
break;
}
inToken = ca.readToken();
}
System.out.println("Context established: " + context.isEstablished());
context.dispose();
Eu verifiquei os dados da rede de entrada e saída - é o mesmo em ambos os lados para que eu possa descartar um problema lá (eu BASE64-codificado a saída e, em seguida, basta enviá-lo através dos fluxos Eu acho que não há muito. que pode dar errado lá ...).
A exceção que eu recebo:
Caused by: GSSException: Failure unspecified at GSS-API level (Mechanism level: Integrity check on decrypted field failed (31))
at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:741)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:323)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:267)
at de.westlb.mrm.sandbox.gss.GssServer.acceptAndEstablish(GssServer.java:88)
at de.westlb.mrm.sandbox.gss.GssServer.run(GssServer.java:66)
... 4 more
Caused by: KrbException: Integrity check on decrypted field failed (31)
at sun.security.krb5.internal.crypto.DesCbcEType.decrypt(DesCbcEType.java:154)
at sun.security.krb5.internal.crypto.DesCbcMd5EType.decrypt(DesCbcMd5EType.java:33)
at sun.security.krb5.internal.crypto.DesCbcEType.decrypt(DesCbcEType.java:125)
at sun.security.krb5.internal.crypto.DesCbcMd5EType.decrypt(DesCbcMd5EType.java:33)
at sun.security.krb5.EncryptedData.decrypt(EncryptedData.java:168)
at sun.security.krb5.KrbApReq.authenticate(KrbApReq.java:267)
at sun.security.krb5.KrbApReq.<init>(KrbApReq.java:134)
at sun.security.jgss.krb5.InitSecContextToken.<init>(InitSecContextToken.java:79)
at sun.security.jgss.krb5.Krb5Context.acceptSecContext(Krb5Context.java:724)
... 8 more
Solução
Se a verificação de integridade falhar que sugere que os dados não estão sendo enviadas / recebidas corretamente (que ou esta é uma mensagem de erro incorreta). Em outras palavras ocorreu alguma modificação.
Eu sei que você diz ter verificado que os dados enviados coincide com os dados recebidos no nível da rede, no entanto você tem certeza que não está corrompido antes de enviar, ou após o recebimento? Eu sugiro que você revise seu código para este primeiro.
edit: Em resposta à sua pergunta, a principal de serviço (realmente, qualquer bilhete) pode ser ligado a uma máquina específica, mas isso é normalmente feito em termos de endereço IP. Em qualquer caso algo como isso deve resultar em um erro de nível superior diferente.
O erro que você está recebendo soa como ele está tendo problemas para descriptografar o bilhete em primeiro lugar. Uma possível causa disso é que ele está usando a tecla errada, o que pode estar relacionado ao seu copiar o keytab. A chave errada também pode ser causada pelo uso do bilhete errado (como Kerberos basicamente fornece um protocolo de gerenciamento de chaves). É possível que você tenha armazenado em cache um bilhete velho / incorreta?