jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java
changeset 25859 3317bb8137f4
parent 23010 6dadb192ad81
child 25995 6267b0694e45
equal deleted inserted replaced
25858:836adbf7a2cd 25859:3317bb8137f4
       
     1 /*
       
     2  * Copyright (c) 2000, 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.  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  *
       
    30  *  Copyright 1997 The Open Group Research Institute.  All rights reserved.
       
    31  * ===========================================================================
       
    32  *
       
    33  */
       
    34 package sun.security.krb5.internal.ccache;
       
    35 
       
    36 import sun.security.krb5.*;
       
    37 import sun.security.krb5.internal.*;
       
    38 import java.util.StringTokenizer;
       
    39 import java.util.Vector;
       
    40 import java.io.IOException;
       
    41 import java.io.File;
       
    42 import java.io.FileInputStream;
       
    43 import java.io.FileOutputStream;
       
    44 import java.io.BufferedReader;
       
    45 import java.io.InputStreamReader;
       
    46 import java.lang.reflect.*;
       
    47 
       
    48 /**
       
    49  * CredentialsCache stores credentials(tickets, session keys, etc) in a
       
    50  * semi-permanent store
       
    51  * for later use by different program.
       
    52  *
       
    53  * @author Yanni Zhang
       
    54  * @author Ram Marti
       
    55  */
       
    56 
       
    57 public class FileCredentialsCache extends CredentialsCache
       
    58     implements FileCCacheConstants {
       
    59     public int version;
       
    60     public Tag tag; // optional
       
    61     public PrincipalName primaryPrincipal;
       
    62     private Vector<Credentials> credentialsList;
       
    63     private static String dir;
       
    64     private static boolean DEBUG = Krb5.DEBUG;
       
    65 
       
    66     public static synchronized FileCredentialsCache acquireInstance(
       
    67                 PrincipalName principal, String cache) {
       
    68         try {
       
    69             FileCredentialsCache fcc = new FileCredentialsCache();
       
    70             if (cache == null) {
       
    71                 cacheName = FileCredentialsCache.getDefaultCacheName();
       
    72             } else {
       
    73                 cacheName = FileCredentialsCache.checkValidation(cache);
       
    74             }
       
    75             if ((cacheName == null) || !(new File(cacheName)).exists()) {
       
    76                 // invalid cache name or the file doesn't exist
       
    77                 return null;
       
    78             }
       
    79             if (principal != null) {
       
    80                 fcc.primaryPrincipal = principal;
       
    81             }
       
    82             fcc.load(cacheName);
       
    83             return fcc;
       
    84         } catch (IOException e) {
       
    85             // we don't handle it now, instead we return a null at the end.
       
    86             if (DEBUG) {
       
    87                 e.printStackTrace();
       
    88             }
       
    89         } catch (KrbException e) {
       
    90             // we don't handle it now, instead we return a null at the end.
       
    91             if (DEBUG) {
       
    92                 e.printStackTrace();
       
    93             }
       
    94         }
       
    95         return null;
       
    96     }
       
    97 
       
    98     public static FileCredentialsCache acquireInstance() {
       
    99         return acquireInstance(null, null);
       
   100     }
       
   101 
       
   102     static synchronized FileCredentialsCache New(PrincipalName principal,
       
   103                                                 String name) {
       
   104         try {
       
   105             FileCredentialsCache fcc = new FileCredentialsCache();
       
   106             cacheName = FileCredentialsCache.checkValidation(name);
       
   107             if (cacheName == null) {
       
   108                 // invalid cache name or the file doesn't exist
       
   109                 return null;
       
   110             }
       
   111             fcc.init(principal, cacheName);
       
   112             return fcc;
       
   113         }
       
   114         catch (IOException e) {
       
   115         }
       
   116         catch (KrbException e) {
       
   117         }
       
   118         return null;
       
   119     }
       
   120 
       
   121     static synchronized FileCredentialsCache New(PrincipalName principal) {
       
   122         try {
       
   123             FileCredentialsCache fcc = new FileCredentialsCache();
       
   124             cacheName = FileCredentialsCache.getDefaultCacheName();
       
   125             fcc.init(principal, cacheName);
       
   126             return fcc;
       
   127         }
       
   128         catch (IOException e) {
       
   129             if (DEBUG) {
       
   130                 e.printStackTrace();
       
   131             }
       
   132         } catch (KrbException e) {
       
   133             if (DEBUG) {
       
   134                 e.printStackTrace();
       
   135             }
       
   136 
       
   137         }
       
   138         return null;
       
   139     }
       
   140 
       
   141     private FileCredentialsCache() {
       
   142     }
       
   143 
       
   144     boolean exists(String cache) {
       
   145         File file = new File(cache);
       
   146         if (file.exists()) {
       
   147             return true;
       
   148         } else return false;
       
   149     }
       
   150 
       
   151     synchronized void init(PrincipalName principal, String name)
       
   152         throws IOException, KrbException {
       
   153         primaryPrincipal = principal;
       
   154         CCacheOutputStream cos =
       
   155             new CCacheOutputStream(new FileOutputStream(name));
       
   156         version = KRB5_FCC_FVNO_3;
       
   157         cos.writeHeader(primaryPrincipal, version);
       
   158         cos.close();
       
   159         load(name);
       
   160     }
       
   161 
       
   162     synchronized void load(String name) throws IOException, KrbException {
       
   163         PrincipalName p;
       
   164         CCacheInputStream cis =
       
   165             new CCacheInputStream(new FileInputStream(name));
       
   166         version = cis.readVersion();
       
   167         if (version == KRB5_FCC_FVNO_4) {
       
   168             tag = cis.readTag();
       
   169         } else {
       
   170             tag = null;
       
   171             if (version == KRB5_FCC_FVNO_1 || version == KRB5_FCC_FVNO_2) {
       
   172                 cis.setNativeByteOrder();
       
   173             }
       
   174         }
       
   175         p = cis.readPrincipal(version);
       
   176 
       
   177         if (primaryPrincipal != null) {
       
   178             if (!(primaryPrincipal.match(p))) {
       
   179                 throw new IOException("Primary principals don't match.");
       
   180             }
       
   181         } else
       
   182             primaryPrincipal = p;
       
   183         credentialsList = new Vector<Credentials> ();
       
   184         while (cis.available() > 0) {
       
   185             Credentials cred = cis.readCred(version);
       
   186             if (cred != null) {
       
   187                 credentialsList.addElement(cred);
       
   188             }
       
   189         }
       
   190         cis.close();
       
   191     }
       
   192 
       
   193 
       
   194     /**
       
   195      * Updates the credentials list. If the specified credentials for the
       
   196      * service is new, add it to the list. If there is an entry in the list,
       
   197      * replace the old credentials with the new one.
       
   198      * @param c the credentials.
       
   199      */
       
   200 
       
   201     public synchronized void update(Credentials c) {
       
   202         if (credentialsList != null) {
       
   203             if (credentialsList.isEmpty()) {
       
   204                 credentialsList.addElement(c);
       
   205             } else {
       
   206                 Credentials tmp = null;
       
   207                 boolean matched = false;
       
   208 
       
   209                 for (int i = 0; i < credentialsList.size(); i++) {
       
   210                     tmp = credentialsList.elementAt(i);
       
   211                     if (match(c.sname.getNameStrings(),
       
   212                               tmp.sname.getNameStrings()) &&
       
   213                         ((c.sname.getRealmString()).equalsIgnoreCase(
       
   214                                      tmp.sname.getRealmString()))) {
       
   215                         matched = true;
       
   216                         if (c.endtime.getTime() >= tmp.endtime.getTime()) {
       
   217                             if (DEBUG) {
       
   218                                 System.out.println(" >>> FileCredentialsCache "
       
   219                                          +  "Ticket matched, overwrite "
       
   220                                          +  "the old one.");
       
   221                             }
       
   222                             credentialsList.removeElementAt(i);
       
   223                             credentialsList.addElement(c);
       
   224                         }
       
   225                     }
       
   226                 }
       
   227                 if (matched == false) {
       
   228                     if (DEBUG) {
       
   229                         System.out.println(" >>> FileCredentialsCache Ticket "
       
   230                                         +   "not exactly matched, "
       
   231                                         +   "add new one into cache.");
       
   232                     }
       
   233 
       
   234                     credentialsList.addElement(c);
       
   235                 }
       
   236             }
       
   237         }
       
   238     }
       
   239 
       
   240     public synchronized PrincipalName getPrimaryPrincipal() {
       
   241         return primaryPrincipal;
       
   242     }
       
   243 
       
   244 
       
   245     /**
       
   246      * Saves the credentials cache file to the disk.
       
   247      */
       
   248     public synchronized void save() throws IOException, Asn1Exception {
       
   249         CCacheOutputStream cos
       
   250             = new CCacheOutputStream(new FileOutputStream(cacheName));
       
   251         cos.writeHeader(primaryPrincipal, version);
       
   252         Credentials[] tmp = null;
       
   253         if ((tmp = getCredsList()) != null) {
       
   254             for (int i = 0; i < tmp.length; i++) {
       
   255                 cos.addCreds(tmp[i]);
       
   256             }
       
   257         }
       
   258         cos.close();
       
   259     }
       
   260 
       
   261     boolean match(String[] s1, String[] s2) {
       
   262         if (s1.length != s2.length) {
       
   263             return false;
       
   264         } else {
       
   265             for (int i = 0; i < s1.length; i++) {
       
   266                 if (!(s1[i].equalsIgnoreCase(s2[i]))) {
       
   267                     return false;
       
   268                 }
       
   269             }
       
   270         }
       
   271         return true;
       
   272     }
       
   273 
       
   274     /**
       
   275      * Returns the list of credentials entries in the cache file.
       
   276      */
       
   277     public synchronized Credentials[] getCredsList() {
       
   278         if ((credentialsList == null) || (credentialsList.isEmpty())) {
       
   279             return null;
       
   280         } else {
       
   281             Credentials[] tmp = new Credentials[credentialsList.size()];
       
   282             for (int i = 0; i < credentialsList.size(); i++) {
       
   283                 tmp[i] = credentialsList.elementAt(i);
       
   284             }
       
   285             return tmp;
       
   286         }
       
   287 
       
   288     }
       
   289 
       
   290     public Credentials getCreds(LoginOptions options, PrincipalName sname) {
       
   291         if (options == null) {
       
   292             return getCreds(sname);
       
   293         } else {
       
   294             Credentials[] list = getCredsList();
       
   295             if (list == null) {
       
   296                 return null;
       
   297             } else {
       
   298                 for (int i = 0; i < list.length; i++) {
       
   299                     if (sname.match(list[i].sname)) {
       
   300                         if (list[i].flags.match(options)) {
       
   301                             return list[i];
       
   302                         }
       
   303                     }
       
   304                 }
       
   305             }
       
   306             return null;
       
   307         }
       
   308     }
       
   309 
       
   310 
       
   311     /**
       
   312      * Gets a credentials for a specified service.
       
   313      * @param sname service principal name.
       
   314      */
       
   315     public Credentials getCreds(PrincipalName sname) {
       
   316         Credentials[] list = getCredsList();
       
   317         if (list == null) {
       
   318             return null;
       
   319         } else {
       
   320             for (int i = 0; i < list.length; i++) {
       
   321                 if (sname.match(list[i].sname)) {
       
   322                     return list[i];
       
   323                 }
       
   324             }
       
   325         }
       
   326         return null;
       
   327     }
       
   328 
       
   329     public Credentials getDefaultCreds() {
       
   330         Credentials[] list = getCredsList();
       
   331         if (list == null) {
       
   332             return null;
       
   333         } else {
       
   334             for (int i = list.length-1; i >= 0; i--) {
       
   335                 if (list[i].sname.toString().startsWith("krbtgt")) {
       
   336                     String[] nameStrings = list[i].sname.getNameStrings();
       
   337                     // find the TGT for the current realm krbtgt/realm@realm
       
   338                     if (nameStrings[1].equals(list[i].sname.getRealm().toString())) {
       
   339                        return list[i];
       
   340                     }
       
   341                 }
       
   342             }
       
   343         }
       
   344         return null;
       
   345     }
       
   346 
       
   347     /*
       
   348      * Returns path name of the credentials cache file.
       
   349      * The path name is searched in the following order:
       
   350      *
       
   351      * 1. KRB5CCNAME (bare file name without FILE:)
       
   352      * 2. /tmp/krb5cc_<uid> on unix systems
       
   353      * 3. <user.home>/krb5cc_<user.name>
       
   354      * 4. <user.home>/krb5cc (if can't get <user.name>)
       
   355      */
       
   356 
       
   357     public static String getDefaultCacheName() {
       
   358 
       
   359         String stdCacheNameComponent = "krb5cc";
       
   360         String name;
       
   361 
       
   362         // The env var can start with TYPE:, we only support FILE: here.
       
   363         // http://docs.oracle.com/cd/E19082-01/819-2252/6n4i8rtr3/index.html
       
   364         name = java.security.AccessController.doPrivileged(
       
   365                 new java.security.PrivilegedAction<String>() {
       
   366             @Override
       
   367             public String run() {
       
   368                 String cache = System.getenv("KRB5CCNAME");
       
   369                 if (cache != null &&
       
   370                         (cache.length() >= 5) &&
       
   371                         cache.regionMatches(true, 0, "FILE:", 0, 5)) {
       
   372                     cache = cache.substring(5);
       
   373                 }
       
   374                 return cache;
       
   375             }
       
   376         });
       
   377         if (name != null) {
       
   378             if (DEBUG) {
       
   379                 System.out.println(">>>KinitOptions cache name is " + name);
       
   380             }
       
   381             return name;
       
   382         }
       
   383 
       
   384         // get cache name from system.property
       
   385         String osname =
       
   386             java.security.AccessController.doPrivileged(
       
   387                         new sun.security.action.GetPropertyAction("os.name"));
       
   388 
       
   389         /*
       
   390          * For Unix platforms we use the default cache name to be
       
   391          * /tmp/krbcc_uid ; for all other platforms  we use
       
   392          * {user_home}/krb5_cc{user_name}
       
   393          * Please note that for Windows 2K we will use LSA to get
       
   394          * the TGT from the the default cache even before we come here;
       
   395          * however when we create cache we will create a cache under
       
   396          * {user_home}/krb5_cc{user_name} for non-Unix platforms including
       
   397          * Windows 2K.
       
   398          */
       
   399 
       
   400         if (osname != null) {
       
   401             String cmd = null;
       
   402             String uidStr = null;
       
   403             long uid = 0;
       
   404 
       
   405             if (osname.startsWith("SunOS") ||
       
   406                 (osname.startsWith("Linux"))) {
       
   407                 try {
       
   408                     Class<?> c = Class.forName
       
   409                         ("com.sun.security.auth.module.UnixSystem");
       
   410                     Constructor<?> constructor = c.getConstructor();
       
   411                     Object obj = constructor.newInstance();
       
   412                     Method method = c.getMethod("getUid");
       
   413                     uid =  ((Long)method.invoke(obj)).longValue();
       
   414                     name = File.separator + "tmp" +
       
   415                         File.separator + stdCacheNameComponent + "_" + uid;
       
   416                     if (DEBUG) {
       
   417                         System.out.println(">>>KinitOptions cache name is " +
       
   418                                            name);
       
   419                     }
       
   420                     return name;
       
   421                 } catch (Exception e) {
       
   422                     if (DEBUG) {
       
   423                         System.out.println("Exception in obtaining uid " +
       
   424                                             "for Unix platforms " +
       
   425                                             "Using user's home directory");
       
   426 
       
   427 
       
   428                         e.printStackTrace();
       
   429                     }
       
   430                 }
       
   431             }
       
   432         }
       
   433 
       
   434         // we did not get the uid;
       
   435 
       
   436 
       
   437         String user_name =
       
   438             java.security.AccessController.doPrivileged(
       
   439                         new sun.security.action.GetPropertyAction("user.name"));
       
   440 
       
   441         String user_home =
       
   442             java.security.AccessController.doPrivileged(
       
   443                         new sun.security.action.GetPropertyAction("user.home"));
       
   444 
       
   445         if (user_home == null) {
       
   446             user_home =
       
   447                 java.security.AccessController.doPrivileged(
       
   448                         new sun.security.action.GetPropertyAction("user.dir"));
       
   449         }
       
   450 
       
   451         if (user_name != null) {
       
   452             name = user_home + File.separator  +
       
   453                 stdCacheNameComponent + "_" + user_name;
       
   454         } else {
       
   455             name = user_home + File.separator + stdCacheNameComponent;
       
   456         }
       
   457 
       
   458         if (DEBUG) {
       
   459             System.out.println(">>>KinitOptions cache name is " + name);
       
   460         }
       
   461 
       
   462         return name;
       
   463     }
       
   464 
       
   465     public static String checkValidation(String name) {
       
   466         String fullname = null;
       
   467         if (name == null) {
       
   468             return null;
       
   469         }
       
   470         try {
       
   471             // get full path name
       
   472             fullname = (new File(name)).getCanonicalPath();
       
   473             File fCheck = new File(fullname);
       
   474             if (!(fCheck.exists())) {
       
   475                 // get absolute directory
       
   476                 File temp = new File(fCheck.getParent());
       
   477                 // test if the directory exists
       
   478                 if (!(temp.isDirectory()))
       
   479                     fullname = null;
       
   480                 temp = null;
       
   481             }
       
   482             fCheck = null;
       
   483 
       
   484         } catch (IOException e) {
       
   485             fullname = null; // invalid name
       
   486         }
       
   487         return fullname;
       
   488     }
       
   489 
       
   490 
       
   491     private static String exec(String c) {
       
   492         StringTokenizer st = new StringTokenizer(c);
       
   493         Vector<String> v = new Vector<>();
       
   494         while (st.hasMoreTokens()) {
       
   495             v.addElement(st.nextToken());
       
   496         }
       
   497         final String[] command = new String[v.size()];
       
   498         v.copyInto(command);
       
   499         try {
       
   500 
       
   501             Process p =
       
   502                 java.security.AccessController.doPrivileged
       
   503                 (new java.security.PrivilegedAction<Process> () {
       
   504                         public Process run() {
       
   505                             try {
       
   506                                 return (Runtime.getRuntime().exec(command));
       
   507                             } catch (java.io.IOException e) {
       
   508                                 if (DEBUG) {
       
   509                                     e.printStackTrace();
       
   510                                 }
       
   511                                 return null;
       
   512                             }
       
   513                         }
       
   514                     });
       
   515             if (p == null) {
       
   516                 // exception occurred during executing the command
       
   517                 return null;
       
   518             }
       
   519 
       
   520             BufferedReader commandResult =
       
   521                 new BufferedReader
       
   522                     (new InputStreamReader(p.getInputStream(), "8859_1"));
       
   523             String s1 = null;
       
   524             if ((command.length == 1) &&
       
   525                 (command[0].equals("/usr/bin/env"))) {
       
   526                 while ((s1 = commandResult.readLine()) != null) {
       
   527                     if (s1.length() >= 11) {
       
   528                         if ((s1.substring(0, 11)).equalsIgnoreCase
       
   529                             ("KRB5CCNAME=")) {
       
   530                             s1 = s1.substring(11);
       
   531                             break;
       
   532                         }
       
   533                     }
       
   534                 }
       
   535             } else     s1 = commandResult.readLine();
       
   536             commandResult.close();
       
   537             return s1;
       
   538         } catch (Exception e) {
       
   539             if (DEBUG) {
       
   540                 e.printStackTrace();
       
   541             }
       
   542         }
       
   543         return null;
       
   544     }
       
   545 }