使用keytab验证kerberos服务令牌

时间:2013-02-06 20:24:55

标签: kerberos

此论坛之前已经提出过类似的问题,但接受的答案对我没有帮助。我的服务器有一个Kerberos keytab文件,我想用它来验证客户端发送的服务票证。

根据Sun的文档和散布在其他地方的示例代码,这就是我目前所拥有的:

  1. 客户从KDC申请MYSPN的服务票据
  2. 客户端将文件发送到服务服务器以请求访问服务。
  3. 服务器在使用已存在的MYSPN的keytab验证服务票证后授予访问权限。
  4. 我无法让#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
         ;
    };
    

    我确定服务票证是有效的,因为如果我为服务帐户提供密码,服务器可以进行身份​​验证,但我想使用密钥表文件而不是密码。

0 个答案:

没有答案