このフォーラムで以前に同様の質問がありましたが、受け入れられた回答は役に立ちませんでした。私のサーバーには、クライアントから送信されたサービス チケットを検証するために使用したい Kerberos キータブ ファイルがあります。
他の場所に散らばっている Sun のドキュメントとサンプル コードに続いて、これは私が現在持っているものです。
- クライアントは、MYSPN の KDC からサービス チケットを要求します。
- クライアントはファイルをサービス サーバーに送信して、サービスへのアクセスを要求します。
- サーバーは、既に持っている MYSPN のキータブでサービス チケットを検証した後、アクセスを許可します。
#3を機能させるのに問題があります。私が得る特定のエラーは次のとおりです。
GSSException: No valid credentials provided (Mechanism level: Attempt to obtain new ACCEPT credentials failed!)
at sun.security.jgss.krb5.Krb5AcceptCredential.getInstance(Krb5AcceptCredential.java:100)
at sun.security.jgss.krb5.Krb5MechFactory.getCredentialElement(Krb5MechFactory.java:128)
at sun.security.jgss.krb5.Krb5MechFactory.getMechanismContext(Krb5MechFactory.java:200)
at sun.security.jgss.GSSManagerImpl.getMechanismContext(GSSManagerImpl.java:231)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:319)
at sun.security.jgss.GSSContextImpl.acceptSecContext(GSSContextImpl.java:285)
at cms.gssapi.Server$1.run(Server.java:188)
at cms.gssapi.Server$1.run(Server.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:357)
at cms.gssapi.Server.acceptSecurityContext(Server.java:182)
at cms.gssapi.Server.main(Server.java:59)
Caused by: javax.security.auth.login.LoginException: Unable to obtain Princpal Name for authentication
at com.sun.security.auth.module.Krb5LoginModule.promptForName(Krb5LoginModule.java:750)
at com.sun.security.auth.module.Krb5LoginModule.attemptAuthentication(Krb5LoginModule.java:646)
at com.sun.security.auth.module.Krb5LoginModule.login(Krb5LoginModule.java:559)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:784)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:203)
at javax.security.auth.login.LoginContext$5.run(LoginContext.java:721)
at javax.security.auth.login.LoginContext$5.run(LoginContext.java:719)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokeCreatorPriv(LoginContext.java:718)
at javax.security.auth.login.LoginContext.login(LoginContext.java:590)
at sun.security.jgss.GSSUtil.login(GSSUtil.java:264)
at sun.security.jgss.krb5.Krb5Util.getKeys(Krb5Util.java:202)
at sun.security.jgss.krb5.Krb5AcceptCredential$1.run(Krb5AcceptCredential.java:95)
at sun.security.jgss.krb5.Krb5AcceptCredential$1.run(Krb5AcceptCredential.java:93)
at java.security.AccessController.doPrivileged(Native Method)
at sun.security.jgss.krb5.Krb5AcceptCredential.getInstance(Krb5AcceptCredential.java:92)
... 11 more
これは、keytab を使用してクライアントのサービス チケットを検証しようとするサーバー コードのスニペットです。
public static void main( String[] args) {
Properties props = new Properties();
props.load( new FileInputStream( "server.properties"));
System.setProperty( "sun.security.krb5.debug", "true");
System.setProperty( "java.security.krb5.realm", props.getProperty( "realm"));
System.setProperty( "java.security.krb5.kdc", props.getProperty( "kdc"));
System.setProperty( "java.security.auth.login.config", "./jaas.conf");
System.setProperty( "javax.security.auth.useSubjectCredsOnly", "false");
krb5Oid = new Oid( "1.2.840.113554.1.2.2");
Server server = new Server();
server.login();
byte serviceTicket[] = readClientTicketFromFile();
String clientName = server.acceptSecurityContext(serviceTicket);
}
private static byte[] readClientTicketFromFile() throws IOException {
BufferedReader in = new BufferedReader( new FileReader( "serviceticket.token"));
String str;
StringBuffer buffer = new StringBuffer();
while ((str = in.readLine()) != null) {
buffer.append( str + "\n");
}
in.close();
BASE64Decoder decoder = new BASE64Decoder();
return decoder.decodeBuffer( buffer.toString());
}
private static Oid krb5Oid;
private Subject login() throws LoginException {
LoginContext loginCtx = null;
loginCtx = new LoginContext( "Server", new LoginCallbackHandler(null,null));
System.out.println("Attempting to do Login...");
loginCtx.login();
Subject ret_sub = loginCtx.getSubject();
return ret_sub;
}
private String acceptSecurityContext( final byte[] serviceTicket)
throws GSSException {
krb5Oid = new Oid( "1.2.840.113554.1.2.2");
return Subject.doAs( subject, new PrivilegedAction<String>() {
public String run() {
try {
GSSManager manager = GSSManager.getInstance();
GSSContext context = manager.createContext( (GSSCredential) null);
context.acceptSecContext( serviceTicket, 0, serviceTicket.length);
return context.getSrcName().toString();
}
catch ( Exception e) {
e.printStackTrace();
return null;
}
}
});
}
これが私のserver.propertiesです
realm=MYREALM
kdc=192.168.1.1
および jaas.conf ファイル
Client {
com.sun.security.auth.module.Krb5LoginModule required
useTicketCache=false
useKeyTab=false
storeKey=false
isInitiator=true
debug=true
;
};
Server {
com.sun.security.auth.module.Krb5LoginModule required
useKeyTab=true
storeKey=true
doNotPrompt=true
isInitiator=false
keyTab="/etc/krb5.keytab"
principal="MYSPN/host.domain.com@MYREALM"
debug=true
;
};
サービス アカウントにパスワードを指定するとサーバーが認証できるため、サービス チケットは有効であると確信していますが、パスワードの代わりにキータブ ファイルを使用したいと考えています。