jdk/src/share/classes/sun/security/krb5/internal/rcache/DflCache.java
author weijun
Thu, 08 May 2014 22:30:31 +0800
changeset 24271 19000122bb5e
parent 18536 092411ced388
child 24506 abb4cc4647ee
permissions -rw-r--r--
8039951: com.sun.security.auth.module missing classes on some platforms Reviewed-by: mullan
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
     1
/*
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
     2
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
     4
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    10
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    15
 * accompanied this code).
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    16
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    20
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    23
 * questions.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    24
 */
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    25
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    26
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    27
package sun.security.krb5.internal.rcache;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    28
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    29
import java.io.*;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    30
import java.nio.BufferUnderflowException;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    31
import java.nio.ByteBuffer;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    32
import java.nio.ByteOrder;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    33
import java.nio.channels.SeekableByteChannel;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    34
import java.nio.file.Files;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    35
import java.nio.file.Path;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    36
import java.nio.file.StandardCopyOption;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    37
import java.nio.file.StandardOpenOption;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    38
import java.nio.file.attribute.PosixFilePermission;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    39
import java.security.AccessController;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    40
import java.util.*;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    41
24271
19000122bb5e 8039951: com.sun.security.auth.module missing classes on some platforms
weijun
parents: 18536
diff changeset
    42
