001: /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
002: /*
003: Copyright (c) 2002-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: import java.util.Vector;
033:
034: class UserAuthPublicKey extends UserAuth {
035:
036: public boolean start(Session session) throws Exception {
037: super .start(session);
038:
039: Vector identities = session.jsch.identities;
040:
041: byte[] passphrase = null;
042: byte[] _username = null;
043:
044: int command;
045:
046: synchronized (identities) {
047: if (identities.size() <= 0) {
048: return false;
049: }
050:
051: _username = Util.str2byte(username);
052:
053: for (int i = 0; i < identities.size(); i++) {
054: Identity identity = (Identity) (identities.elementAt(i));
055: byte[] pubkeyblob = identity.getPublicKeyBlob();
056:
057: //System.err.println("UserAuthPublicKey: "+identity+" "+pubkeyblob);
058:
059: if (pubkeyblob != null) {
060: // send
061: // byte SSH_MSG_USERAUTH_REQUEST(50)
062: // string user name
063: // string service name ("ssh-connection")
064: // string "publickey"
065: // boolen FALSE
066: // string plaintext password (ISO-10646 UTF-8)
067: packet.reset();
068: buf.putByte((byte) SSH_MSG_USERAUTH_REQUEST);
069: buf.putString(_username);
070: buf.putString("ssh-connection".getBytes());
071: buf.putString("publickey".getBytes());
072: buf.putByte((byte) 0);
073: buf.putString(identity.getAlgName().getBytes());
074: buf.putString(pubkeyblob);
075: session.write(packet);
076:
077: loop1: while (true) {
078: buf = session.read(buf);
079: command = buf.getCommand() & 0xff;
080:
081: if (command == SSH_MSG_USERAUTH_PK_OK) {
082: break;
083: } else if (command == SSH_MSG_USERAUTH_FAILURE) {
084: break;
085: } else if (command == SSH_MSG_USERAUTH_BANNER) {
086: buf.getInt();
087: buf.getByte();
088: buf.getByte();
089: byte[] _message = buf.getString();
090: byte[] lang = buf.getString();
091: String message = null;
092: try {
093: message = new String(_message, "UTF-8");
094: } catch (java.io.UnsupportedEncodingException e) {
095: message = new String(_message);
096: }
097: if (userinfo != null) {
098: userinfo.showMessage(message);
099: }
100: continue loop1;
101: } else {
102: //System.err.println("USERAUTH fail ("+command+")");
103: //throw new JSchException("USERAUTH fail ("+command+")");
104: break;
105: }
106: }
107:
108: if (command != SSH_MSG_USERAUTH_PK_OK) {
109: continue;
110: }
111: }
112:
113: //System.err.println("UserAuthPublicKey: identity.isEncrypted()="+identity.isEncrypted());
114:
115: int count = 5;
116: while (true) {
117: if ((identity.isEncrypted() && passphrase == null)) {
118: if (userinfo == null)
119: throw new JSchException("USERAUTH fail");
120: if (identity.isEncrypted()
121: && !userinfo
122: .promptPassphrase("Passphrase for "
123: + identity.getName())) {
124: throw new JSchAuthCancelException(
125: "publickey");
126: //throw new JSchException("USERAUTH cancel");
127: //break;
128: }
129: String _passphrase = userinfo.getPassphrase();
130: if (_passphrase != null) {
131: passphrase = Util.str2byte(_passphrase);
132: }
133: }
134:
135: if (!identity.isEncrypted() || passphrase != null) {
136: if (identity.setPassphrase(passphrase))
137: break;
138: }
139: Util.bzero(passphrase);
140: passphrase = null;
141: count--;
142: if (count == 0)
143: break;
144: }
145:
146: Util.bzero(passphrase);
147: passphrase = null;
148: //System.err.println("UserAuthPublicKey: identity.isEncrypted()="+identity.isEncrypted());
149:
150: if (identity.isEncrypted())
151: continue;
152: if (pubkeyblob == null)
153: pubkeyblob = identity.getPublicKeyBlob();
154:
155: //System.err.println("UserAuthPublicKey: pubkeyblob="+pubkeyblob);
156:
157: if (pubkeyblob == null)
158: continue;
159:
160: // send
161: // byte SSH_MSG_USERAUTH_REQUEST(50)
162: // string user name
163: // string service name ("ssh-connection")
164: // string "publickey"
165: // boolen TRUE
166: // string plaintext password (ISO-10646 UTF-8)
167: packet.reset();
168: buf.putByte((byte) SSH_MSG_USERAUTH_REQUEST);
169: buf.putString(_username);
170: buf.putString("ssh-connection".getBytes());
171: buf.putString("publickey".getBytes());
172: buf.putByte((byte) 1);
173: buf.putString(identity.getAlgName().getBytes());
174: buf.putString(pubkeyblob);
175:
176: // byte[] tmp=new byte[buf.index-5];
177: // System.arraycopy(buf.buffer, 5, tmp, 0, tmp.length);
178: // buf.putString(signature);
179:
180: byte[] sid = session.getSessionId();
181: int sidlen = sid.length;
182: byte[] tmp = new byte[4 + sidlen + buf.index - 5];
183: tmp[0] = (byte) (sidlen >>> 24);
184: tmp[1] = (byte) (sidlen >>> 16);
185: tmp[2] = (byte) (sidlen >>> 8);
186: tmp[3] = (byte) (sidlen);
187: System.arraycopy(sid, 0, tmp, 4, sidlen);
188: System.arraycopy(buf.buffer, 5, tmp, 4 + sidlen,
189: buf.index - 5);
190: byte[] signature = identity.getSignature(tmp);
191: if (signature == null) { // for example, too long key length.
192: break;
193: }
194: buf.putString(signature);
195: session.write(packet);
196:
197: loop2: while (true) {
198: buf = session.read(buf);
199: command = buf.getCommand() & 0xff;
200:
201: if (command == SSH_MSG_USERAUTH_SUCCESS) {
202: return true;
203: } else if (command == SSH_MSG_USERAUTH_BANNER) {
204: buf.getInt();
205: buf.getByte();
206: buf.getByte();
207: byte[] _message = buf.getString();
208: byte[] lang = buf.getString();
209: String message = null;
210: try {
211: message = new String(_message, "UTF-8");
212: } catch (java.io.UnsupportedEncodingException e) {
213: message = new String(_message);
214: }
215: if (userinfo != null) {
216: userinfo.showMessage(message);
217: }
218: continue loop2;
219: } else if (command == SSH_MSG_USERAUTH_FAILURE) {
220: buf.getInt();
221: buf.getByte();
222: buf.getByte();
223: byte[] foo = buf.getString();
224: int partial_success = buf.getByte();
225: //System.err.println(new String(foo)+
226: // " partial_success:"+(partial_success!=0));
227: if (partial_success != 0) {
228: throw new JSchPartialAuthException(
229: new String(foo));
230: }
231: break;
232: }
233: //System.err.println("USERAUTH fail ("+command+")");
234: //throw new JSchException("USERAUTH fail ("+command+")");
235: break;
236: }
237: }
238: }
239: return false;
240: }
241: }
|