blob: 6003cdfaeabbce1225b14bf137807303746c6ba5 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.security.jgss.spnego;
27
28import java.io.*;
29import java.util.*;
30import org.ietf.jgss.*;
31import sun.security.jgss.*;
32import sun.security.util.*;
33
34/**
35 * Implements the SPNEGO NegTokenInit token
36 * as specified in RFC 2478
37 *
38 * NegTokenInit ::= SEQUENCE {
39 * mechTypes [0] MechTypeList OPTIONAL,
40 * reqFlags [1] ContextFlags OPTIONAL,
41 * mechToken [2] OCTET STRING OPTIONAL,
42 * mechListMIC [3] OCTET STRING OPTIONAL
43 * }
44 *
45 * MechTypeList ::= SEQUENCE OF MechType
46 *
47 * MechType::= OBJECT IDENTIFIER
48 *
49 * ContextFlags ::= BIT STRING {
50 * delegFlag (0),
51 * mutualFlag (1),
52 * replayFlag (2),
53 * sequenceFlag (3),
54 * anonFlag (4),
55 * confFlag (5),
56 * integFlag (6)
57 * }
58 *
59 * @author Seema Malkani
60 * @since 1.6
61 */
62
63public class NegTokenInit extends SpNegoToken {
64
65 // DER-encoded mechTypes
66 private byte[] mechTypes = null;
67 private Oid[] mechTypeList = null;
68
69 private byte[] reqFlags = null;
70 private byte[] mechToken = null;
71 private byte[] mechListMIC = null;
72
73 NegTokenInit(byte[] mechTypes, byte[] flags,
74 byte[] token, byte[] mechListMIC)
75 {
76 super(NEG_TOKEN_INIT_ID);
77 this.mechTypes = mechTypes;
78 this.reqFlags = flags;
79 this.mechToken = token;
80 this.mechListMIC = mechListMIC;
81 }
82
83 // Used by sun.security.jgss.wrapper.NativeGSSContext
84 // to parse SPNEGO tokens
85 public NegTokenInit(byte[] in) throws GSSException {
86 super(NEG_TOKEN_INIT_ID);
87 parseToken(in);
88 }
89
90 final byte[] encode() throws GSSException {
91 try {
92 // create negInitToken
93 DerOutputStream initToken = new DerOutputStream();
94
95 // DER-encoded mechTypes with CONTEXT 00
96 if (mechTypes != null) {
97 initToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,
98 true, (byte) 0x00), mechTypes);
99 }
100
101 // write context flags with CONTEXT 01
102 if (reqFlags != null) {
103 DerOutputStream flags = new DerOutputStream();
104 flags.putBitString(reqFlags);
105 initToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,
106 true, (byte) 0x01), flags);
107 }
108
109 // mechToken with CONTEXT 02
110 if (mechToken != null) {
111 DerOutputStream dataValue = new DerOutputStream();
112 dataValue.putOctetString(mechToken);
113 initToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,
114 true, (byte) 0x02), dataValue);
115 }
116
117 // mechListMIC with CONTEXT 03
118 if (mechListMIC != null) {
119 if (DEBUG) {
120 System.out.println("SpNegoToken NegTokenInit: " +
121 "sending MechListMIC");
122 }
123 DerOutputStream mic = new DerOutputStream();
124 mic.putOctetString(mechListMIC);
125 initToken.write(DerValue.createTag(DerValue.TAG_CONTEXT,
126 true, (byte) 0x03), mic);
127 }
128
129 // insert in a SEQUENCE
130 DerOutputStream out = new DerOutputStream();
131 out.write(DerValue.tag_Sequence, initToken);
132
133 return out.toByteArray();
134
135 } catch (IOException e) {
136 throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
137 "Invalid SPNEGO NegTokenInit token : " + e.getMessage());
138 }
139 }
140
141 private void parseToken(byte[] in) throws GSSException {
142 try {
143 DerValue der = new DerValue(in);
144 // verify NegotiationToken type token
145 if (!der.isContextSpecific((byte) NEG_TOKEN_INIT_ID)) {
146 throw new IOException("SPNEGO NegoTokenInit : " +
147 "did not have right token type");
148 }
149 DerValue tmp1 = der.data.getDerValue();
150 if (tmp1.tag != DerValue.tag_Sequence) {
151 throw new IOException("SPNEGO NegoTokenInit : " +
152 "did not have the Sequence tag");
153 }
154
155 // parse SEQUENCE of mechTypes, if present
156 if (tmp1.data.available() > 0) {
157 DerValue tmp2 = tmp1.data.getDerValue();
158 if (!tmp2.isContextSpecific((byte)0x00)) {
159 throw new IOException("SPNEGO NegoTokenInit : " +
160 "did not have the right context tag for mechTypes");
161 }
162 // get the DER-encoded sequence of mechTypes
163 DerInputStream mValue = tmp2.data;
164 mechTypes = mValue.toByteArray();
165
166 // read all the mechTypes
167 DerValue[] mList = mValue.getSequence(0);
168 mechTypeList = new Oid[mList.length];
169 ObjectIdentifier mech = null;
170 for (int i = 0; i < mList.length; i++) {
171 mech = mList[i].getOID();
172 if (DEBUG) {
173 System.out.println("SpNegoToken NegTokenInit: " +
174 "reading Mechanism Oid = " + mech);
175 }
176 mechTypeList[i] = new Oid(mech.toString());
177 }
178 }
179
180 // parse mechToken, if present (skip reqFlags)
181 if (tmp1.data.available() > 0) {
182 DerValue tmp3 = tmp1.data.getDerValue();
183 if (tmp3.isContextSpecific((byte)0x01)) {
184 // received reqFlags, skip it
185 // now parse next field mechToken
186 if (tmp1.data.available() > 0) {
187 tmp3 = tmp1.data.getDerValue();
188 }
189 }
190 if (!tmp3.isContextSpecific((byte)0x02)) {
191 throw new IOException("SPNEGO NegoTokenInit : " +
192 "did not have the right context tag for mechToken");
193 }
194 if (DEBUG) {
195 System.out.println("SpNegoToken NegTokenInit: " +
196 "reading Mech Token");
197 }
198 mechToken = tmp3.data.getOctetString();
199 }
200
201 // parse mechListMIC, if present and not in MS interop mode
202 if (!GSSUtil.useMSInterop() && (tmp1.data.available() > 0)) {
203 if (DEBUG) {
204 System.out.println("SpNegoToken NegTokenInit: " +
205 "receiving MechListMIC");
206 }
207 DerValue tmp6 = tmp1.data.getDerValue();
208 if (!tmp6.isContextSpecific((byte)0x03)) {
209 throw new IOException("SPNEGO NegoTokenInit : " +
210 "did not have the right context tag for MICToken");
211 }
212 mechListMIC = tmp6.data.getOctetString();
213 if (DEBUG) {
214 System.out.println("SpNegoToken NegTokenInit: " +
215 "MechListMIC Token = " + getHexBytes(mechListMIC));
216 }
217 } else {
218 if (DEBUG) {
219 System.out.println("SpNegoToken NegTokenInit : " +
220 "no MIC token included");
221 }
222 }
223
224 } catch (IOException e) {
225 throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
226 "Invalid SPNEGO NegTokenInit token : " + e.getMessage());
227 }
228 }
229
230 byte[] getMechTypes() {
231 return mechTypes;
232 }
233
234 // Used by sun.security.jgss.wrapper.NativeGSSContext
235 // to find the mechs in SPNEGO tokens
236 public Oid[] getMechTypeList() {
237 return mechTypeList;
238 }
239
240 byte[] getReqFlags() {
241 return reqFlags;
242 }
243
244 // Used by sun.security.jgss.wrapper.NativeGSSContext
245 // to access the mech token portion of SPNEGO tokens
246 public byte[] getMechToken() {
247 return mechToken;
248 }
249
250 byte[] getMechListMIC() {
251 return mechListMIC;
252 }
253
254}