import com.sun.security.auth.module.UnixSystem;
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    43
import sun.security.action.GetPropertyAction;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    44
import sun.security.krb5.internal.KerberosTime;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    45
import sun.security.krb5.internal.Krb5;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    46
import sun.security.krb5.internal.KrbApErrException;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    47
import sun.security.krb5.internal.ReplayCache;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    48
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    49
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    50
/**
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    51
 * A dfl file is used to sustores AuthTime entries when the system property
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    52
 * sun.security.krb5.rcache is set to
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    53
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    54
 *    dfl(|:path/|:path/name|:name)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    55
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    56
 * The file will be path/name. If path is not given, it will be
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    57
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    58
 *    System.getProperty("java.io.tmpdir")
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    59
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    60
 * If name is not given, it will be
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    61
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    62
 *    service_euid
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    63
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    64
 * Java does not have a method to get euid, so uid is used instead. This
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    65
 * should normally to be since a Java program is seldom used as a setuid app.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    66
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    67
 * The file has a header:
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    68
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    69
 *    i16 0x0501 (KRB5_RC_VNO) in network order
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    70
 *    i32 number of seconds for lifespan (in native order, same below)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    71
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    72
 * followed by cache entries concatenated, which can be encoded in
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    73
 * 2 styles:
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    74
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    75
 * The traditional style is:
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    76
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    77
 *    LC of client principal
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    78
 *    LC of server principal
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    79
 *    i32 cusec of Authenticator
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    80
 *    i32 ctime of Authenticator
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    81
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    82
 * The new style has a hash:
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    83
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    84
 *    LC of ""
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    85
 *    LC of "HASH:%s %lu:%s %lu:%s" of (hash, clientlen, client, serverlen,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    86
 *          server) where msghash is 32 char (lower case) text mode md5sum
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    87
 *          of the ciphertext of authenticator.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    88
 *    i32 cusec of Authenticator
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    89
 *    i32 ctime of Authenticator
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    90
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    91
 * where LC of a string means
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    92
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    93
 *    i32 strlen(string) + 1
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    94
 *    octets of string, with the \0x00 ending
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    95
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    96
 * The old style block is always created by MIT krb5 used even if a new style
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    97
 * is available, which means there can be 2 entries for a single Authenticator.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    98
 * Java also does this way.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    99
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   100
 * See src/lib/krb5/rcache/rc_io.c and src/lib/krb5/rcache/rc_dfl.c.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   101
 */
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   102
public class DflCache extends ReplayCache {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   103
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   104
    private static final int KRB5_RV_VNO = 0x501;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   105
    private static final int EXCESSREPS = 30;   // if missed-hit>this, recreate
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   106
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   107
    private final String source;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   108
24271
19000122bb5e 8039951: com.sun.security.auth.module missing classes on some platforms
weijun
parents: 18536
diff changeset
   109
    private static long uid;
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   110
    static {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   111
        try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   112
            // Available on Solaris, Linux and Mac. Otherwise, no _euid suffix
24271
19000122bb5e 8039951: com.sun.security.auth.module missing classes on some platforms
weijun
parents: 18536
diff changeset
   113
            UnixSystem us = new com.sun.security.auth.module.UnixSystem();
19000122bb5e 8039951: com.sun.security.auth.module missing classes on some platforms
weijun
parents: 18536
diff changeset
   114
            uid = us.getUid();
19000122bb5e 8039951: com.sun.security.auth.module missing classes on some platforms
weijun
parents: 18536
diff changeset
   115
        } catch (Throwable e) {
19000122bb5e 8039951: com.sun.security.auth.module missing classes on some platforms
weijun
parents: 18536
diff changeset
   116
            // Cannot be only Exception, might be UnsatisfiedLinkError
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   117
            uid = -1;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   118
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   119
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   120
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   121
    public DflCache (String source) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   122
        this.source = source;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   123
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   124
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   125
    private static String defaultPath() {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   126
        return AccessController.doPrivileged(
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   127
                new GetPropertyAction("java.io.tmpdir"));
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   128
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   129
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   130
    private static String defaultFile(String server) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   131
        // service/host@REALM -> service
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   132
        int slash = server.indexOf('/');
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   133
        if (slash == -1) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   134
            // A normal principal? say, dummy@REALM
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   135
            slash = server.indexOf('@');
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   136
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   137
        if (slash != -1) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   138
            // Should not happen, but be careful
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   139
            server= server.substring(0, slash);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   140
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   141
        if (uid != -1) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   142
            server += "_" + uid;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   143
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   144
        return server;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   145
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   146
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   147
    private static Path getFileName(String source, String server) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   148
        String path, file;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   149
        if (source.equals("dfl")) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   150
            path = defaultPath();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   151
            file = defaultFile(server);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   152
        } else if (source.startsWith("dfl:")) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   153
            source = source.substring(4);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   154
            int pos = source.lastIndexOf('/');
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   155
            int pos1 = source.lastIndexOf('\\');
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   156
            if (pos1 > pos) pos = pos1;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   157
            if (pos == -1) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   158
                // Only file name
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   159
                path = defaultPath();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   160
                file = source;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   161
            } else if (new File(source).isDirectory()) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   162
                // Only path
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   163
                path = source;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   164
                file = defaultFile(server);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   165
            } else {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   166
                // Full pathname
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   167
                path = null;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   168
                file = source;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   169
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   170
        } else {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   171
            throw new IllegalArgumentException();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   172
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   173
        return new File(path, file).toPath();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   174
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   175
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   176
    @Override
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   177
    public void checkAndStore(KerberosTime currTime, AuthTimeWithHash time)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   178
            throws KrbApErrException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   179
        try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   180
            checkAndStore0(currTime, time);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   181
        } catch (IOException ioe) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   182
            KrbApErrException ke = new KrbApErrException(Krb5.KRB_ERR_GENERIC);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   183
            ke.initCause(ioe);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   184
            throw ke;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   185
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   186
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   187
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   188
    private synchronized void checkAndStore0(KerberosTime currTime, AuthTimeWithHash time)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   189
            throws IOException, KrbApErrException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   190
        Path p = getFileName(source, time.server);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   191
        int missed = 0;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   192
        try (Storage s = new Storage()) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   193
            try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   194
                missed = s.loadAndCheck(p, time, currTime);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   195
            } catch (IOException ioe) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   196
                // Non-existing or invalid file
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   197
                Storage.create(p);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   198
                missed = s.loadAndCheck(p, time, currTime);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   199
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   200
            s.append(time);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   201
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   202
        if (missed > EXCESSREPS) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   203
            Storage.expunge(p, currTime);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   204
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   205
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   206
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   207
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   208
    private static class Storage implements Closeable {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   209
        // Static methods
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   210
        @SuppressWarnings("try")
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   211
        private static void create(Path p) throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   212
            try (SeekableByteChannel newChan = createNoClose(p)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   213
                // Do nothing, wait for close
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   214
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   215
            makeMine(p);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   216
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   217
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   218
        private static void makeMine(Path p) throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   219
            // chmod to owner-rw only, otherwise MIT krb5 rejects
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   220
            try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   221
                Set<PosixFilePermission> attrs = new HashSet<>();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   222
                attrs.add(PosixFilePermission.OWNER_READ);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   223
                attrs.add(PosixFilePermission.OWNER_WRITE);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   224
                Files.setPosixFilePermissions(p, attrs);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   225
            } catch (UnsupportedOperationException uoe) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   226
                // No POSIX permission. That's OK.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   227
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   228
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   229
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   230
        private static SeekableByteChannel createNoClose(Path p)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   231
                throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   232
            SeekableByteChannel newChan = Files.newByteChannel(
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   233
                    p, StandardOpenOption.CREATE,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   234
                        StandardOpenOption.TRUNCATE_EXISTING,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   235
                        StandardOpenOption.WRITE);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   236
            ByteBuffer buffer = ByteBuffer.allocate(6);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   237
            buffer.putShort((short)KRB5_RV_VNO);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   238
            buffer.order(ByteOrder.nativeOrder());
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   239
            buffer.putInt(KerberosTime.getDefaultSkew());
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   240
            buffer.flip();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   241
            newChan.write(buffer);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   242
            return newChan;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   243
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   244
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   245
        private static void expunge(Path p, KerberosTime currTime)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   246
                throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   247
            Path p2 = Files.createTempFile(p.getParent(), "rcache", null);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   248
            try (SeekableByteChannel oldChan = Files.newByteChannel(p);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   249
                    SeekableByteChannel newChan = createNoClose(p2)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   250
                long timeLimit = currTime.getSeconds() - readHeader(oldChan);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   251
                while (true) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   252
                    try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   253
                        AuthTime at = AuthTime.readFrom(oldChan);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   254
                        if (at.ctime > timeLimit) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   255
                            ByteBuffer bb = ByteBuffer.wrap(at.encode(true));
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   256
                            newChan.write(bb);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   257
                        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   258
                    } catch (BufferUnderflowException e) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   259
                        break;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   260
                    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   261
                }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   262
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   263
            makeMine(p2);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   264
            Files.move(p2, p,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   265
                    StandardCopyOption.REPLACE_EXISTING,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   266
                    StandardCopyOption.ATOMIC_MOVE);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   267
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   268
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   269
        // Instance methods
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   270
        SeekableByteChannel chan;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   271
        private int loadAndCheck(Path p, AuthTimeWithHash time,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   272
                KerberosTime currTime)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   273
                throws IOException, KrbApErrException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   274
            int missed = 0;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   275
            if (Files.isSymbolicLink(p)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   276
                throw new IOException("Symlink not accepted");
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   277
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   278
            try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   279
                Set<PosixFilePermission> perms =
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   280
                        Files.getPosixFilePermissions(p);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   281
                if (uid != -1 &&
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   282
                        (Integer)Files.getAttribute(p, "unix:uid") != uid) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   283
                    throw new IOException("Not mine");
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   284
                }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   285
                if (perms.contains(PosixFilePermission.GROUP_READ) ||
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   286
                        perms.contains(PosixFilePermission.GROUP_WRITE) ||
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   287
                        perms.contains(PosixFilePermission.GROUP_EXECUTE) ||
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   288
                        perms.contains(PosixFilePermission.OTHERS_READ) ||
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   289
                        perms.contains(PosixFilePermission.OTHERS_WRITE) ||
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   290
                        perms.contains(PosixFilePermission.OTHERS_EXECUTE)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   291
                    throw new IOException("Accessible by someone else");
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   292
                }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   293
            } catch (UnsupportedOperationException uoe) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   294
                // No POSIX permissions? Ignore it.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   295
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   296
            chan = Files.newByteChannel(p, StandardOpenOption.WRITE,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   297
                    StandardOpenOption.READ);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   298
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   299
            long timeLimit = currTime.getSeconds() - readHeader(chan);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   300
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   301
            long pos = 0;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   302
            boolean seeNewButNotSame = false;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   303
            while (true) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   304
                try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   305
                    pos = chan.position();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   306
                    AuthTime a = AuthTime.readFrom(chan);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   307
                    if (a instanceof AuthTimeWithHash) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   308
                        if (time.equals(a)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   309
                            // Exact match, must be a replay
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   310
                            throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   311
                        } else if (time.isSameIgnoresHash(a)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   312
                            // Two different authenticators in the same second.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   313
                            // Remember it
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   314
                            seeNewButNotSame = true;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   315
                        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   316
                    } else {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   317
                        if (time.isSameIgnoresHash(a)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   318
                            // Two authenticators in the same second. Considered
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   319
                            // same if we haven't seen a new style version of it
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   320
                            if (!seeNewButNotSame) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   321
                                throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   322
                            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   323
                        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   324
                    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   325
                    if (a.ctime < timeLimit) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   326
                        missed++;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   327
                    } else {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   328
                        missed--;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   329
                    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   330
                } catch (BufferUnderflowException e) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   331
                    // Half-written file?
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   332
                    chan.position(pos);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   333
                    break;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   334
                }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   335
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   336
            return missed;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   337
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   338
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   339
        private static int readHeader(SeekableByteChannel chan)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   340
                throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   341
            ByteBuffer bb = ByteBuffer.allocate(6);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   342
            chan.read(bb);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   343
            if (bb.getShort(0) != KRB5_RV_VNO) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   344
                throw new IOException("Not correct rcache version");
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   345
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   346
            bb.order(ByteOrder.nativeOrder());
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   347
            return bb.getInt(2);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   348
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   349
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   350
        private void append(AuthTimeWithHash at) throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   351
            // Write an entry with hash, to be followed by one without it,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   352
            // for the benefit of old implementations.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   353
            ByteBuffer bb;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   354
            bb = ByteBuffer.wrap(at.encode(true));
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   355
            chan.write(bb);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   356
            bb = ByteBuffer.wrap(at.encode(false));
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   357
            chan.write(bb);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   358
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   359
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   360
        @Override
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   361
        public void close() throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   362
            if (chan != null) chan.close();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   363
            chan = null;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   364
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   365
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   366
}