Home » openjdk-7 » sun.security » krb5 » [javadoc | source]

    1   /*
    2    * Copyright (c) 2000, 2010, 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.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   /*
   27    *
   28    *  (C) Copyright IBM Corp. 1999 All Rights Reserved.
   29    *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
   30    */
   31   
   32   package sun.security.krb5;
   33   
   34   import sun.security.krb5.internal;
   35   import sun.security.krb5.internal.ccache.CredentialsCache;
   36   import sun.security.krb5.internal.crypto.EType;
   37   import java.io.IOException;
   38   import java.util.Date;
   39   import java.util.Locale;
   40   import java.net.InetAddress;
   41   
   42   /**
   43    * This class encapsulates the concept of a Kerberos service
   44    * credential. That includes a Kerberos ticket and an associated
   45    * session key.
   46    */
   47   public class Credentials {
   48   
   49       Ticket ticket;
   50       PrincipalName client;
   51       PrincipalName server;
   52       EncryptionKey key;
   53       TicketFlags flags;
   54       KerberosTime authTime;
   55       KerberosTime startTime;
   56       KerberosTime endTime;
   57       KerberosTime renewTill;
   58       HostAddresses cAddr;
   59       EncryptionKey serviceKey;
   60       AuthorizationData authzData;
   61       private static boolean DEBUG = Krb5.DEBUG;
   62       private static CredentialsCache cache;
   63       static boolean alreadyLoaded = false;
   64       private static boolean alreadyTried = false;
   65       private static native Credentials acquireDefaultNativeCreds();
   66   
   67       public Credentials(Ticket new_ticket,
   68                          PrincipalName new_client,
   69                          PrincipalName new_server,
   70                          EncryptionKey new_key,
   71                          TicketFlags new_flags,
   72                          KerberosTime authTime,
   73                          KerberosTime new_startTime,
   74                          KerberosTime new_endTime,
   75                          KerberosTime renewTill,
   76                          HostAddresses cAddr,
   77                          AuthorizationData authzData) {
   78           this(new_ticket, new_client, new_server, new_key, new_flags,
   79                   authTime, new_startTime, new_endTime, renewTill, cAddr);
   80           this.authzData = authzData;
   81       }
   82   
   83       public Credentials(Ticket new_ticket,
   84                          PrincipalName new_client,
   85                          PrincipalName new_server,
   86                          EncryptionKey new_key,
   87                          TicketFlags new_flags,
   88                          KerberosTime authTime,
   89                          KerberosTime new_startTime,
   90                          KerberosTime new_endTime,
   91                          KerberosTime renewTill,
   92                          HostAddresses cAddr) {
   93           ticket = new_ticket;
   94           client = new_client;
   95           server = new_server;
   96           key = new_key;
   97           flags = new_flags;
   98           this.authTime = authTime;
   99           startTime = new_startTime;
  100           endTime = new_endTime;
  101           this.renewTill = renewTill;
  102           this.cAddr = cAddr;
  103       }
  104   
  105       public Credentials(byte[] encoding,
  106                          String client,
  107                          String server,
  108                          byte[] keyBytes,
  109                          int keyType,
  110                          boolean[] flags,
  111                          Date authTime,
  112                          Date startTime,
  113                          Date endTime,
  114                          Date renewTill,
  115                          InetAddress[] cAddrs) throws KrbException, IOException {
  116           this(new Ticket(encoding),
  117                new PrincipalName(client, PrincipalName.KRB_NT_PRINCIPAL),
  118                new PrincipalName(server, PrincipalName.KRB_NT_SRV_INST),
  119                new EncryptionKey(keyType, keyBytes),
  120                (flags == null? null: new TicketFlags(flags)),
  121                (authTime == null? null: new KerberosTime(authTime)),
  122                (startTime == null? null: new KerberosTime(startTime)),
  123                (endTime == null? null: new KerberosTime(endTime)),
  124                (renewTill == null? null: new KerberosTime(renewTill)),
  125                null); // caddrs are in the encoding at this point
  126       }
  127   
  128       /**
  129        * Acquires a service ticket for the specified service
  130        * principal. If the service ticket is not already available, it
  131        * obtains a new one from the KDC.
  132        */
  133       /*
  134       public Credentials(Credentials tgt, PrincipalName service)
  135           throws KrbException {
  136       }
  137       */
  138   
  139       public final PrincipalName getClient() {
  140           return client;
  141       }
  142   
  143       public final PrincipalName getServer() {
  144           return server;
  145       }
  146   
  147       public final EncryptionKey getSessionKey() {
  148           return key;
  149       }
  150   
  151       public final Date getAuthTime() {
  152           if (authTime != null) {
  153               return authTime.toDate();
  154           } else {
  155               return null;
  156           }
  157       }
  158   
  159       public final Date getStartTime() {
  160           if (startTime != null)
  161               {
  162                   return startTime.toDate();
  163               }
  164           return null;
  165       }
  166   
  167       public final Date getEndTime() {
  168           if (endTime != null)
  169               {
  170                   return endTime.toDate();
  171               }
  172           return null;
  173       }
  174   
  175       public final Date getRenewTill() {
  176           if (renewTill != null)
  177               {
  178                   return renewTill.toDate();
  179               }
  180           return null;
  181       }
  182   
  183       public final boolean[] getFlags() {
  184           if (flags == null) // Can be in a KRB-CRED
  185           return null;
  186           return flags.toBooleanArray();
  187       }
  188   
  189       public final InetAddress[] getClientAddresses() {
  190   
  191           if (cAddr == null)
  192           return null;
  193   
  194           return cAddr.getInetAddresses();
  195       }
  196   
  197       public final byte[] getEncoded() {
  198           byte[] retVal = null;
  199           try {
  200               retVal = ticket.asn1Encode();
  201           } catch (Asn1Exception e) {
  202               if (DEBUG)
  203               System.out.println(e);
  204           } catch (IOException ioe) {
  205               if (DEBUG)
  206               System.out.println(ioe);
  207           }
  208           return retVal;
  209       }
  210   
  211       public boolean isForwardable() {
  212           return flags.get(Krb5.TKT_OPTS_FORWARDABLE);
  213       }
  214   
  215       public boolean isRenewable() {
  216           return flags.get(Krb5.TKT_OPTS_RENEWABLE);
  217       }
  218   
  219       public Ticket getTicket() {
  220           return ticket;
  221       }
  222   
  223       public TicketFlags getTicketFlags() {
  224           return flags;
  225       }
  226   
  227       public AuthorizationData getAuthzData() {
  228           return authzData;
  229       }
  230       /**
  231        * Checks if the service ticket returned by the KDC has the OK-AS-DELEGATE
  232        * flag set
  233        * @return true if OK-AS_DELEGATE flag is set, otherwise, return false.
  234        */
  235       public boolean checkDelegate() {
  236           return flags.get(Krb5.TKT_OPTS_DELEGATE);
  237       }
  238   
  239       /**
  240        * Reset TKT_OPTS_DELEGATE to false, called at credentials acquirement
  241        * when one of the cross-realm TGTs does not have the OK-AS-DELEGATE
  242        * flag set. This info must be preservable and restorable through
  243        * the Krb5Util.credsToTicket/ticketToCreds() methods so that even if
  244        * the service ticket is cached it still remembers the cross-realm
  245        * authentication result.
  246        */
  247       public void resetDelegate() {
  248           flags.set(Krb5.TKT_OPTS_DELEGATE, false);
  249       }
  250   
  251       public Credentials renew() throws KrbException, IOException {
  252           KDCOptions options = new KDCOptions();
  253           options.set(KDCOptions.RENEW, true);
  254           /*
  255            * Added here to pass KrbKdcRep.check:73
  256            */
  257           options.set(KDCOptions.RENEWABLE, true);
  258   
  259           return new KrbTgsReq(options,
  260                                this,
  261                                server,
  262                                null, // from
  263                                null, // till
  264                                null, // rtime
  265                                null, // eTypes
  266                                cAddr,
  267                                null,
  268                                null,
  269                                null).sendAndGetCreds();
  270       }
  271   
  272       /**
  273        * Returns a TGT for the given client principal from a ticket cache.
  274        *
  275        * @param princ the client principal. A value of null means that the
  276        * default principal name in the credentials cache will be used.
  277        * @param ticketCache the path to the tickets file. A value
  278        * of null will be accepted to indicate that the default
  279        * path should be searched
  280        * @returns the TGT credentials or null if none were found. If the tgt
  281        * expired, it is the responsibility of the caller to determine this.
  282        */
  283       public static Credentials acquireTGTFromCache(PrincipalName princ,
  284                                                     String ticketCache)
  285           throws KrbException, IOException {
  286   
  287           if (ticketCache == null) {
  288               // The default ticket cache on Windows is not a file.
  289               String os = java.security.AccessController.doPrivileged(
  290                           new sun.security.action.GetPropertyAction("os.name"));
  291               if (os.toUpperCase(Locale.ENGLISH).startsWith("WINDOWS")) {
  292                   Credentials creds = acquireDefaultCreds();
  293                   if (creds == null) {
  294                       if (DEBUG) {
  295                           System.out.println(">>> Found no TGT's in LSA");
  296                       }
  297                       return null;
  298                   }
  299                   if (princ != null) {
  300                       if (creds.getClient().equals(princ)) {
  301                           if (DEBUG) {
  302                               System.out.println(">>> Obtained TGT from LSA: "
  303                                                  + creds);
  304                           }
  305                           return creds;
  306                       } else {
  307                           if (DEBUG) {
  308                               System.out.println(">>> LSA contains TGT for "
  309                                                  + creds.getClient()
  310                                                  + " not "
  311                                                  + princ);
  312                           }
  313                           return null;
  314                       }
  315                   } else {
  316                       if (DEBUG) {
  317                           System.out.println(">>> Obtained TGT from LSA: "
  318                                              + creds);
  319                       }
  320                       return creds;
  321                   }
  322               }
  323           }
  324   
  325           /*
  326            * Returns the appropriate cache. If ticketCache is null, it is the
  327            * default cache otherwise it is the cache filename contained in it.
  328            */
  329           CredentialsCache ccache =
  330               CredentialsCache.getInstance(princ, ticketCache);
  331   
  332           if (ccache == null)
  333               return null;
  334   
  335           sun.security.krb5.internal.ccache.Credentials tgtCred  =
  336               ccache.getDefaultCreds();
  337   
  338           if (EType.isSupported(tgtCred.getEType())) {
  339               return tgtCred.setKrbCreds();
  340           } else {
  341               if (DEBUG) {
  342                   System.out.println(
  343                       ">>> unsupported key type found the default TGT: " +
  344                       tgtCred.getEType());
  345               }
  346               return null;
  347           }
  348       }
  349   
  350       /**
  351        * Acquires default credentials.
  352        * <br>The possible locations for default credentials cache is searched in
  353        * the following order:
  354        * <ol>
  355        * <li> The directory and cache file name specified by "KRB5CCNAME" system.
  356        * property.
  357        * <li> The directory and cache file name specified by "KRB5CCNAME"
  358        * environment variable.
  359        * <li> A cache file named krb5cc_{user.name} at {user.home} directory.
  360        * </ol>
  361        * @return a <code>KrbCreds</code> object if the credential is found,
  362        * otherwise return null.
  363        */
  364   
  365       // this method is intentionally changed to not check if the caller's
  366       // principal name matches cache file's principal name.
  367       // It assumes that the GSS call has
  368       // the privilege to access the default cache file.
  369   
  370       public static synchronized Credentials acquireDefaultCreds() {
  371           Credentials result = null;
  372   
  373           if (cache == null) {
  374               cache = CredentialsCache.getInstance();
  375           }
  376           if (cache != null) {
  377               if (DEBUG) {
  378                   System.out.println(">>> KrbCreds found the default ticket " +
  379                                      "granting ticket in credential cache.");
  380               }
  381               sun.security.krb5.internal.ccache.Credentials temp =
  382                   cache.getDefaultCreds();
  383               if (EType.isSupported(temp.getEType())) {
  384                   result = temp.setKrbCreds();
  385               } else {
  386                   if (DEBUG) {
  387                       System.out.println(
  388                           ">>> unsupported key type found the default TGT: " +
  389                           temp.getEType());
  390                   }
  391               }
  392           }
  393           if (result == null) {
  394               // Doesn't seem to be a default cache on this system or
  395               // TGT has unsupported encryption type
  396   
  397               if (!alreadyTried) {
  398                   // See if there's any native code to load
  399                   try {
  400                       ensureLoaded();
  401                   } catch (Exception e) {
  402                       if (DEBUG) {
  403                           System.out.println("Can not load credentials cache");
  404                           e.printStackTrace();
  405                       }
  406                       alreadyTried = true;
  407                   }
  408               }
  409               if (alreadyLoaded) {
  410                   // There is some native code
  411                   if (DEBUG)
  412                      System.out.println(">> Acquire default native Credentials");
  413                   result = acquireDefaultNativeCreds();
  414                   // only TGT with DES key will be returned by native method
  415               }
  416           }
  417           return result;
  418       }
  419   
  420       /**
  421        * Acquires credentials for a specified service using initial credential.
  422        * When the service has a different realm
  423        * from the initial credential, we do cross-realm authentication
  424        * - first, we use the current credential to get
  425        * a cross-realm credential from the local KDC, then use that
  426        * cross-realm credential to request service credential
  427        * from the foreigh KDC.
  428        *
  429        * @param service the name of service principal using format
  430        * components@realm
  431        * @param ccreds client's initial credential.
  432        * @exception IOException if an error occurs in reading the credentials
  433        * cache
  434        * @exception KrbException if an error occurs specific to Kerberos
  435        * @return a <code>Credentials</code> object.
  436        */
  437   
  438       public static Credentials acquireServiceCreds(String service,
  439                                                     Credentials ccreds)
  440           throws KrbException, IOException {
  441           return CredentialsUtil.acquireServiceCreds(service, ccreds);
  442       }
  443   
  444       public CredentialsCache getCache() {
  445           return cache;
  446       }
  447   
  448       public EncryptionKey getServiceKey() {
  449           return serviceKey;
  450       }
  451   
  452       /*
  453        * Prints out debug info.
  454        */
  455       public static void printDebug(Credentials c) {
  456           System.out.println(">>> DEBUG: ----Credentials----");
  457           System.out.println("\tclient: " + c.client.toString());
  458           System.out.println("\tserver: " + c.server.toString());
  459           System.out.println("\tticket: realm: " + c.ticket.realm.toString());
  460           System.out.println("\t        sname: " + c.ticket.sname.toString());
  461           if (c.startTime != null) {
  462               System.out.println("\tstartTime: " + c.startTime.getTime());
  463           }
  464           System.out.println("\tendTime: " + c.endTime.getTime());
  465           System.out.println("        ----Credentials end----");
  466       }
  467   
  468   
  469       static void ensureLoaded() {
  470           java.security.AccessController.doPrivileged(
  471                   new java.security.PrivilegedAction<Void> () {
  472                           public Void run() {
  473                                   System.loadLibrary("w2k_lsa_auth");
  474                                   return null;
  475                           }
  476                   });
  477           alreadyLoaded = true;
  478       }
  479   
  480       public String toString() {
  481           StringBuffer buffer = new StringBuffer("Credentials:");
  482           buffer.append("\nclient=").append(client);
  483           buffer.append("\nserver=").append(server);
  484           if (authTime != null) {
  485               buffer.append("\nauthTime=").append(authTime);
  486           }
  487           if (startTime != null) {
  488               buffer.append("\nstartTime=").append(startTime);
  489           }
  490           buffer.append("\nendTime=").append(endTime);
  491           buffer.append("\nrenewTill=").append(renewTill);
  492           buffer.append("\nflags: ").append(flags);
  493           buffer.append("\nEType (int): ").append(key.getEType());
  494           return buffer.toString();
  495       }
  496   
  497   }

Home » openjdk-7 » sun.security » krb5 » [javadoc | source]