001: /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
002: /*
003: Copyright(c) 2006-2008 ymnk, JCraft,Inc. All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions are met:
007:
008: 1. Redistributions of source code must retain the above copyright notice,
009: this list of conditions and the following disclaimer.
010:
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in
013: the documentation and/or other materials provided with the distribution.
014:
015: 3. The names of the authors may not be used to endorse or promote products
016: derived from this software without specific prior written permission.
017:
018: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
019: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
020: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
021: INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
022: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT
023: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
024: OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY OF
025: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING
026: NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
027: EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jcraft.jsch;
031:
032: public class UserAuthGSSAPIWithMIC extends UserAuth {
033: private static final int SSH_MSG_USERAUTH_GSSAPI_RESPONSE = 60;
034: private static final int SSH_MSG_USERAUTH_GSSAPI_TOKEN = 61;
035: private static final int SSH_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE = 63;
036: private static final int SSH_MSG_USERAUTH_GSSAPI_ERROR = 64;
037: private static final int SSH_MSG_USERAUTH_GSSAPI_ERRTOK = 65;
038: private static final int SSH_MSG_USERAUTH_GSSAPI_MIC = 66;
039:
040: private static final byte[][] supported_oid = {
041: // OID 1.2.840.113554.1.2.2 in DER
042: { (byte) 0x6, (byte) 0x9, (byte) 0x2a, (byte) 0x86, (byte) 0x48,
043: (byte) 0x86, (byte) 0xf7, (byte) 0x12, (byte) 0x1,
044: (byte) 0x2, (byte) 0x2 } };
045:
046: private static final String[] supported_method = { "gssapi-with-mic.krb5" };
047:
048: public boolean start(Session session) throws Exception {
049: super .start(session);
050:
051: byte[] _username = Util.str2byte(username);
052:
053: packet.reset();
054:
055: // byte SSH_MSG_USERAUTH_REQUEST(50)
056: // string user name(in ISO-10646 UTF-8 encoding)
057: // string service name(in US-ASCII)
058: // string "gssapi"(US-ASCII)
059: // uint32 n, the number of OIDs client supports
060: // string[n] mechanism OIDS
061: buf.putByte((byte) SSH_MSG_USERAUTH_REQUEST);
062: buf.putString(_username);
063: buf.putString("ssh-connection".getBytes());
064: buf.putString("gssapi-with-mic".getBytes());
065: buf.putInt(supported_oid.length);
066: for (int i = 0; i < supported_oid.length; i++) {
067: buf.putString(supported_oid[i]);
068: }
069: session.write(packet);
070:
071: String method = null;
072: int command;
073: while (true) {
074: buf = session.read(buf);
075: command = buf.getCommand() & 0xff;
076:
077: if (command == SSH_MSG_USERAUTH_FAILURE) {
078: return false;
079: }
080:
081: if (command == SSH_MSG_USERAUTH_GSSAPI_RESPONSE) {
082: buf.getInt();
083: buf.getByte();
084: buf.getByte();
085: byte[] message = buf.getString();
086:
087: for (int i = 0; i < supported_oid.length; i++) {
088: if (Util.array_equals(message, supported_oid[i])) {
089: method = supported_method[i];
090: break;
091: }
092: }
093:
094: if (method == null) {
095: return false;
096: }
097:
098: break; // success
099: }
100:
101: if (command == SSH_MSG_USERAUTH_BANNER) {
102: buf.getInt();
103: buf.getByte();
104: buf.getByte();
105: byte[] _message = buf.getString();
106: byte[] lang = buf.getString();
107: String message = Util.byte2str(_message);
108: if (userinfo != null) {
109: userinfo.showMessage(message);
110: }
111: continue;
112: }
113: return false;
114: }
115:
116: GSSContext context = null;
117: try {
118: Class c = Class.forName(session.getConfig(method));
119: context = (GSSContext) (c.newInstance());
120: } catch (Exception e) {
121: return false;
122: }
123:
124: try {
125: context.create(username, session.host);
126: } catch (JSchException e) {
127: return false;
128: }
129:
130: byte[] token = new byte[0];
131:
132: while (!context.isEstablished()) {
133: try {
134: token = context.init(token, 0, token.length);
135: } catch (JSchException e) {
136: // TODO
137: // ERRTOK should be sent?
138: // byte SSH_MSG_USERAUTH_GSSAPI_ERRTOK
139: // string error token
140: return false;
141: }
142:
143: if (token != null) {
144: packet.reset();
145: buf.putByte((byte) SSH_MSG_USERAUTH_GSSAPI_TOKEN);
146: buf.putString(token);
147: session.write(packet);
148: }
149:
150: if (!context.isEstablished()) {
151: buf = session.read(buf);
152: command = buf.getCommand() & 0xff;
153: if (command == SSH_MSG_USERAUTH_GSSAPI_ERROR) {
154: // uint32 major_status
155: // uint32 minor_status
156: // string message
157: // string language tag
158:
159: buf = session.read(buf);
160: command = buf.getCommand() & 0xff;
161: //return false;
162: } else if (command == SSH_MSG_USERAUTH_GSSAPI_ERRTOK) {
163: // string error token
164:
165: buf = session.read(buf);
166: command = buf.getCommand() & 0xff;
167: //return false;
168: }
169:
170: if (command == SSH_MSG_USERAUTH_FAILURE) {
171: return false;
172: }
173:
174: buf.getInt();
175: buf.getByte();
176: buf.getByte();
177: token = buf.getString();
178: }
179: }
180:
181: Buffer mbuf = new Buffer();
182: // string session identifier
183: // byte SSH_MSG_USERAUTH_REQUEST
184: // string user name
185: // string service
186: // string "gssapi-with-mic"
187: mbuf.putString(session.getSessionId());
188: mbuf.putByte((byte) SSH_MSG_USERAUTH_REQUEST);
189: mbuf.putString(_username);
190: mbuf.putString("ssh-connection".getBytes());
191: mbuf.putString("gssapi-with-mic".getBytes());
192:
193: byte[] mic = context.getMIC(mbuf.buffer, 0, mbuf.getLength());
194:
195: if (mic == null) {
196: return false;
197: }
198:
199: packet.reset();
200: buf.putByte((byte) SSH_MSG_USERAUTH_GSSAPI_MIC);
201: buf.putString(mic);
202: session.write(packet);
203:
204: context.dispose();
205:
206: buf = session.read(buf);
207: command = buf.getCommand() & 0xff;
208:
209: if (command == SSH_MSG_USERAUTH_SUCCESS) {
210: return true;
211: } else if (command == SSH_MSG_USERAUTH_FAILURE) {
212: buf.getInt();
213: buf.getByte();
214: buf.getByte();
215: byte[] foo = buf.getString();
216: int partial_success = buf.getByte();
217: //System.err.println(new String(foo)+
218: // " partial_success:"+(partial_success!=0));
219: if (partial_success != 0) {
220: throw new JSchPartialAuthException(new String(foo));
221: }
222: }
223: return false;
224: }
225: }
|