1/*
2 * Copyright (c) 2005, 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
26package sun.security.jgss;
27
28import java.io.InputStream;
29import java.io.OutputStream;
30import java.io.IOException;
31import java.io.EOFException;
32import sun.security.util.*;
33
34/**
35 * Utilities for processing GSS Tokens.
36 *
37 */
38
39public abstract class GSSToken {
40
41    /**
42     * Copies an integer value to a byte array in little endian form.
43     * @param value the integer value to write
44     * @param array the byte array into which the integer must be copied. It
45     * is assumed that the array will be large enough to hold the 4 bytes of
46     * the integer.
47     */
48    public static final void writeLittleEndian(int value, byte[] array) {
49        writeLittleEndian(value, array, 0);
50    }
51
52    /**
53     * Copies an integer value to a byte array in little endian form.
54     * @param value the integer value to write
55     * @param array the byte array into which the integer must be copied. It
56     * is assumed that the array will be large enough to hold the 4 bytes of
57     * the integer.
58     * @param pos the position at which to start writing
59     */
60    public static final void writeLittleEndian(int value, byte[] array,
61                                               int pos) {
62        array[pos++] = (byte)(value);
63        array[pos++] = (byte)((value>>>8));
64        array[pos++] = (byte)((value>>>16));
65        array[pos++] = (byte)((value>>>24));
66    }
67
68    public static final void writeBigEndian(int value, byte[] array) {
69        writeBigEndian(value, array, 0);
70    }
71
72    public static final void writeBigEndian(int value, byte[] array,
73                                               int pos) {
74        array[pos++] = (byte)((value>>>24));
75        array[pos++] = (byte)((value>>>16));
76        array[pos++] = (byte)((value>>>8));
77        array[pos++] = (byte)(value);
78    }
79
80    /**
81     * Reads an integer value from a byte array in little endian form. This
82     * method allows the reading of two byte values as well as four bytes
83     * values both of which are needed in the Kerberos v5 GSS-API mechanism.
84     *
85     * @param data the array containing the bytes of the integer value
86     * @param pos the offset in the array
87     * @param size the number of bytes to read from the array.
88     * @return the integer value
89     */
90    public static final int readLittleEndian(byte[] data, int pos, int size) {
91        int retVal = 0;
92        int shifter = 0;
93        while (size > 0) {
94            retVal += (data[pos] & 0xff) << shifter;
95            shifter += 8;
96            pos++;
97            size--;
98        }
99        return retVal;
100    }
101
102    public static final int readBigEndian(byte[] data, int pos, int size) {
103        int retVal = 0;
104        int shifter = (size-1)*8;
105        while (size > 0) {
106            retVal += (data[pos] & 0xff) << shifter;
107            shifter -= 8;
108            pos++;
109            size--;
110        }
111        return retVal;
112    }
113
114    /**
115     * Writes a two byte integer value to a OutputStream.
116     *
117     * @param val the integer value. It will lose the high-order two bytes.
118     * @param os the OutputStream to write to
119     * @throws IOException if an error occurs while writing to the OutputStream
120     */
121    public static final void writeInt(int val, OutputStream os)
122        throws IOException {
123        os.write(val>>>8);
124        os.write(val);
125    }
126
127    /**
128     * Writes a two byte integer value to a byte array.
129     *
130     * @param val the integer value. It will lose the high-order two bytes.
131     * @param dest the byte array to write to
132     * @param pos the offset to start writing to
133     */
134    public static final int writeInt(int val, byte[] dest, int pos) {
135        dest[pos++] = (byte)(val>>>8);
136        dest[pos++] = (byte)val;
137        return pos;
138    }
139
140    /**
141     * Reads a two byte integer value from an InputStream.
142     *
143     * @param is the InputStream to read from
144     * @return the integer value
145     * @throws IOException if some errors occurs while reading the integer
146     * bytes.
147     */
148    public static final int readInt(InputStream is) throws IOException {
149        return (((0xFF & is.read()) << 8)
150                 | (0xFF & is.read()));
151    }
152
153    /**
154     * Reads a two byte integer value from a byte array.
155     *
156     * @param src the byte arra to read from
157     * @param pos the offset to start reading from
158     * @return the integer value
159     */
160    public static final int readInt(byte[] src, int pos) {
161        return ((0xFF & src[pos])<<8 | (0xFF & src[pos+1]));
162    }
163
164    /**
165     * Blocks till the required number of bytes have been read from the
166     * input stream.
167     *
168     * @param is the InputStream to read from
169     * @param buffer the buffer to store the bytes into
170     * @throws EOFException if EOF is reached before all bytes are
171     *         read.
172     * @throws IOException is an error occurs while reading
173     */
174    public static final void readFully(InputStream is, byte[] buffer)
175        throws IOException {
176        readFully(is, buffer, 0, buffer.length);
177    }
178
179    /**
180     * Blocks till the required number of bytes have been read from the
181     * input stream.
182     *
183     * @param is the InputStream to read from
184     * @param buffer the buffer to store the bytes into
185     * @param offset the offset to start storing at
186     * @param len the number of bytes to read
187     * @throws EOFException if EOF is reached before all bytes are
188     *         read.
189     * @throws IOException is an error occurs while reading
190     */
191    public static final void readFully(InputStream is,
192                                       byte[] buffer, int offset, int len)
193        throws IOException {
194        int temp;
195        while (len > 0) {
196            temp = is.read(buffer, offset, len);
197            if (temp == -1)
198                throw new EOFException("Cannot read all "
199                                       + len
200                                       + " bytes needed to form this token!");
201            offset += temp;
202            len -= temp;
203        }
204    }
205
206    public static final void debug(String str) {
207        System.err.print(str);
208    }
209
210    public static final  String getHexBytes(byte[] bytes) {
211        return getHexBytes(bytes, 0, bytes.length);
212    }
213
214    public static final  String getHexBytes(byte[] bytes, int len) {
215        return getHexBytes(bytes, 0, len);
216    }
217
218    public static final String getHexBytes(byte[] bytes, int pos, int len) {
219        StringBuilder sb = new StringBuilder();
220        for (int i = pos; i < (pos+len); i++) {
221            int b1 = (bytes[i]>>4) & 0x0f;
222            int b2 = bytes[i] & 0x0f;
223
224            sb.append(Integer.toHexString(b1));
225            sb.append(Integer.toHexString(b2));
226            sb.append(' ');
227        }
228        return sb.toString();
229    }
230
231}
232