src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java
author weijun
Tue, 14 Aug 2018 22:39:34 +0800
changeset 51398 3c389a284345
parent 47216 71c04702a3d5
permissions -rw-r--r--
8209416: Refactoring GetPropertyAction calls in security libs Reviewed-by: xuelei, rriggs
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
     1
/*
51398
3c389a284345 8209416: Refactoring GetPropertyAction calls in security libs
weijun
parents: 47216
diff changeset
     2
 * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
18536
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.util.*;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    40
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    41
import sun.security.action.GetPropertyAction;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    42
import sun.security.krb5.internal.KerberosTime;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    43
import sun.security.krb5.internal.Krb5;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    44
import sun.security.krb5.internal.KrbApErrException;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    45
import sun.security.krb5.internal.ReplayCache;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    46
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    47
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    48
/**
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    49
 * A dfl file is used to sustores AuthTime entries when the system property
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    50
 * sun.security.krb5.rcache is set to
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    51
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    52
 *    dfl(|:path/|:path/name|:name)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    53
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    54
 * The file will be path/name. If path is not given, it will be
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    55
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    56
 *    System.getProperty("java.io.tmpdir")
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    57
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    58
 * If name is not given, it will be
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    59
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    60
 *    service_euid
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    61
 *
34882
ce2a8ec851c1 8145544: Move sun.misc.VM to jdk.internal.misc
chegar
parents: 25859
diff changeset
    62
 * in which euid is available as jdk.internal.misc.VM.geteuid().
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    63
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    64
 * The file has a header:
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    65
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    66
 *    i16 0x0501 (KRB5_RC_VNO) in network order
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    67
 *    i32 number of seconds for lifespan (in native order, same below)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    68
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    69
 * followed by cache entries concatenated, which can be encoded in
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    70
 * 2 styles:
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    71
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    72
 * The traditional style is:
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    73
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    74
 *    LC of client principal
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    75
 *    LC of server principal
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    76
 *    i32 cusec of Authenticator
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    77
 *    i32 ctime of Authenticator
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    78
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    79
 * The new style has a hash:
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    80
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    81
 *    LC of ""
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    82
 *    LC of "HASH:%s %lu:%s %lu:%s" of (hash, clientlen, client, serverlen,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    83
 *          server) where msghash is 32 char (lower case) text mode md5sum
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    84
 *          of the ciphertext of authenticator.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    85
 *    i32 cusec of Authenticator
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    86
 *    i32 ctime of Authenticator
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    87
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    88
 * where LC of a string means
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    89
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    90
 *    i32 strlen(string) + 1
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    91
 *    octets of string, with the \0x00 ending
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    92
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    93
 * 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
    94
 * is available, which means there can be 2 entries for a single Authenticator.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    95
 * Java also does this way.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    96
 *
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
    97
 * See src/lib/krb5/rcache/rc_io.c and src/lib/krb5/rcache/rc_dfl.c.
41832
15db944958a7 8168518: rcache interop with krb5-1.15
weijun
parents: 34882
diff changeset
    98
 *
15db944958a7 8168518: rcache interop with krb5-1.15
weijun
parents: 34882
diff changeset
    99
 * Update: New version can use other hash algorithms.
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   100
 */
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   101
public class DflCache extends ReplayCache {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   102
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   103
    private static final int KRB5_RV_VNO = 0x501;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   104
    private static final int EXCESSREPS = 30;   // if missed-hit>this, recreate
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   105
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   106
    private final String source;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   107
24271
19000122bb5e 8039951: com.sun.security.auth.module missing classes on some platforms
weijun
parents: 18536
diff changeset
   108
    private static long uid;
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   109
    static {
24506
abb4cc4647ee 8043537: Changes for JDK-8039951 introduced circular dependency between Kerberos and com.sun.security.auth
weijun
parents: 24271
diff changeset
   110
        // Available on Solaris, Linux and Mac. Otherwise, -1 and no _euid suffix
34882
ce2a8ec851c1 8145544: Move sun.misc.VM to jdk.internal.misc
chegar
parents: 25859
diff changeset
   111
        uid = jdk.internal.misc.VM.geteuid();
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   112
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   113
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   114
    public DflCache (String source) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   115
        this.source = source;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   116
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   117
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   118
    private static String defaultPath() {
51398
3c389a284345 8209416: Refactoring GetPropertyAction calls in security libs
weijun
parents: 47216
diff changeset
   119
        return GetPropertyAction.privilegedGetProperty("java.io.tmpdir");
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   120
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   121
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   122
    private static String defaultFile(String server) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   123
        // service/host@REALM -> service
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   124
        int slash = server.indexOf('/');
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   125
        if (slash == -1) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   126
            // A normal principal? say, dummy@REALM
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   127
            slash = server.indexOf('@');
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   128
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   129
        if (slash != -1) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   130
            // Should not happen, but be careful
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   131
            server= server.substring(0, slash);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   132
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   133
        if (uid != -1) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   134
            server += "_" + uid;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   135
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   136
        return server;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   137
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   138
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   139
    private static Path getFileName(String source, String server) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   140
        String path, file;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   141
        if (source.equals("dfl")) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   142
            path = defaultPath();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   143
            file = defaultFile(server);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   144
        } else if (source.startsWith("dfl:")) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   145
            source = source.substring(4);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   146
            int pos = source.lastIndexOf('/');
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   147
            int pos1 = source.lastIndexOf('\\');
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   148
            if (pos1 > pos) pos = pos1;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   149
            if (pos == -1) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   150
                // Only file name
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   151
                path = defaultPath();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   152
                file = source;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   153
            } else if (new File(source).isDirectory()) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   154
                // Only path
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   155
                path = source;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   156
                file = defaultFile(server);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   157
            } else {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   158
                // Full pathname
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   159
                path = null;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   160
                file = source;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   161
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   162
        } else {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   163
            throw new IllegalArgumentException();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   164
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   165
        return new File(path, file).toPath();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   166
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   167
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   168
    @Override
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   169
    public void checkAndStore(KerberosTime currTime, AuthTimeWithHash time)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   170
            throws KrbApErrException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   171
        try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   172
            checkAndStore0(currTime, time);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   173
        } catch (IOException ioe) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   174
            KrbApErrException ke = new KrbApErrException(Krb5.KRB_ERR_GENERIC);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   175
            ke.initCause(ioe);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   176
            throw ke;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   177
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   178
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   179
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   180
    private synchronized void checkAndStore0(KerberosTime currTime, AuthTimeWithHash time)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   181
            throws IOException, KrbApErrException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   182
        Path p = getFileName(source, time.server);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   183
        int missed = 0;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   184
        try (Storage s = new Storage()) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   185
            try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   186
                missed = s.loadAndCheck(p, time, currTime);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   187
            } catch (IOException ioe) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   188
                // Non-existing or invalid file
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   189
                Storage.create(p);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   190
                missed = s.loadAndCheck(p, time, currTime);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   191
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   192
            s.append(time);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   193
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   194
        if (missed > EXCESSREPS) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   195
            Storage.expunge(p, currTime);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   196
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   197
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   198
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   199
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   200
    private static class Storage implements Closeable {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   201
        // Static methods
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   202
        @SuppressWarnings("try")
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   203
        private static void create(Path p) throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   204
            try (SeekableByteChannel newChan = createNoClose(p)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   205
                // Do nothing, wait for close
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   206
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   207
            makeMine(p);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   208
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   209
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   210
        private static void makeMine(Path p) throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   211
            // chmod to owner-rw only, otherwise MIT krb5 rejects
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   212
            try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   213
                Set<PosixFilePermission> attrs = new HashSet<>();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   214
                attrs.add(PosixFilePermission.OWNER_READ);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   215
                attrs.add(PosixFilePermission.OWNER_WRITE);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   216
                Files.setPosixFilePermissions(p, attrs);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   217
            } catch (UnsupportedOperationException uoe) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   218
                // No POSIX permission. That's OK.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   219
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   220
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   221
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   222
        private static SeekableByteChannel createNoClose(Path p)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   223
                throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   224
            SeekableByteChannel newChan = Files.newByteChannel(
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   225
                    p, StandardOpenOption.CREATE,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   226
                        StandardOpenOption.TRUNCATE_EXISTING,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   227
                        StandardOpenOption.WRITE);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   228
            ByteBuffer buffer = ByteBuffer.allocate(6);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   229
            buffer.putShort((short)KRB5_RV_VNO);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   230
            buffer.order(ByteOrder.nativeOrder());
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   231
            buffer.putInt(KerberosTime.getDefaultSkew());
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   232
            buffer.flip();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   233
            newChan.write(buffer);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   234
            return newChan;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   235
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   236
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   237
        private static void expunge(Path p, KerberosTime currTime)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   238
                throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   239
            Path p2 = Files.createTempFile(p.getParent(), "rcache", null);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   240
            try (SeekableByteChannel oldChan = Files.newByteChannel(p);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   241
                    SeekableByteChannel newChan = createNoClose(p2)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   242
                long timeLimit = currTime.getSeconds() - readHeader(oldChan);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   243
                while (true) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   244
                    try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   245
                        AuthTime at = AuthTime.readFrom(oldChan);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   246
                        if (at.ctime > timeLimit) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   247
                            ByteBuffer bb = ByteBuffer.wrap(at.encode(true));
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   248
                            newChan.write(bb);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   249
                        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   250
                    } catch (BufferUnderflowException e) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   251
                        break;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   252
                    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   253
                }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   254
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   255
            makeMine(p2);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   256
            Files.move(p2, p,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   257
                    StandardCopyOption.REPLACE_EXISTING,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   258
                    StandardCopyOption.ATOMIC_MOVE);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   259
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   260
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   261
        // Instance methods
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   262
        SeekableByteChannel chan;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   263
        private int loadAndCheck(Path p, AuthTimeWithHash time,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   264
                KerberosTime currTime)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   265
                throws IOException, KrbApErrException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   266
            int missed = 0;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   267
            if (Files.isSymbolicLink(p)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   268
                throw new IOException("Symlink not accepted");
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   269
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   270
            try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   271
                Set<PosixFilePermission> perms =
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   272
                        Files.getPosixFilePermissions(p);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   273
                if (uid != -1 &&
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   274
                        (Integer)Files.getAttribute(p, "unix:uid") != uid) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   275
                    throw new IOException("Not mine");
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   276
                }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   277
                if (perms.contains(PosixFilePermission.GROUP_READ) ||
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   278
                        perms.contains(PosixFilePermission.GROUP_WRITE) ||
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   279
                        perms.contains(PosixFilePermission.GROUP_EXECUTE) ||
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   280
                        perms.contains(PosixFilePermission.OTHERS_READ) ||
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   281
                        perms.contains(PosixFilePermission.OTHERS_WRITE) ||
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   282
                        perms.contains(PosixFilePermission.OTHERS_EXECUTE)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   283
                    throw new IOException("Accessible by someone else");
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   284
                }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   285
            } catch (UnsupportedOperationException uoe) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   286
                // No POSIX permissions? Ignore it.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   287
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   288
            chan = Files.newByteChannel(p, StandardOpenOption.WRITE,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   289
                    StandardOpenOption.READ);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   290
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   291
            long timeLimit = currTime.getSeconds() - readHeader(chan);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   292
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   293
            long pos = 0;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   294
            boolean seeNewButNotSame = false;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   295
            while (true) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   296
                try {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   297
                    pos = chan.position();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   298
                    AuthTime a = AuthTime.readFrom(chan);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   299
                    if (a instanceof AuthTimeWithHash) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   300
                        if (time.equals(a)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   301
                            // Exact match, must be a replay
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   302
                            throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
41832
15db944958a7 8168518: rcache interop with krb5-1.15
weijun
parents: 34882
diff changeset
   303
                        } else if (time.sameTimeDiffHash((AuthTimeWithHash)a)) {
18536
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   304
                            // Two different authenticators in the same second.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   305
                            // Remember it
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   306
                            seeNewButNotSame = true;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   307
                        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   308
                    } else {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   309
                        if (time.isSameIgnoresHash(a)) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   310
                            // Two authenticators in the same second. Considered
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   311
                            // same if we haven't seen a new style version of it
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   312
                            if (!seeNewButNotSame) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   313
                                throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   314
                            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   315
                        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   316
                    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   317
                    if (a.ctime < timeLimit) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   318
                        missed++;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   319
                    } else {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   320
                        missed--;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   321
                    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   322
                } catch (BufferUnderflowException e) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   323
                    // Half-written file?
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   324
                    chan.position(pos);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   325
                    break;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   326
                }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   327
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   328
            return missed;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   329
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   330
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   331
        private static int readHeader(SeekableByteChannel chan)
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   332
                throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   333
            ByteBuffer bb = ByteBuffer.allocate(6);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   334
            chan.read(bb);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   335
            if (bb.getShort(0) != KRB5_RV_VNO) {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   336
                throw new IOException("Not correct rcache version");
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   337
            }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   338
            bb.order(ByteOrder.nativeOrder());
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   339
            return bb.getInt(2);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   340
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   341
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   342
        private void append(AuthTimeWithHash at) throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   343
            // Write an entry with hash, to be followed by one without it,
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   344
            // for the benefit of old implementations.
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   345
            ByteBuffer bb;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   346
            bb = ByteBuffer.wrap(at.encode(true));
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   347
            chan.write(bb);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   348
            bb = ByteBuffer.wrap(at.encode(false));
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   349
            chan.write(bb);
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   350
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   351
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   352
        @Override
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   353
        public void close() throws IOException {
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   354
            if (chan != null) chan.close();
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   355
            chan = null;
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   356
        }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   357
    }
092411ced388 8001326: Improve Kerberos caching
weijun
parents:
diff changeset
   358
}