1 /*
   2  * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 /*
  24  * @test
  25  * @bug 8005447
  26  * @modules java.security.jgss/sun.security.jgss
  27  * @compile -XDignore.symbol.file ServiceCredsCombination.java
  28  * @run main ServiceCredsCombination
  29  * @summary default principal can act as anyone
  30  */
  31 
  32 import java.security.PrivilegedActionException;
  33 import java.security.PrivilegedExceptionAction;
  34 import java.util.Objects;
  35 import javax.security.auth.Subject;
  36 import javax.security.auth.kerberos.KerberosKey;
  37 import javax.security.auth.kerberos.KerberosPrincipal;
  38 import javax.security.auth.kerberos.KeyTab;
  39 import org.ietf.jgss.GSSCredential;
  40 import org.ietf.jgss.GSSException;
  41 import org.ietf.jgss.GSSManager;
  42 import org.ietf.jgss.GSSName;
  43 import sun.security.jgss.GSSUtil;
  44 
  45 public class ServiceCredsCombination {
  46 
  47     public static void main(String[] args) throws Exception {
  48         // pass
  49         check("a", "a", princ("a"), key("a"));
  50         check(null, "a", princ("a"), key("a"));
  51         check("x", "NOCRED", princ("a"), key("a"));
  52         // two pass
  53         check("a", "a", princ("a"), key("a"), princ("b"), key("b"));
  54         check("b", "b", princ("a"), key("a"), princ("b"), key("b"));
  55         check(null, null, princ("a"), key("a"), princ("b"), key("b"));
  56         check("x", "NOCRED", princ("a"), key("a"), princ("b"), key("b"));
  57         // old ktab
  58         check("b", "b", princ("b"), oldktab());
  59         check("x", "NOCRED", princ("b"), oldktab());
  60         check(null, "b", princ("b"), oldktab());
  61         // Two old ktab
  62         check("a", "a", princ("a"), princ("b"), oldktab(), oldktab());
  63         check("b", "b", princ("a"), princ("b"), oldktab(), oldktab());
  64         check(null, null, princ("a"), princ("b"), oldktab(), oldktab());
  65         check("x", "NOCRED", princ("a"), princ("b"), oldktab(), oldktab());
  66         // bound ktab
  67         check("c", "c", princ("c"), ktab("c"));
  68         check(null, "c", princ("c"), ktab("c"));
  69         // unbound ktab
  70         check("x", "x", ktab());
  71         check(null, null, ktab());
  72         // Two bound ktab
  73         check("c1", "c1", princ("c1"), princ("c2"), ktab("c1"), ktab("c2"));
  74         check("c2", "c2", princ("c1"), princ("c2"), ktab("c1"), ktab("c2"));
  75         check("x", "NOCRED", princ("c1"), princ("c2"), ktab("c1"), ktab("c2"));
  76         check(null, null, princ("c1"), princ("c2"), ktab("c1"), ktab("c2"));
  77         // One bound, one unbound
  78         check("c1", "c1", princ("c1"), ktab("c1"), ktab());
  79         check("x", "x", princ("c1"), ktab("c1"), ktab());
  80         check(null, null, princ("c1"), ktab("c1"), ktab());
  81         // Two unbound ktab
  82         check("x", "x", ktab(), ktab());
  83         check(null, null, ktab(), ktab());
  84         // pass + old ktab
  85         check("a", "a", princ("a"), princ("b"), key("a"), oldktab());
  86         check("b", "b", princ("a"), princ("b"), key("a"), oldktab());
  87         check(null, null, princ("a"), princ("b"), key("a"), oldktab());
  88         check("x", "NOCRED", princ("a"), princ("b"), key("a"), oldktab());
  89         // pass + bound ktab
  90         check("a", "a", princ("a"), princ("c"), key("a"), ktab("c"));
  91         check("c", "c", princ("a"), princ("c"), key("a"), ktab("c"));
  92         check("x", "NOCRED", princ("a"), princ("c"), key("a"), ktab("c"));
  93         check(null, null, princ("a"), princ("c"), key("a"), ktab("c"));
  94         // pass + unbound ktab
  95         check("a", "a", princ("a"), key("a"), ktab());
  96         check("x", "x", princ("a"), key("a"), ktab());
  97         check(null, null, princ("a"), key("a"), ktab());
  98         // Compatibility, automatically add princ for keys
  99         check(null, "a", key("a"));
 100         check("x", "NOCRED", key("a"));
 101         check(null, "a", key("a"), oldktab());
 102         check("x", "NOCRED", key("a"), oldktab());
 103         // Limitation, "a" has no key, but we don't know oldktab() is for "b"
 104         check("a", "a", princ("a"), princ("b"), oldktab());
 105     }
 106 
 107     /**
 108      * Checks the correct bound
 109      * @param a get a creds for this principal, null for default one
 110      * @param b expected name, null for still unbound, "NOCRED" for no creds
 111      * @param objs princs, keys and keytabs in the subject
 112      */
 113     private static void check(final String a, String b, Object... objs)
 114             throws Exception {
 115         Subject subj = new Subject();
 116         for (Object obj: objs) {
 117             if (obj instanceof KerberosPrincipal) {
 118                 subj.getPrincipals().add((KerberosPrincipal)obj);
 119             } else if (obj instanceof KerberosKey || obj instanceof KeyTab) {
 120                 subj.getPrivateCredentials().add(obj);
 121             }
 122         }
 123         final GSSManager man = GSSManager.getInstance();
 124         try {
 125             String result = Subject.doAs(
 126                     subj, new PrivilegedExceptionAction<String>() {
 127                 @Override
 128                 public String run() throws GSSException {
 129                     GSSCredential cred = man.createCredential(
 130                             a == null ? null : man.createName(r(a), null),
 131                             GSSCredential.INDEFINITE_LIFETIME,
 132                             GSSUtil.GSS_KRB5_MECH_OID,
 133                             GSSCredential.ACCEPT_ONLY);
 134                     GSSName name = cred.getName();
 135                     return name == null ? null : name.toString();
 136                 }
 137             });
 138             if (!Objects.equals(result, r(b))) {
 139                 throw new Exception("Check failed: getInstance(" + a
 140                         + ") has name " + result + ", not " + b);
 141             }
 142         } catch (PrivilegedActionException e) {
 143             if (!"NOCRED".equals(b)) {
 144                 throw new Exception("Check failed: getInstance(" + a
 145                         + ") is null " + ", but not one with name " + b);
 146             }
 147         }
 148     }
 149     private static String r(String s) {
 150         return s == null ? null : (s+"@REALM");
 151     }
 152     private static KerberosPrincipal princ(String s) {
 153         return new KerberosPrincipal(r(s));
 154     }
 155     private static KerberosKey key(String s) {
 156         return new KerberosKey(princ(s), new byte[0], 0, 0);
 157     }
 158     private static KeyTab oldktab() {
 159         return KeyTab.getInstance();
 160     }
 161     static KeyTab ktab(String s) {
 162         return KeyTab.getInstance(princ(s));
 163     }
 164     static KeyTab ktab() {
 165         return KeyTab.getUnboundInstance();
 166     }
 167 }