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: import java.net.*;
033: import java.util.Vector;
034:
035: class ChannelAgentForwarding extends Channel {
036:
037: static private final int LOCAL_WINDOW_SIZE_MAX = 0x20000;
038: static private final int LOCAL_MAXIMUM_PACKET_SIZE = 0x4000;
039:
040: private final int SSH2_AGENTC_REQUEST_IDENTITIES = 11;
041: private final int SSH2_AGENT_IDENTITIES_ANSWER = 12;
042: private final int SSH2_AGENTC_SIGN_REQUEST = 13;
043: private final int SSH2_AGENT_SIGN_RESPONSE = 14;
044: private final int SSH2_AGENTC_ADD_IDENTITY = 17;
045: private final int SSH2_AGENTC_REMOVE_IDENTITY = 18;
046: private final int SSH2_AGENTC_REMOVE_ALL_IDENTITIES = 19;
047: private final int SSH2_AGENT_FAILURE = 30;
048:
049: boolean init = true;
050:
051: private Buffer rbuf = null;
052: private Buffer wbuf = null;
053: private Packet packet = null;
054: private Buffer mbuf = null;
055:
056: ChannelAgentForwarding() {
057: super ();
058:
059: setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX);
060: setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX);
061: setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE);
062:
063: type = "auth-agent@openssh.com".getBytes();
064: rbuf = new Buffer();
065: rbuf.reset();
066: //wbuf=new Buffer(rmpsize);
067: //packet=new Packet(wbuf);
068: mbuf = new Buffer();
069: connected = true;
070: }
071:
072: public void run() {
073: try {
074: sendOpenConfirmation();
075: } catch (Exception e) {
076: close = true;
077: disconnect();
078: }
079: }
080:
081: void write(byte[] foo, int s, int l) throws java.io.IOException {
082:
083: if (packet == null) {
084: wbuf = new Buffer(rmpsize);
085: packet = new Packet(wbuf);
086: }
087:
088: rbuf.shift();
089: if (rbuf.buffer.length < rbuf.index + l) {
090: byte[] newbuf = new byte[rbuf.s + l];
091: System.arraycopy(rbuf.buffer, 0, newbuf, 0,
092: rbuf.buffer.length);
093: rbuf.buffer = newbuf;
094: }
095:
096: rbuf.putByte(foo, s, l);
097:
098: int mlen = rbuf.getInt();
099: if (mlen > rbuf.getLength()) {
100: rbuf.s -= 4;
101: return;
102: }
103:
104: int typ = rbuf.getByte();
105:
106: Vector identities = getSession().jsch.identities;
107: UserInfo userinfo = getSession().getUserInfo();
108:
109: if (typ == SSH2_AGENTC_REQUEST_IDENTITIES) {
110: mbuf.reset();
111: mbuf.putByte((byte) SSH2_AGENT_IDENTITIES_ANSWER);
112: synchronized (identities) {
113: int count = 0;
114: for (int i = 0; i < identities.size(); i++) {
115: Identity identity = (Identity) (identities
116: .elementAt(i));
117: if (identity.getPublicKeyBlob() != null)
118: count++;
119: }
120: mbuf.putInt(count);
121: for (int i = 0; i < identities.size(); i++) {
122: Identity identity = (Identity) (identities
123: .elementAt(i));
124: byte[] pubkeyblob = identity.getPublicKeyBlob();
125: if (pubkeyblob == null)
126: continue;
127: mbuf.putString(pubkeyblob);
128: mbuf.putString("".getBytes());
129: }
130: }
131: byte[] bar = new byte[mbuf.getLength()];
132: mbuf.getByte(bar);
133:
134: send(bar);
135: } else if (typ == SSH2_AGENTC_SIGN_REQUEST) {
136: byte[] blob = rbuf.getString();
137: byte[] data = rbuf.getString();
138: int flags = rbuf.getInt();
139:
140: // if((flags & 1)!=0){ //SSH_AGENT_OLD_SIGNATURE // old OpenSSH 2.0, 2.1
141: // datafellows = SSH_BUG_SIGBLOB;
142: // }
143:
144: Identity identity = null;
145: synchronized (identities) {
146: for (int i = 0; i < identities.size(); i++) {
147: Identity _identity = (Identity) (identities
148: .elementAt(i));
149: if (_identity.getPublicKeyBlob() == null)
150: continue;
151: if (!Util.array_equals(blob, _identity
152: .getPublicKeyBlob())) {
153: continue;
154: }
155: if (_identity.isEncrypted()) {
156: if (userinfo == null)
157: continue;
158: while (_identity.isEncrypted()) {
159: if (!userinfo
160: .promptPassphrase("Passphrase for "
161: + _identity.getName())) {
162: break;
163: }
164:
165: String _passphrase = userinfo
166: .getPassphrase();
167: if (_passphrase == null) {
168: break;
169: }
170:
171: byte[] passphrase = Util
172: .str2byte(_passphrase);
173: try {
174: if (_identity.setPassphrase(passphrase)) {
175: break;
176: }
177: } catch (JSchException e) {
178: break;
179: }
180: }
181: }
182:
183: if (!_identity.isEncrypted()) {
184: identity = _identity;
185: break;
186: }
187: }
188: }
189:
190: byte[] signature = null;
191:
192: if (identity != null) {
193: signature = identity.getSignature(data);
194: }
195:
196: mbuf.reset();
197: if (signature == null) {
198: mbuf.putByte((byte) SSH2_AGENT_FAILURE);
199: } else {
200: mbuf.putByte((byte) SSH2_AGENT_SIGN_RESPONSE);
201: mbuf.putString(signature);
202: }
203:
204: byte[] bar = new byte[mbuf.getLength()];
205: mbuf.getByte(bar);
206:
207: send(bar);
208: }
209: }
210:
211: private void send(byte[] message) {
212: packet.reset();
213: wbuf.putByte((byte) Session.SSH_MSG_CHANNEL_DATA);
214: wbuf.putInt(recipient);
215: wbuf.putInt(4 + message.length);
216: wbuf.putString(message);
217:
218: try {
219: session.write(packet, this , 4 + message.length);
220: } catch (Exception e) {
221: }
222: }
223: }
|