diff --git a/src/JavaFileStorageBindings/Transforms/Metadata.xml b/src/JavaFileStorageBindings/Transforms/Metadata.xml index 2587ddc4..5219b2c0 100644 --- a/src/JavaFileStorageBindings/Transforms/Metadata.xml +++ b/src/JavaFileStorageBindings/Transforms/Metadata.xml @@ -6,4 +6,8 @@ This sample removes the method: android.support.v4.content.CursorLoader.loadInBackground: --> + + + + diff --git a/src/KeePassLib2Android/KeePassLib2Android.csproj b/src/KeePassLib2Android/KeePassLib2Android.csproj index a94a4e68..2097a03d 100644 --- a/src/KeePassLib2Android/KeePassLib2Android.csproj +++ b/src/KeePassLib2Android/KeePassLib2Android.csproj @@ -20,7 +20,7 @@ full False bin\Debug - DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE + DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE prompt 4 False diff --git a/src/Kp2aBusinessLogic/Io/SftpFileStorage.cs b/src/Kp2aBusinessLogic/Io/SftpFileStorage.cs new file mode 100644 index 00000000..ce2f3a9c --- /dev/null +++ b/src/Kp2aBusinessLogic/Io/SftpFileStorage.cs @@ -0,0 +1,18 @@ +using Android.Content; +#if !EXCLUDE_JAVAFILESTORAGE + +namespace keepass2android.Io +{ + public class SftpFileStorage: JavaFileStorage + { + public SftpFileStorage(IKp2aApp app) : + base(new Keepass2android.Javafilestorage.SftpStorage(), app) + { + } + + + } + + +} +#endif \ No newline at end of file diff --git a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj index 9b7d78b0..9c6aaaef 100644 --- a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj +++ b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj @@ -20,7 +20,7 @@ full false bin\Debug\ - TRACE;DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE + TRACE;DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE prompt 4 @@ -67,6 +67,7 @@ + @@ -96,6 +97,11 @@ + + + + + diff --git a/src/Kp2aBusinessLogic/SearchDbHelper.cs b/src/Kp2aBusinessLogic/SearchDbHelper.cs index f26f76d6..2ebe35eb 100644 --- a/src/Kp2aBusinessLogic/SearchDbHelper.cs +++ b/src/Kp2aBusinessLogic/SearchDbHelper.cs @@ -17,6 +17,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file using System; using System.Collections.Generic; using System.Text.RegularExpressions; +using KeePass.Util.Spr; using KeePassLib; using KeePassLib.Collections; using KeePassLib.Interfaces; @@ -104,7 +105,9 @@ namespace keepass2android return pgResults; foreach (PwEntry entry in database.Entries.Values) { - String otherHost = ExtractHost(entry.Strings.ReadSafe(PwDefs.UrlField)); + string otherUrl = entry.Strings.ReadSafe(PwDefs.UrlField); + otherUrl = SprEngine.Compile(otherUrl, new SprContext(entry, database.KpDatabase, SprCompileFlags.References)); + String otherHost = ExtractHost(otherUrl); if ((allowSubdomains) && (otherHost.StartsWith("www."))) otherHost = otherHost.Substring(4); //remove "www." if (String.IsNullOrWhiteSpace(otherHost)) diff --git a/src/keepass2android/Utils/EntryUtil.cs b/src/Kp2aBusinessLogic/Utils/EntryUtil.cs similarity index 100% rename from src/keepass2android/Utils/EntryUtil.cs rename to src/Kp2aBusinessLogic/Utils/EntryUtil.cs diff --git a/src/keepass2android/Utils/Spr/SprContext.cs b/src/Kp2aBusinessLogic/Utils/Spr/SprContext.cs similarity index 100% rename from src/keepass2android/Utils/Spr/SprContext.cs rename to src/Kp2aBusinessLogic/Utils/Spr/SprContext.cs diff --git a/src/keepass2android/Utils/Spr/SprEncoding.cs b/src/Kp2aBusinessLogic/Utils/Spr/SprEncoding.cs similarity index 100% rename from src/keepass2android/Utils/Spr/SprEncoding.cs rename to src/Kp2aBusinessLogic/Utils/Spr/SprEncoding.cs diff --git a/src/keepass2android/Utils/Spr/SprEngine.PickChars.cs b/src/Kp2aBusinessLogic/Utils/Spr/SprEngine.PickChars.cs similarity index 100% rename from src/keepass2android/Utils/Spr/SprEngine.PickChars.cs rename to src/Kp2aBusinessLogic/Utils/Spr/SprEngine.PickChars.cs diff --git a/src/keepass2android/Utils/Spr/SprEngine.cs b/src/Kp2aBusinessLogic/Utils/Spr/SprEngine.cs similarity index 98% rename from src/keepass2android/Utils/Spr/SprEngine.cs rename to src/Kp2aBusinessLogic/Utils/Spr/SprEngine.cs index 198b4518..854b520f 100644 --- a/src/keepass2android/Utils/Spr/SprEngine.cs +++ b/src/Kp2aBusinessLogic/Utils/Spr/SprEngine.cs @@ -592,16 +592,6 @@ namespace KeePass.Util.Spr return (strText.IndexOf('{') >= 0); } - internal static string DerefFn(string str, PwEntry pe) - { - if(!MightDeref(str)) return str; - - SprContext ctx = new SprContext(pe, - App.Kp2a.GetDb().KpDatabase, - SprCompileFlags.Deref); - // ctx.ForcePlainTextPasswords = false; - - return Compile(str, ctx); - } + } } diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/Buffer.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/Buffer.java new file mode 100644 index 00000000..4dbb64b7 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/Buffer.java @@ -0,0 +1,294 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public class Buffer{ + final byte[] tmp=new byte[4]; + byte[] buffer; + int index; + int s; + public Buffer(int size){ + buffer=new byte[size]; + index=0; + s=0; + } + public Buffer(byte[] buffer){ + this.buffer=buffer; + index=0; + s=0; + } + public Buffer(){ this(1024*10*2); } + public void putByte(byte foo){ + buffer[index++]=foo; + } + public void putByte(byte[] foo) { + putByte(foo, 0, foo.length); + } + public void putByte(byte[] foo, int begin, int length) { + System.arraycopy(foo, begin, buffer, index, length); + index+=length; + } + public void putString(byte[] foo){ + putString(foo, 0, foo.length); + } + public void putString(byte[] foo, int begin, int length) { + putInt(length); + putByte(foo, begin, length); + } + public void putInt(int val) { + tmp[0]=(byte)(val >>> 24); + tmp[1]=(byte)(val >>> 16); + tmp[2]=(byte)(val >>> 8); + tmp[3]=(byte)(val); + System.arraycopy(tmp, 0, buffer, index, 4); + index+=4; + } + public void putLong(long val) { + tmp[0]=(byte)(val >>> 56); + tmp[1]=(byte)(val >>> 48); + tmp[2]=(byte)(val >>> 40); + tmp[3]=(byte)(val >>> 32); + System.arraycopy(tmp, 0, buffer, index, 4); + tmp[0]=(byte)(val >>> 24); + tmp[1]=(byte)(val >>> 16); + tmp[2]=(byte)(val >>> 8); + tmp[3]=(byte)(val); + System.arraycopy(tmp, 0, buffer, index+4, 4); + index+=8; + } + void skip(int n) { + index+=n; + } + void putPad(int n) { + while(n>0){ + buffer[index++]=(byte)0; + n--; + } + } + public void putMPInt(byte[] foo){ + int i=foo.length; + if((foo[0]&0x80)!=0){ + i++; + putInt(i); + putByte((byte)0); + } + else{ + putInt(i); + } + putByte(foo); + } + public int getLength(){ + return index-s; + } + public int getOffSet(){ + return s; + } + public void setOffSet(int s){ + this.s=s; + } + public long getLong(){ + long foo = getInt()&0xffffffffL; + foo = ((foo<<32)) | (getInt()&0xffffffffL); + return foo; + } + public int getInt(){ + int foo = getShort(); + foo = ((foo<<16)&0xffff0000) | (getShort()&0xffff); + return foo; + } + public long getUInt(){ + long foo = 0L; + long bar = 0L; + foo = getByte(); + foo = ((foo<<8)&0xff00)|(getByte()&0xff); + bar = getByte(); + bar = ((bar<<8)&0xff00)|(getByte()&0xff); + foo = ((foo<<16)&0xffff0000) | (bar&0xffff); + return foo; + } + int getShort() { + int foo = getByte(); + foo = ((foo<<8)&0xff00)|(getByte()&0xff); + return foo; + } + public int getByte() { + return (buffer[s++]&0xff); + } + public void getByte(byte[] foo) { + getByte(foo, 0, foo.length); + } + void getByte(byte[] foo, int start, int len) { + System.arraycopy(buffer, s, foo, start, len); + s+=len; + } + public int getByte(int len) { + int foo=s; + s+=len; + return foo; + } + public byte[] getMPInt() { + int i=getInt(); // uint32 + if(i<0 || // bigger than 0x7fffffff + i>8*1024){ + // TODO: an exception should be thrown. + i = 8*1024; // the session will be broken, but working around OOME. + } + byte[] foo=new byte[i]; + getByte(foo, 0, i); + return foo; + } + public byte[] getMPIntBits() { + int bits=getInt(); + int bytes=(bits+7)/8; + byte[] foo=new byte[bytes]; + getByte(foo, 0, bytes); + if((foo[0]&0x80)!=0){ + byte[] bar=new byte[foo.length+1]; + bar[0]=0; // ?? + System.arraycopy(foo, 0, bar, 1, foo.length); + foo=bar; + } + return foo; + } + public byte[] getString() { + int i = getInt(); // uint32 + if(i<0 || // bigger than 0x7fffffff + i>256*1024){ + // TODO: an exception should be thrown. + i = 256*1024; // the session will be broken, but working around OOME. + } + byte[] foo=new byte[i]; + getByte(foo, 0, i); + return foo; + } + byte[] getString(int[]start, int[]len) { + int i=getInt(); + start[0]=getByte(i); + len[0]=i; + return buffer; + } + public void reset(){ + index=0; + s=0; + } + public void shift(){ + if(s==0)return; + System.arraycopy(buffer, s, buffer, 0, index-s); + index=index-s; + s=0; + } + void rewind(){ + s=0; + } + + byte getCommand(){ + return buffer[5]; + } + + void checkFreeSize(int n){ + if(buffer.length>>4)&0xf]); + System.err.print(chars[foo&0xf]); + if(i%16==15){ + System.err.println(""); + continue; + } + if(i>0 && i%2==1){ + System.err.print(" "); + } + } + System.err.println(""); + } + static void dump(byte[] b){ + dump(b, 0, b.length); + } + static void dump(byte[] b, int s, int l){ + for(int i=s; i0) + notifyAll(); + } + int getRecipient(){ + return recipient; + } + + void init() throws JSchException { + } + + public void connect() throws JSchException{ + connect(0); + } + + public void connect(int connectTimeout) throws JSchException{ + this.connectTimeout=connectTimeout; + try{ + sendChannelOpen(); + start(); + } + catch(Exception e){ + connected=false; + disconnect(); + if(e instanceof JSchException) + throw (JSchException)e; + throw new JSchException(e.toString(), e); + } + } + + public void setXForwarding(boolean foo){ + } + + public void start() throws JSchException{} + + public boolean isEOF() {return eof_remote;} + + void getData(Buffer buf){ + setRecipient(buf.getInt()); + setRemoteWindowSize(buf.getUInt()); + setRemotePacketSize(buf.getInt()); + } + + public void setInputStream(InputStream in){ + io.setInputStream(in, false); + } + public void setInputStream(InputStream in, boolean dontclose){ + io.setInputStream(in, dontclose); + } + public void setOutputStream(OutputStream out){ + io.setOutputStream(out, false); + } + public void setOutputStream(OutputStream out, boolean dontclose){ + io.setOutputStream(out, dontclose); + } + public void setExtOutputStream(OutputStream out){ + io.setExtOutputStream(out, false); + } + public void setExtOutputStream(OutputStream out, boolean dontclose){ + io.setExtOutputStream(out, dontclose); + } + public InputStream getInputStream() throws IOException { + PipedInputStream in= + new MyPipedInputStream( + 32*1024 // this value should be customizable. + ); + io.setOutputStream(new PassiveOutputStream(in), false); + return in; + } + public InputStream getExtInputStream() throws IOException { + PipedInputStream in= + new MyPipedInputStream( + 32*1024 // this value should be customizable. + ); + io.setExtOutputStream(new PassiveOutputStream(in), false); + return in; + } + public OutputStream getOutputStream() throws IOException { + /* + PipedOutputStream out=new PipedOutputStream(); + io.setInputStream(new PassiveInputStream(out + , 32*1024 + ), false); + return out; + */ + + final Channel channel=this; + OutputStream out=new OutputStream(){ + private int dataLen=0; + private Buffer buffer=null; + private Packet packet=null; + private boolean closed=false; + private synchronized void init() throws java.io.IOException{ + buffer=new Buffer(rmpsize); + packet=new Packet(buffer); + + byte[] _buf=buffer.buffer; + if(_buf.length-(14+0)-Session.buffer_margin<=0){ + buffer=null; + packet=null; + throw new IOException("failed to initialize the channel."); + } + + } + byte[] b=new byte[1]; + public void write(int w) throws java.io.IOException{ + b[0]=(byte)w; + write(b, 0, 1); + } + public void write(byte[] buf, int s, int l) throws java.io.IOException{ + if(packet==null){ + init(); + } + + if(closed){ + throw new java.io.IOException("Already closed"); + } + + byte[] _buf=buffer.buffer; + int _bufl=_buf.length; + while(l>0){ + int _l=l; + if(l>_bufl-(14+dataLen)-Session.buffer_margin){ + _l=_bufl-(14+dataLen)-Session.buffer_margin; + } + + if(_l<=0){ + flush(); + continue; + } + + System.arraycopy(buf, s, _buf, 14+dataLen, _l); + dataLen+=_l; + s+=_l; + l-=_l; + } + } + + public void flush() throws java.io.IOException{ + if(closed){ + throw new java.io.IOException("Already closed"); + } + if(dataLen==0) + return; + packet.reset(); + buffer.putByte((byte)Session.SSH_MSG_CHANNEL_DATA); + buffer.putInt(recipient); + buffer.putInt(dataLen); + buffer.skip(dataLen); + try{ + int foo=dataLen; + dataLen=0; + synchronized(channel){ + if(!channel.close) + getSession().write(packet, channel, foo); + } + } + catch(Exception e){ + close(); + throw new java.io.IOException(e.toString()); + } + + } + public void close() throws java.io.IOException{ + if(packet==null){ + try{ + init(); + } + catch(java.io.IOException e){ + // close should be finished silently. + return; + } + } + if(closed){ + return; + } + if(dataLen>0){ + flush(); + } + channel.eof(); + closed=true; + } + }; + return out; + } + + class MyPipedInputStream extends PipedInputStream{ + MyPipedInputStream() throws IOException{ super(); } + MyPipedInputStream(int size) throws IOException{ + super(); + buffer=new byte[size]; + } + MyPipedInputStream(PipedOutputStream out) throws IOException{ super(out); } + MyPipedInputStream(PipedOutputStream out, int size) throws IOException{ + super(out); + buffer=new byte[size]; + } + + /* + * TODO: We should have our own Piped[I/O]Stream implementation. + * Before accepting data, JDK's PipedInputStream will check the existence of + * reader thread, and if it is not alive, the stream will be closed. + * That behavior may cause the problem if multiple threads make access to it. + */ + public synchronized void updateReadSide() throws IOException { + if(available() != 0){ // not empty + return; + } + in = 0; + out = 0; + buffer[in++] = 0; + read(); + } + } + void setLocalWindowSizeMax(int foo){ this.lwsize_max=foo; } + void setLocalWindowSize(int foo){ this.lwsize=foo; } + void setLocalPacketSize(int foo){ this.lmpsize=foo; } + synchronized void setRemoteWindowSize(long foo){ this.rwsize=foo; } + synchronized void addRemoteWindowSize(int foo){ + this.rwsize+=foo; + if(notifyme>0) + notifyAll(); + } + void setRemotePacketSize(int foo){ this.rmpsize=foo; } + + public void run(){ + } + + void write(byte[] foo) throws IOException { + write(foo, 0, foo.length); + } + void write(byte[] foo, int s, int l) throws IOException { + try{ + io.put(foo, s, l); + }catch(NullPointerException e){} + } + void write_ext(byte[] foo, int s, int l) throws IOException { + try{ + io.put_ext(foo, s, l); + }catch(NullPointerException e){} + } + + void eof_remote(){ + eof_remote=true; + try{ + io.out_close(); + } + catch(NullPointerException e){} + } + + void eof(){ + if(eof_local)return; + eof_local=true; + + try{ + Buffer buf=new Buffer(100); + Packet packet=new Packet(buf); + packet.reset(); + buf.putByte((byte)Session.SSH_MSG_CHANNEL_EOF); + buf.putInt(getRecipient()); + synchronized(this){ + if(!close) + getSession().write(packet); + } + } + catch(Exception e){ + //System.err.println("Channel.eof"); + //e.printStackTrace(); + } + /* + if(!isConnected()){ disconnect(); } + */ + } + + /* + http://www1.ietf.org/internet-drafts/draft-ietf-secsh-connect-24.txt + +5.3 Closing a Channel + When a party will no longer send more data to a channel, it SHOULD + send SSH_MSG_CHANNEL_EOF. + + byte SSH_MSG_CHANNEL_EOF + uint32 recipient_channel + + No explicit response is sent to this message. However, the + application may send EOF to whatever is at the other end of the + channel. Note that the channel remains open after this message, and + more data may still be sent in the other direction. This message + does not consume window space and can be sent even if no window space + is available. + + When either party wishes to terminate the channel, it sends + SSH_MSG_CHANNEL_CLOSE. Upon receiving this message, a party MUST + send back a SSH_MSG_CHANNEL_CLOSE unless it has already sent this + message for the channel. The channel is considered closed for a + party when it has both sent and received SSH_MSG_CHANNEL_CLOSE, and + the party may then reuse the channel number. A party MAY send + SSH_MSG_CHANNEL_CLOSE without having sent or received + SSH_MSG_CHANNEL_EOF. + + byte SSH_MSG_CHANNEL_CLOSE + uint32 recipient_channel + + This message does not consume window space and can be sent even if no + window space is available. + + It is recommended that any data sent before this message is delivered + to the actual destination, if possible. + */ + + void close(){ + if(close)return; + close=true; + eof_local=eof_remote=true; + + try{ + Buffer buf=new Buffer(100); + Packet packet=new Packet(buf); + packet.reset(); + buf.putByte((byte)Session.SSH_MSG_CHANNEL_CLOSE); + buf.putInt(getRecipient()); + synchronized(this){ + getSession().write(packet); + } + } + catch(Exception e){ + //e.printStackTrace(); + } + } + public boolean isClosed(){ + return close; + } + static void disconnect(Session session){ + Channel[] channels=null; + int count=0; + synchronized(pool){ + channels=new Channel[pool.size()]; + for(int i=0; i0){ + if(timeout>0L){ + if((System.currentTimeMillis()-start)>timeout){ + retry=0; + continue; + } + } + try{ + long t = timeout==0L ? 5000L : timeout; + this.notifyme=1; + wait(t); + } + catch(java.lang.InterruptedException e){ + } + finally{ + this.notifyme=0; + } + retry--; + } + } + if(!_session.isConnected()){ + throw new JSchException("session is down"); + } + if(this.getRecipient()==-1){ // timeout + throw new JSchException("channel is not opened."); + } + if(this.open_confirmation==false){ // SSH_MSG_CHANNEL_OPEN_FAILURE + throw new JSchException("channel is not opened."); + } + connected=true; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelAgentForwarding.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelAgentForwarding.java new file mode 100644 index 00000000..6a77c374 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelAgentForwarding.java @@ -0,0 +1,266 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.net.*; +import java.util.Vector; + +class ChannelAgentForwarding extends Channel{ + + static private final int LOCAL_WINDOW_SIZE_MAX=0x20000; + static private final int LOCAL_MAXIMUM_PACKET_SIZE=0x4000; + + private final byte SSH_AGENTC_REQUEST_RSA_IDENTITIES = 1; + private final byte SSH_AGENT_RSA_IDENTITIES_ANSWER = 2; + private final byte SSH_AGENTC_RSA_CHALLENGE = 3; + private final byte SSH_AGENT_RSA_RESPONSE = 4; + private final byte SSH_AGENT_FAILURE = 5; + private final byte SSH_AGENT_SUCCESS = 6; + private final byte SSH_AGENTC_ADD_RSA_IDENTITY = 7; + private final byte SSH_AGENTC_REMOVE_RSA_IDENTITY = 8; + private final byte SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES = 9; + + private final byte SSH2_AGENTC_REQUEST_IDENTITIES=11; + private final byte SSH2_AGENT_IDENTITIES_ANSWER=12; + private final byte SSH2_AGENTC_SIGN_REQUEST=13; + private final byte SSH2_AGENT_SIGN_RESPONSE=14; + private final byte SSH2_AGENTC_ADD_IDENTITY=17; + private final byte SSH2_AGENTC_REMOVE_IDENTITY=18; + private final byte SSH2_AGENTC_REMOVE_ALL_IDENTITIES=19; + private final byte SSH2_AGENT_FAILURE=30; + + boolean init=true; + + private Buffer rbuf=null; + private Buffer wbuf=null; + private Packet packet=null; + private Buffer mbuf=null; + + ChannelAgentForwarding(){ + super(); + + setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX); + setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX); + setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE); + + type=Util.str2byte("auth-agent@openssh.com"); + rbuf=new Buffer(); + rbuf.reset(); + //wbuf=new Buffer(rmpsize); + //packet=new Packet(wbuf); + mbuf=new Buffer(); + connected=true; + } + + public void run(){ + try{ + sendOpenConfirmation(); + } + catch(Exception e){ + close=true; + disconnect(); + } + } + + void write(byte[] foo, int s, int l) throws java.io.IOException { + + if(packet==null){ + wbuf=new Buffer(rmpsize); + packet=new Packet(wbuf); + } + + rbuf.shift(); + if(rbuf.buffer.lengthrbuf.getLength()){ + rbuf.s-=4; + return; + } + + int typ=rbuf.getByte(); + + Session _session=null; + try{ + _session=getSession(); + } + catch(JSchException e){ + throw new java.io.IOException(e.toString()); + } + + IdentityRepository irepo = _session.getIdentityRepository(); + UserInfo userinfo=_session.getUserInfo(); + + mbuf.reset(); + + if(typ==SSH2_AGENTC_REQUEST_IDENTITIES){ + mbuf.putByte(SSH2_AGENT_IDENTITIES_ANSWER); + Vector identities = irepo.getIdentities(); + synchronized(identities){ + int count=0; + for(int i=0; iname and value are needed to be passed + * to the remote in your favorite encoding, + * use {@link #setEnv(byte[], byte[])}. + * Refer to RFC4254 6.4 Environment Variable Passing. + * + * @param name A name for environment variable. + * @param value A value for environment variable. + */ + public void setEnv(String name, String value){ + setEnv(Util.str2byte(name), Util.str2byte(value)); + } + + /** + * Set the environment variable. + * Refer to RFC4254 6.4 Environment Variable Passing. + * + * @param name A name of environment variable. + * @param value A value of environment variable. + * @see #setEnv(String, String) + */ + public void setEnv(byte[] name, byte[] value){ + synchronized(this){ + getEnv().put(name, value); + } + } + + private Hashtable getEnv(){ + if(env==null) + env=new Hashtable(); + return env; + } + + /** + * Allocate a Pseudo-Terminal. + * Refer to RFC4254 6.2. Requesting a Pseudo-Terminal. + * + * @param enable + */ + public void setPty(boolean enable){ + pty=enable; + } + + /** + * Set the terminal mode. + * + * @param terminal_mode + */ + public void setTerminalMode(byte[] terminal_mode){ + this.terminal_mode=terminal_mode; + } + + /** + * Change the window dimension interactively. + * Refer to RFC4254 6.7. Window Dimension Change Message. + * + * @param col terminal width, columns + * @param row terminal height, rows + * @param wp terminal width, pixels + * @param hp terminal height, pixels + */ + public void setPtySize(int col, int row, int wp, int hp){ + setPtyType(this.ttype, col, row, wp, hp); + if(!pty || !isConnected()){ + return; + } + try{ + RequestWindowChange request=new RequestWindowChange(); + request.setSize(col, row, wp, hp); + request.request(getSession(), this); + } + catch(Exception e){ + //System.err.println("ChannelSessio.setPtySize: "+e); + } + } + + /** + * Set the terminal type. + * This method is not effective after Channel#connect(). + * + * @param ttype terminal type(for example, "vt100") + * @see #setPtyType(String, int, int, int, int) + */ + public void setPtyType(String ttype){ + setPtyType(ttype, 80, 24, 640, 480); + } + + /** + * Set the terminal type. + * This method is not effective after Channel#connect(). + * + * @param ttype terminal type(for example, "vt100") + * @param col terminal width, columns + * @param row terminal height, rows + * @param wp terminal width, pixels + * @param hp terminal height, pixels + */ + public void setPtyType(String ttype, int col, int row, int wp, int hp){ + this.ttype=ttype; + this.tcol=col; + this.trow=row; + this.twp=wp; + this.thp=hp; + } + + protected void sendRequests() throws Exception{ + Session _session=getSession(); + Request request; + if(agent_forwarding){ + request=new RequestAgentForwarding(); + request.request(_session, this); + } + + if(xforwading){ + request=new RequestX11(); + request.request(_session, this); + } + + if(pty){ + request=new RequestPtyReq(); + ((RequestPtyReq)request).setTType(ttype); + ((RequestPtyReq)request).setTSize(tcol, trow, twp, thp); + if(terminal_mode!=null){ + ((RequestPtyReq)request).setTerminalMode(terminal_mode); + } + request.request(_session, this); + } + + if(env!=null){ + for(Enumeration _env=env.keys(); _env.hasMoreElements();){ + Object name=_env.nextElement(); + Object value=env.get(name); + request=new RequestEnv(); + ((RequestEnv)request).setEnv(toByteArray(name), + toByteArray(value)); + request.request(_session, this); + } + } + } + + private byte[] toByteArray(Object o){ + if(o instanceof String){ + return Util.str2byte((String)o); + } + return (byte[])o; + } + + public void run(){ + //System.err.println(this+":run >"); + + Buffer buf=new Buffer(rmpsize); + Packet packet=new Packet(buf); + int i=-1; + try{ + while(isConnected() && + thread!=null && + io!=null && + io.in!=null){ + i=io.in.read(buf.buffer, + 14, + buf.buffer.length-14 + -Session.buffer_margin + ); + if(i==0)continue; + if(i==-1){ + eof(); + break; + } + if(close)break; + //System.out.println("write: "+i); + packet.reset(); + buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA); + buf.putInt(recipient); + buf.putInt(i); + buf.skip(i); + getSession().write(packet, this, i); + } + } + catch(Exception e){ + //System.err.println("# ChannelExec.run"); + //e.printStackTrace(); + } + Thread _thread=thread; + if(_thread!=null){ + synchronized(_thread){ _thread.notifyAll(); } + } + thread=null; + //System.err.println(this+":run <"); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelSftp.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelSftp.java new file mode 100644 index 00000000..fca709c7 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelSftp.java @@ -0,0 +1,3015 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.io.*; + +import java.util.Vector; + +public class ChannelSftp extends ChannelSession{ + + static private final int LOCAL_MAXIMUM_PACKET_SIZE=32*1024; + static private final int LOCAL_WINDOW_SIZE_MAX=(64*LOCAL_MAXIMUM_PACKET_SIZE); + + private static final byte SSH_FXP_INIT= 1; + private static final byte SSH_FXP_VERSION= 2; + private static final byte SSH_FXP_OPEN= 3; + private static final byte SSH_FXP_CLOSE= 4; + private static final byte SSH_FXP_READ= 5; + private static final byte SSH_FXP_WRITE= 6; + private static final byte SSH_FXP_LSTAT= 7; + private static final byte SSH_FXP_FSTAT= 8; + private static final byte SSH_FXP_SETSTAT= 9; + private static final byte SSH_FXP_FSETSTAT= 10; + private static final byte SSH_FXP_OPENDIR= 11; + private static final byte SSH_FXP_READDIR= 12; + private static final byte SSH_FXP_REMOVE= 13; + private static final byte SSH_FXP_MKDIR= 14; + private static final byte SSH_FXP_RMDIR= 15; + private static final byte SSH_FXP_REALPATH= 16; + private static final byte SSH_FXP_STAT= 17; + private static final byte SSH_FXP_RENAME= 18; + private static final byte SSH_FXP_READLINK= 19; + private static final byte SSH_FXP_SYMLINK= 20; + private static final byte SSH_FXP_STATUS= 101; + private static final byte SSH_FXP_HANDLE= 102; + private static final byte SSH_FXP_DATA= 103; + private static final byte SSH_FXP_NAME= 104; + private static final byte SSH_FXP_ATTRS= 105; + private static final byte SSH_FXP_EXTENDED= (byte)200; + private static final byte SSH_FXP_EXTENDED_REPLY= (byte)201; + + // pflags + private static final int SSH_FXF_READ= 0x00000001; + private static final int SSH_FXF_WRITE= 0x00000002; + private static final int SSH_FXF_APPEND= 0x00000004; + private static final int SSH_FXF_CREAT= 0x00000008; + private static final int SSH_FXF_TRUNC= 0x00000010; + private static final int SSH_FXF_EXCL= 0x00000020; + + private static final int SSH_FILEXFER_ATTR_SIZE= 0x00000001; + private static final int SSH_FILEXFER_ATTR_UIDGID= 0x00000002; + private static final int SSH_FILEXFER_ATTR_PERMISSIONS= 0x00000004; + private static final int SSH_FILEXFER_ATTR_ACMODTIME= 0x00000008; + private static final int SSH_FILEXFER_ATTR_EXTENDED= 0x80000000; + + public static final int SSH_FX_OK= 0; + public static final int SSH_FX_EOF= 1; + public static final int SSH_FX_NO_SUCH_FILE= 2; + public static final int SSH_FX_PERMISSION_DENIED= 3; + public static final int SSH_FX_FAILURE= 4; + public static final int SSH_FX_BAD_MESSAGE= 5; + public static final int SSH_FX_NO_CONNECTION= 6; + public static final int SSH_FX_CONNECTION_LOST= 7; + public static final int SSH_FX_OP_UNSUPPORTED= 8; +/* + SSH_FX_OK + Indicates successful completion of the operation. + SSH_FX_EOF + indicates end-of-file condition; for SSH_FX_READ it means that no + more data is available in the file, and for SSH_FX_READDIR it + indicates that no more files are contained in the directory. + SSH_FX_NO_SUCH_FILE + is returned when a reference is made to a file which should exist + but doesn't. + SSH_FX_PERMISSION_DENIED + is returned when the authenticated user does not have sufficient + permissions to perform the operation. + SSH_FX_FAILURE + is a generic catch-all error message; it should be returned if an + error occurs for which there is no more specific error code + defined. + SSH_FX_BAD_MESSAGE + may be returned if a badly formatted packet or protocol + incompatibility is detected. + SSH_FX_NO_CONNECTION + is a pseudo-error which indicates that the client has no + connection to the server (it can only be generated locally by the + client, and MUST NOT be returned by servers). + SSH_FX_CONNECTION_LOST + is a pseudo-error which indicates that the connection to the + server has been lost (it can only be generated locally by the + client, and MUST NOT be returned by servers). + SSH_FX_OP_UNSUPPORTED + indicates that an attempt was made to perform an operation which + is not supported for the server (it may be generated locally by + the client if e.g. the version number exchange indicates that a + required feature is not supported by the server, or it may be + returned by the server if the server does not implement an + operation). +*/ + private static final int MAX_MSG_LENGTH = 256* 1024; + + public static final int OVERWRITE=0; + public static final int RESUME=1; + public static final int APPEND=2; + + private boolean interactive=false; + private int seq=1; + private int[] ackid=new int[1]; + + private Buffer buf; + private Packet packet; + + // The followings will be used in file uploading. + private Buffer obuf; + private Packet opacket; + + private int client_version=3; + private int server_version=3; + private String version=String.valueOf(client_version); + + private java.util.Hashtable extensions=null; + private InputStream io_in=null; + + private boolean extension_posix_rename = false; + private boolean extension_statvfs = false; + // private boolean extension_fstatvfs = false; + private boolean extension_hardlink = false; + +/* +10. Changes from previous protocol versions + The SSH File Transfer Protocol has changed over time, before it's + standardization. The following is a description of the incompatible + changes between different versions. +10.1 Changes between versions 3 and 2 + o The SSH_FXP_READLINK and SSH_FXP_SYMLINK messages were added. + o The SSH_FXP_EXTENDED and SSH_FXP_EXTENDED_REPLY messages were added. + o The SSH_FXP_STATUS message was changed to include fields `error + message' and `language tag'. +10.2 Changes between versions 2 and 1 + o The SSH_FXP_RENAME message was added. +10.3 Changes between versions 1 and 0 + o Implementation changes, no actual protocol changes. +*/ + + private static final String file_separator=java.io.File.separator; + private static final char file_separatorc=java.io.File.separatorChar; + private static boolean fs_is_bs=(byte)java.io.File.separatorChar == '\\'; + + private String cwd; + private String home; + private String lcwd; + + private static final String UTF8="UTF-8"; + private String fEncoding=UTF8; + private boolean fEncoding_is_utf8=true; + + private RequestQueue rq = new RequestQueue(16); + + /** + * Specify how many requests may be sent at any one time. + * Increasing this value may slightly improve file transfer speed but will + * increase memory usage. The default is 16 requests. + * + * @param bulk_requests how many requests may be outstanding at any one time. + */ + public void setBulkRequests(int bulk_requests) throws JSchException { + if(bulk_requests>0) + rq = new RequestQueue(bulk_requests); + else + throw new JSchException("setBulkRequests: "+ + bulk_requests+" must be greater than 0."); + } + + /** + * This method will return the value how many requests may be + * sent at any one time. + * + * @return how many requests may be sent at any one time. + */ + public int getBulkRequests(){ + return rq.size(); + } + + public ChannelSftp(){ + super(); + setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX); + setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX); + setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE); + } + + void init(){ + } + + public void start() throws JSchException{ + try{ + + PipedOutputStream pos=new PipedOutputStream(); + io.setOutputStream(pos); + PipedInputStream pis=new MyPipedInputStream(pos, rmpsize); + io.setInputStream(pis); + + io_in=io.in; + + if(io_in==null){ + throw new JSchException("channel is down"); + } + + Request request=new RequestSftp(); + request.request(getSession(), this); + + /* + System.err.println("lmpsize: "+lmpsize); + System.err.println("lwsize: "+lwsize); + System.err.println("rmpsize: "+rmpsize); + System.err.println("rwsize: "+rwsize); + */ + + buf=new Buffer(lmpsize); + packet=new Packet(buf); + + obuf=new Buffer(rmpsize); + opacket=new Packet(obuf); + + int i=0; + int length; + int type; + byte[] str; + + // send SSH_FXP_INIT + sendINIT(); + + // receive SSH_FXP_VERSION + Header header=new Header(); + header=header(buf, header); + length=header.length; + if(length > MAX_MSG_LENGTH){ + throw new SftpException(SSH_FX_FAILURE, + "Received message is too long: " + length); + } + type=header.type; // 2 -> SSH_FXP_VERSION + server_version=header.rid; + //System.err.println("SFTP protocol server-version="+server_version); + extensions=new java.util.Hashtable(); + if(length>0){ + // extension data + fill(buf, length); + byte[] extension_name=null; + byte[] extension_data=null; + while(length>0){ + extension_name=buf.getString(); + length-=(4+extension_name.length); + extension_data=buf.getString(); + length-=(4+extension_data.length); + extensions.put(Util.byte2str(extension_name), + Util.byte2str(extension_data)); + } + } + + if(extensions.get("posix-rename@openssh.com")!=null && + extensions.get("posix-rename@openssh.com").equals("1")){ + extension_posix_rename = true; + } + + if(extensions.get("statvfs@openssh.com")!=null && + extensions.get("statvfs@openssh.com").equals("2")){ + extension_statvfs = true; + } + + /* + if(extensions.get("fstatvfs@openssh.com")!=null && + extensions.get("fstatvfs@openssh.com").equals("2")){ + extension_fstatvfs = true; + } + */ + + if(extensions.get("hardlink@openssh.com")!=null && + extensions.get("hardlink@openssh.com").equals("1")){ + extension_hardlink = true; + } + + lcwd=new File(".").getCanonicalPath(); + } + catch(Exception e){ + //System.err.println(e); + if(e instanceof JSchException) throw (JSchException)e; + if(e instanceof Throwable) + throw new JSchException(e.toString(), (Throwable)e); + throw new JSchException(e.toString()); + } + } + + public void quit(){ disconnect();} + public void exit(){ disconnect();} + public void lcd(String path) throws SftpException{ + path=localAbsolutePath(path); + if((new File(path)).isDirectory()){ + try{ + path=(new File(path)).getCanonicalPath(); + } + catch(Exception e){} + lcwd=path; + return; + } + throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such directory"); + } + + public void cd(String path) throws SftpException{ + try{ + ((MyPipedInputStream)io_in).updateReadSide(); + + path=remoteAbsolutePath(path); + path=isUnique(path); + + byte[] str=_realpath(path); + SftpATTRS attr=_stat(str); + + if((attr.getFlags()&SftpATTRS.SSH_FILEXFER_ATTR_PERMISSIONS)==0){ + throw new SftpException(SSH_FX_FAILURE, + "Can't change directory: "+path); + } + if(!attr.isDir()){ + throw new SftpException(SSH_FX_FAILURE, + "Can't change directory: "+path); + } + + setCwd(Util.byte2str(str, fEncoding)); + } + catch(Exception e){ + if(e instanceof SftpException) throw (SftpException)e; + if(e instanceof Throwable) + throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e); + throw new SftpException(SSH_FX_FAILURE, ""); + } + } + + public void put(String src, String dst) throws SftpException{ + put(src, dst, null, OVERWRITE); + } + public void put(String src, String dst, int mode) throws SftpException{ + put(src, dst, null, mode); + } + public void put(String src, String dst, + SftpProgressMonitor monitor) throws SftpException{ + put(src, dst, monitor, OVERWRITE); + } + + /** + * Sends data from src file to dst file. + * The mode should be OVERWRITE, + * RESUME or APPEND. + * + * @param src source file + * @param dst destination file + * @param monitor progress monitor + * @param mode how data should be added to dst + */ + public void put(String src, String dst, + SftpProgressMonitor monitor, int mode) throws SftpException{ + + try{ + ((MyPipedInputStream)io_in).updateReadSide(); + + src=localAbsolutePath(src); + dst=remoteAbsolutePath(dst); + + Vector v=glob_remote(dst); + int vsize=v.size(); + if(vsize!=1){ + if(vsize==0){ + if(isPattern(dst)) + throw new SftpException(SSH_FX_FAILURE, dst); + else + dst=Util.unquote(dst); + } + throw new SftpException(SSH_FX_FAILURE, v.toString()); + } + else{ + dst=(String)(v.elementAt(0)); + } + + boolean isRemoteDir=isRemoteDir(dst); + + v=glob_local(src); + vsize=v.size(); + + StringBuffer dstsb=null; + if(isRemoteDir){ + if(!dst.endsWith("/")){ + dst+="/"; + } + dstsb=new StringBuffer(dst); + } + else if(vsize>1){ + throw new SftpException(SSH_FX_FAILURE, + "Copying multiple files, but the destination is missing or a file."); + } + + for(int j=0; ji) + i=ii; + } + if(i==-1) dstsb.append(_src); + else dstsb.append(_src.substring(i + 1)); + _dst=dstsb.toString(); + dstsb.delete(dst.length(), _dst.length()); + } + else{ + _dst=dst; + } + //System.err.println("_dst "+_dst); + + long size_of_dst=0; + if(mode==RESUME){ + try{ + SftpATTRS attr=_stat(_dst); + size_of_dst=attr.getSize(); + } + catch(Exception eee){ + //System.err.println(eee); + } + long size_of_src=new File(_src).length(); + if(size_of_srcsrc to dst file. + * The mode should be OVERWRITE, + * RESUME or APPEND. + * + * @param src input stream + * @param dst destination file + * @param monitor progress monitor + * @param mode how data should be added to dst + */ + public void put(InputStream src, String dst, + SftpProgressMonitor monitor, int mode) throws SftpException{ + try{ + ((MyPipedInputStream)io_in).updateReadSide(); + + dst=remoteAbsolutePath(dst); + + Vector v=glob_remote(dst); + int vsize=v.size(); + if(vsize!=1){ + if(vsize==0){ + if(isPattern(dst)) + throw new SftpException(SSH_FX_FAILURE, dst); + else + dst=Util.unquote(dst); + } + throw new SftpException(SSH_FX_FAILURE, v.toString()); + } + else{ + dst=(String)(v.elementAt(0)); + } + + if(monitor!=null){ + monitor.init(SftpProgressMonitor.PUT, + "-", dst, + SftpProgressMonitor.UNKNOWN_SIZE); + } + + _put(src, dst, monitor, mode); + } + catch(Exception e){ + if(e instanceof SftpException) { + if(((SftpException)e).id == SSH_FX_FAILURE && + isRemoteDir(dst)) { + throw new SftpException(SSH_FX_FAILURE, dst+" is a directory"); + } + throw (SftpException)e; + } + if(e instanceof Throwable) + throw new SftpException(SSH_FX_FAILURE, e.toString(), (Throwable)e); + throw new SftpException(SSH_FX_FAILURE, e.toString()); + } + } + + public void _put(InputStream src, String dst, + SftpProgressMonitor monitor, int mode) throws SftpException{ + try{ + ((MyPipedInputStream)io_in).updateReadSide(); + + byte[] dstb=Util.str2byte(dst, fEncoding); + long skip=0; + if(mode==RESUME || mode==APPEND){ + try{ + SftpATTRS attr=_stat(dstb); + skip=attr.getSize(); + } + catch(Exception eee){ + //System.err.println(eee); + } + } + if(mode==RESUME && skip>0){ + long skipped=src.skip(skip); + if(skipped0){ + int sent=sendWRITE(handle, _offset[0], d, s, _len); + writecount++; + _offset[0]+=sent; + s+=sent; + _len-=sent; + if((seq-1)==startid || + io_in.available()>=1024){ + while(io_in.available()>0){ + if(checkStatus(ackid, header)){ + _ackid=ackid[0]; + if(startid>_ackid || _ackid>seq-1){ + throw new SftpException(SSH_FX_FAILURE, ""); + } + ackcount++; + } + else{ + break; + } + } + } + } + if(monitor!=null && !monitor.count(len)){ + close(); + throw new IOException("canceled"); + } + } + catch(IOException e){ throw e; } + catch(Exception e){ throw new IOException(e.toString()); } + } + + byte[] _data=new byte[1]; + public void write(int foo) throws java.io.IOException{ + _data[0]=(byte)foo; + write(_data, 0, 1); + } + + public void flush() throws java.io.IOException{ + + if(isClosed){ + throw new IOException("stream already closed"); + } + + if(!init){ + try{ + while(writecount>ackcount){ + if(!checkStatus(null, header)){ + break; + } + ackcount++; + } + } + catch(SftpException e){ + throw new IOException(e.toString()); + } + } + } + + public void close() throws java.io.IOException{ + if(isClosed){ + return; + } + flush(); + if(monitor!=null)monitor.end(); + try{ _sendCLOSE(handle, header); } + catch(IOException e){ throw e; } + catch(Exception e){ + throw new IOException(e.toString()); + } + isClosed=true; + } + }; + return out; + } + catch(Exception e){ + if(e instanceof SftpException) throw (SftpException)e; + if(e instanceof Throwable) + throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e); + throw new SftpException(SSH_FX_FAILURE, ""); + } + } + + public void get(String src, String dst) throws SftpException{ + get(src, dst, null, OVERWRITE); + } + public void get(String src, String dst, + SftpProgressMonitor monitor) throws SftpException{ + get(src, dst, monitor, OVERWRITE); + } + public void get(String src, String dst, + SftpProgressMonitor monitor, int mode) throws SftpException{ + // System.out.println("get: "+src+" "+dst); + + boolean _dstExist = false; + String _dst=null; + try{ + ((MyPipedInputStream)io_in).updateReadSide(); + + src=remoteAbsolutePath(src); + dst=localAbsolutePath(dst); + + Vector v=glob_remote(src); + int vsize=v.size(); + if(vsize==0){ + throw new SftpException(SSH_FX_NO_SUCH_FILE, "No such file"); + } + + File dstFile=new File(dst); + boolean isDstDir=dstFile.isDirectory(); + StringBuffer dstsb=null; + if(isDstDir){ + if(!dst.endsWith(file_separator)){ + dst+=file_separator; + } + dstsb=new StringBuffer(dst); + } + else if(vsize>1){ + throw new SftpException(SSH_FX_FAILURE, + "Copying multiple files, but destination is missing or a file."); + } + + for(int j=0; jsize_of_src){ + throw new SftpException(SSH_FX_FAILURE, + "failed to resume for "+_dst); + } + if(size_of_dst==size_of_src){ + return; + } + } + + if(monitor!=null){ + monitor.init(SftpProgressMonitor.GET, _src, _dst, attr.getSize()); + if(mode==RESUME){ + monitor.count(_dstFile.length()); + } + } + + FileOutputStream fos=null; + _dstExist = _dstFile.exists(); + try{ + if(mode==OVERWRITE){ + fos=new FileOutputStream(_dst); + } + else{ + fos=new FileOutputStream(_dst, true); // append + } + // System.err.println("_get: "+_src+", "+_dst); + _get(_src, fos, monitor, mode, new File(_dst).length()); + } + finally{ + if(fos!=null){ + fos.close(); + } + } + } + } + catch(Exception e){ + if(!_dstExist && _dst!=null){ + File _dstFile = new File(_dst); + if(_dstFile.exists() && _dstFile.length()==0){ + _dstFile.delete(); + } + } + if(e instanceof SftpException) throw (SftpException)e; + if(e instanceof Throwable) + throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e); + throw new SftpException(SSH_FX_FAILURE, ""); + } + } + public void get(String src, OutputStream dst) throws SftpException{ + get(src, dst, null, OVERWRITE, 0); + } + public void get(String src, OutputStream dst, + SftpProgressMonitor monitor) throws SftpException{ + get(src, dst, monitor, OVERWRITE, 0); + } + public void get(String src, OutputStream dst, + SftpProgressMonitor monitor, int mode, long skip) throws SftpException{ +//System.err.println("get: "+src+", "+dst); + try{ + ((MyPipedInputStream)io_in).updateReadSide(); + + src=remoteAbsolutePath(src); + src=isUnique(src); + + if(monitor!=null){ + SftpATTRS attr=_stat(src); + monitor.init(SftpProgressMonitor.GET, src, "??", attr.getSize()); + if(mode==RESUME){ + monitor.count(skip); + } + } + _get(src, dst, monitor, mode, skip); + } + catch(Exception e){ + if(e instanceof SftpException) throw (SftpException)e; + if(e instanceof Throwable) + throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e); + throw new SftpException(SSH_FX_FAILURE, ""); + } + } + + private void _get(String src, OutputStream dst, + SftpProgressMonitor monitor, int mode, long skip) throws SftpException{ + //System.err.println("_get: "+src+", "+dst); + + byte[] srcb=Util.str2byte(src, fEncoding); + try{ + sendOPENR(srcb); + + Header header=new Header(); + header=header(buf, header); + int length=header.length; + int type=header.type; + + fill(buf, length); + + if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){ + throw new SftpException(SSH_FX_FAILURE, ""); + } + + if(type==SSH_FXP_STATUS){ + int i=buf.getInt(); + throwStatusError(buf, i); + } + + byte[] handle=buf.getString(); // filename + + long offset=0; + if(mode==RESUME){ + offset+=skip; + } + + int request_max=1; + rq.init(); + long request_offset=offset; + + int request_len = buf.buffer.length-13; + if(server_version==0){ request_len=1024; } + + loop: + while(true){ + + while(rq.count() < request_max){ + sendREAD(handle, request_offset, request_len, rq); + request_offset += request_len; + } + + header=header(buf, header); + length=header.length; + type=header.type; + + RequestQueue.Request rr = null; + try{ + rr = rq.get(header.rid); + } + catch(RequestQueue.OutOfOrderException e){ + request_offset = e.offset; + skip(header.length); + rq.cancel(header, buf); + continue; + } + + if(type==SSH_FXP_STATUS){ + fill(buf, length); + int i=buf.getInt(); + if(i==SSH_FX_EOF){ + break loop; + } + throwStatusError(buf, i); + } + + if(type!=SSH_FXP_DATA){ + break loop; + } + + buf.rewind(); + fill(buf.buffer, 0, 4); length-=4; + int length_of_data = buf.getInt(); // length of data + + /** + Since sftp protocol version 6, "end-of-file" has been defined, + + byte SSH_FXP_DATA + uint32 request-id + string data + bool end-of-file [optional] + + but some sftpd server will send such a field in the sftp protocol 3 ;-( + */ + int optional_data = length - length_of_data; + + int foo = length_of_data; + while(foo>0){ + int bar=foo; + if(bar>buf.buffer.length){ + bar=buf.buffer.length; + } + int data_len = io_in.read(buf.buffer, 0, bar); + if(data_len<0){ + break loop; + } + + dst.write(buf.buffer, 0, data_len); + + offset+=data_len; + foo-=data_len; + + if(monitor!=null){ + if(!monitor.count(data_len)){ + skip(foo); + if(optional_data>0){ + skip(optional_data); + } + break loop; + } + } + + } + //System.err.println("length: "+length); // length should be 0 + + if(optional_data>0){ + skip(optional_data); + } + + if(length_of_data=rrq.length) tail -= rrq.length; + rrq[tail].id=id; + rrq[tail].offset=offset; + rrq[tail].length=length; + count++; + } + + Request get(int id) throws OutOfOrderException, SftpException { + count -= 1; + int i = head; + head++; + if(head==rrq.length) head=0; + if(rrq[i].id != id){ + long offset = getOffset(); + boolean find = false; + for(int j = 0; jrrq[i].offset) + result=rrq[i].offset; + } + + return result; + } + } + + public InputStream get(String src) throws SftpException{ + return get(src, null, 0L); + } + public InputStream get(String src, SftpProgressMonitor monitor) throws SftpException{ + return get(src, monitor, 0L); + } + + /** + * @deprecated This method will be deleted in the future. + */ + public InputStream get(String src, int mode) throws SftpException{ + return get(src, null, 0L); + } + /** + * @deprecated This method will be deleted in the future. + */ + public InputStream get(String src, final SftpProgressMonitor monitor, final int mode) throws SftpException{ + return get(src, monitor, 0L); + } + public InputStream get(String src, final SftpProgressMonitor monitor, final long skip) throws SftpException{ + + try{ + ((MyPipedInputStream)io_in).updateReadSide(); + + src=remoteAbsolutePath(src); + src=isUnique(src); + + byte[] srcb=Util.str2byte(src, fEncoding); + + SftpATTRS attr=_stat(srcb); + if(monitor!=null){ + monitor.init(SftpProgressMonitor.GET, src, "??", attr.getSize()); + } + + sendOPENR(srcb); + + Header header=new Header(); + header=header(buf, header); + int length=header.length; + int type=header.type; + + fill(buf, length); + + if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){ + throw new SftpException(SSH_FX_FAILURE, ""); + } + if(type==SSH_FXP_STATUS){ + int i=buf.getInt(); + throwStatusError(buf, i); + } + + final byte[] handle=buf.getString(); // handle + + rq.init(); + + java.io.InputStream in=new java.io.InputStream(){ + long offset=skip; + boolean closed=false; + int rest_length=0; + byte[] _data=new byte[1]; + byte[] rest_byte=new byte[1024]; + Header header=new Header(); + int request_max=1; + long request_offset=offset; + + public int read() throws java.io.IOException{ + if(closed)return -1; + int i=read(_data, 0, 1); + if (i==-1) { return -1; } + else { + return _data[0]&0xff; + } + } + public int read(byte[] d) throws java.io.IOException{ + if(closed)return -1; + return read(d, 0, d.length); + } + public int read(byte[] d, int s, int len) throws java.io.IOException{ + if(closed)return -1; + if(d==null){throw new NullPointerException();} + if(s<0 || len <0 || s+len>d.length){ + throw new IndexOutOfBoundsException(); + } + if(len==0){ return 0; } + + if(rest_length>0){ + int foo=rest_length; + if(foo>len) foo=len; + System.arraycopy(rest_byte, 0, d, s, foo); + if(foo!=rest_length){ + System.arraycopy(rest_byte, foo, + rest_byte, 0, rest_length-foo); + } + + if(monitor!=null){ + if(!monitor.count(foo)){ + close(); + return -1; + } + } + + rest_length-=foo; + return foo; + } + + if(buf.buffer.length-131024){ + len=1024; + } + + if(rq.count()==0) { + int request_len = buf.buffer.length-13; + if(server_version==0){ request_len=1024; } + + while(rq.count() < request_max){ + try{ + sendREAD(handle, request_offset, request_len, rq); + } + catch(Exception e){ throw new IOException("error"); } + request_offset += request_len; + } + } + + header=header(buf, header); + rest_length=header.length; + int type=header.type; + int id=header.rid; + + RequestQueue.Request rr = null; + try{ + rr = rq.get(header.rid); + } + catch(RequestQueue.OutOfOrderException e){ + request_offset = e.offset; + skip(header.length); + rq.cancel(header, buf); + return 0; + } + catch(SftpException e){ + throw new IOException("error: "+e.toString()); + } + + if(type!=SSH_FXP_STATUS && type!=SSH_FXP_DATA){ + throw new IOException("error"); + } + if(type==SSH_FXP_STATUS){ + fill(buf, rest_length); + int i=buf.getInt(); + rest_length=0; + if(i==SSH_FX_EOF){ + close(); + return -1; + } + //throwStatusError(buf, i); + throw new IOException("error"); + } + + buf.rewind(); + fill(buf.buffer, 0, 4); + int length_of_data = buf.getInt(); rest_length-=4; + + /** + Since sftp protocol version 6, "end-of-file" has been defined, + + byte SSH_FXP_DATA + uint32 request-id + string data + bool end-of-file [optional] + + but some sftpd server will send such a field in the sftp protocol 3 ;-( + */ + int optional_data = rest_length - length_of_data; + + offset += length_of_data; + int foo = length_of_data; + if(foo>0){ + int bar=foo; + if(bar>len){ + bar=len; + } + int i=io_in.read(d, s, bar); + if(i<0){ + return -1; + } + foo-=i; + rest_length=foo; + + if(foo>0){ + if(rest_byte.length0){ + j=io_in.read(rest_byte, _s, _len); + if(j<=0)break; + _s+=j; + _len-=j; + } + } + + if(optional_data>0){ + io_in.skip(optional_data); + } + + if(length_of_datapath. + * Each files and directories will be passed to + * LsEntrySelector#select(LsEntry) method, and if that method + * returns LsEntrySelector#BREAK, the operation will be + * canceled immediately. + * + * @see ChannelSftp.LsEntrySelector + * @since 0.1.47 + */ + public void ls(String path, LsEntrySelector selector) throws SftpException{ + //System.out.println("ls: "+path); + try{ + ((MyPipedInputStream)io_in).updateReadSide(); + + path=remoteAbsolutePath(path); + byte[] pattern=null; + java.util.Vector v=new java.util.Vector(); + + int foo=path.lastIndexOf('/'); + String dir=path.substring(0, ((foo==0)?1:foo)); + String _pattern=path.substring(foo+1); + dir=Util.unquote(dir); + + // If pattern has included '*' or '?', we need to convert + // to UTF-8 string before globbing. + byte[][] _pattern_utf8=new byte[1][]; + boolean pattern_has_wildcard=isPattern(_pattern, _pattern_utf8); + + if(pattern_has_wildcard){ + pattern=_pattern_utf8[0]; + } + else{ + String upath=Util.unquote(path); + //SftpATTRS attr=_lstat(upath); + SftpATTRS attr=_stat(upath); + if(attr.isDir()){ + pattern=null; + dir=upath; + } + else{ + /* + // If we can generage longname by ourself, + // we don't have to use openDIR. + String filename=Util.unquote(_pattern); + String longname=... + v.addElement(new LsEntry(filename, longname, attr)); + return v; + */ + + if(fEncoding_is_utf8){ + pattern=_pattern_utf8[0]; + pattern=Util.unquote(pattern); + } + else{ + _pattern=Util.unquote(_pattern); + pattern=Util.str2byte(_pattern, fEncoding); + } + + } + } + + sendOPENDIR(Util.str2byte(dir, fEncoding)); + + Header header=new Header(); + header=header(buf, header); + int length=header.length; + int type=header.type; + + fill(buf, length); + + if(type!=SSH_FXP_STATUS && type!=SSH_FXP_HANDLE){ + throw new SftpException(SSH_FX_FAILURE, ""); + } + if(type==SSH_FXP_STATUS){ + int i=buf.getInt(); + throwStatusError(buf, i); + } + + int cancel = LsEntrySelector.CONTINUE; + byte[] handle=buf.getString(); // handle + + while(cancel==LsEntrySelector.CONTINUE){ + + sendREADDIR(handle); + + header=header(buf, header); + length=header.length; + type=header.type; + if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){ + throw new SftpException(SSH_FX_FAILURE, ""); + } + if(type==SSH_FXP_STATUS){ + fill(buf, length); + int i=buf.getInt(); + if(i==SSH_FX_EOF) + break; + throwStatusError(buf, i); + } + + buf.rewind(); + fill(buf.buffer, 0, 4); length-=4; + int count=buf.getInt(); + + byte[] str; + int flags; + + buf.reset(); + while(count>0){ + if(length>0){ + buf.shift(); + int j=(buf.buffer.length>(buf.index+length)) ? + length : + (buf.buffer.length-buf.index); + int i=fill(buf.buffer, buf.index, j); + buf.index+=i; + length-=i; + } + byte[] filename=buf.getString(); + byte[] longname=null; + if(server_version<=3){ + longname=buf.getString(); + } + SftpATTRS attrs=SftpATTRS.getATTR(buf); + + if(cancel==LsEntrySelector.BREAK){ + count--; + continue; + } + + boolean find=false; + String f=null; + if(pattern==null){ + find=true; + } + else if(!pattern_has_wildcard){ + find=Util.array_equals(pattern, filename); + } + else{ + byte[] _filename=filename; + if(!fEncoding_is_utf8){ + f=Util.byte2str(_filename, fEncoding); + _filename=Util.str2byte(f, UTF8); + } + find=Util.glob(pattern, _filename); + } + + if(find){ + if(f==null){ + f=Util.byte2str(filename, fEncoding); + } + String l=null; + if(longname==null){ + // TODO: we need to generate long name from attrs + // for the sftp protocol 4(and later). + l=attrs.toString()+" "+f; + } + else{ + l=Util.byte2str(longname, fEncoding); + } + + cancel = selector.select(new LsEntry(f, l, attrs)); + } + + count--; + } + } + _sendCLOSE(handle, header); + + /* + if(v.size()==1 && pattern_has_wildcard){ + LsEntry le=(LsEntry)v.elementAt(0); + if(le.getAttrs().isDir()){ + String f=le.getFilename(); + if(isPattern(f)){ + f=Util.quote(f); + } + if(!dir.endsWith("/")){ + dir+="/"; + } + v=null; + return ls(dir+f); + } + } + */ + + } + catch(Exception e){ + if(e instanceof SftpException) throw (SftpException)e; + if(e instanceof Throwable) + throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e); + throw new SftpException(SSH_FX_FAILURE, ""); + } + } + + public String readlink(String path) throws SftpException{ + try{ + if(server_version<3){ + throw new SftpException(SSH_FX_OP_UNSUPPORTED, + "The remote sshd is too old to support symlink operation."); + } + + ((MyPipedInputStream)io_in).updateReadSide(); + + path=remoteAbsolutePath(path); + + path=isUnique(path); + + sendREADLINK(Util.str2byte(path, fEncoding)); + + Header header=new Header(); + header=header(buf, header); + int length=header.length; + int type=header.type; + + fill(buf, length); + + if(type!=SSH_FXP_STATUS && type!=SSH_FXP_NAME){ + throw new SftpException(SSH_FX_FAILURE, ""); + } + if(type==SSH_FXP_NAME){ + int count=buf.getInt(); // count + byte[] filename=null; + for(int i=0; i=2){ + throw new SftpException(SSH_FX_FAILURE, v.toString()); + } + if(vsize==1){ + newpath=(String)(v.elementAt(0)); + } + else{ // vsize==0 + if(isPattern(newpath)) + throw new SftpException(SSH_FX_FAILURE, newpath); + newpath=Util.unquote(newpath); + } + + sendRENAME(Util.str2byte(oldpath, fEncoding), + Util.str2byte(newpath, fEncoding)); + + Header header=new Header(); + header=header(buf, header); + int length=header.length; + int type=header.type; + + fill(buf, length); + + if(type!=SSH_FXP_STATUS){ + throw new SftpException(SSH_FX_FAILURE, ""); + } + + int i=buf.getInt(); + if(i==SSH_FX_OK) return; + throwStatusError(buf, i); + } + catch(Exception e){ + if(e instanceof SftpException) throw (SftpException)e; + if(e instanceof Throwable) + throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e); + throw new SftpException(SSH_FX_FAILURE, ""); + } + } + public void rm(String path) throws SftpException{ + try{ + ((MyPipedInputStream)io_in).updateReadSide(); + + path=remoteAbsolutePath(path); + + Vector v=glob_remote(path); + int vsize=v.size(); + + Header header=new Header(); + + for(int j=0; j0){ + str=buf.getString(); // absolute path; + if(server_version<=3){ + byte[] lname=buf.getString(); // long filename + } + SftpATTRS attr=SftpATTRS.getATTR(buf); // dummy attribute + } + return str; + } + + public void setStat(String path, SftpATTRS attr) throws SftpException{ + try{ + ((MyPipedInputStream)io_in).updateReadSide(); + + path=remoteAbsolutePath(path); + + Vector v=glob_remote(path); + int vsize=v.size(); + for(int j=0; j0){ + i=io_in.read(buf, s, l); + if(i<=0){ + throw new SftpException(SSH_FX_FAILURE, ""); + } + s+=i; + l-=i; + } + } + + private boolean checkStatus(int[] ackid, Header header) throws IOException, SftpException{ + header=header(buf, header); + int length=header.length; + int type=header.type; + if(ackid!=null) + ackid[0]=header.rid; + + fill(buf, length); + + if(type!=SSH_FXP_STATUS){ + throw new SftpException(SSH_FX_FAILURE, ""); + } + int i=buf.getInt(); + if(i!=SSH_FX_OK){ + throwStatusError(buf, i); + } + return true; + } + private boolean _sendCLOSE(byte[] handle, Header header) throws Exception{ + sendCLOSE(handle); + return checkStatus(null, header); + } + + private void sendINIT() throws Exception{ + packet.reset(); + putHEAD(SSH_FXP_INIT, 5); + buf.putInt(3); // version 3 + getSession().write(packet, this, 5+4); + } + + private void sendREALPATH(byte[] path) throws Exception{ + sendPacketPath(SSH_FXP_REALPATH, path); + } + private void sendSTAT(byte[] path) throws Exception{ + sendPacketPath(SSH_FXP_STAT, path); + } + private void sendSTATVFS(byte[] path) throws Exception{ + sendPacketPath((byte)0, path, "statvfs@openssh.com"); + } + /* + private void sendFSTATVFS(byte[] handle) throws Exception{ + sendPacketPath((byte)0, handle, "fstatvfs@openssh.com"); + } + */ + private void sendLSTAT(byte[] path) throws Exception{ + sendPacketPath(SSH_FXP_LSTAT, path); + } + private void sendFSTAT(byte[] handle) throws Exception{ + sendPacketPath(SSH_FXP_FSTAT, handle); + } + private void sendSETSTAT(byte[] path, SftpATTRS attr) throws Exception{ + packet.reset(); + putHEAD(SSH_FXP_SETSTAT, 9+path.length+attr.length()); + buf.putInt(seq++); + buf.putString(path); // path + attr.dump(buf); + getSession().write(packet, this, 9+path.length+attr.length()+4); + } + private void sendREMOVE(byte[] path) throws Exception{ + sendPacketPath(SSH_FXP_REMOVE, path); + } + private void sendMKDIR(byte[] path, SftpATTRS attr) throws Exception{ + packet.reset(); + putHEAD(SSH_FXP_MKDIR, 9+path.length+(attr!=null?attr.length():4)); + buf.putInt(seq++); + buf.putString(path); // path + if(attr!=null) attr.dump(buf); + else buf.putInt(0); + getSession().write(packet, this, 9+path.length+(attr!=null?attr.length():4)+4); + } + private void sendRMDIR(byte[] path) throws Exception{ + sendPacketPath(SSH_FXP_RMDIR, path); + } + private void sendSYMLINK(byte[] p1, byte[] p2) throws Exception{ + sendPacketPath(SSH_FXP_SYMLINK, p1, p2); + } + private void sendHARDLINK(byte[] p1, byte[] p2) throws Exception{ + sendPacketPath((byte)0, p1, p2, "hardlink@openssh.com"); + } + private void sendREADLINK(byte[] path) throws Exception{ + sendPacketPath(SSH_FXP_READLINK, path); + } + private void sendOPENDIR(byte[] path) throws Exception{ + sendPacketPath(SSH_FXP_OPENDIR, path); + } + private void sendREADDIR(byte[] path) throws Exception{ + sendPacketPath(SSH_FXP_READDIR, path); + } + private void sendRENAME(byte[] p1, byte[] p2) throws Exception{ + sendPacketPath(SSH_FXP_RENAME, p1, p2, + extension_posix_rename ? "posix-rename@openssh.com" : null); + } + private void sendCLOSE(byte[] path) throws Exception{ + sendPacketPath(SSH_FXP_CLOSE, path); + } + private void sendOPENR(byte[] path) throws Exception{ + sendOPEN(path, SSH_FXF_READ); + } + private void sendOPENW(byte[] path) throws Exception{ + sendOPEN(path, SSH_FXF_WRITE|SSH_FXF_CREAT|SSH_FXF_TRUNC); + } + private void sendOPENA(byte[] path) throws Exception{ + sendOPEN(path, SSH_FXF_WRITE|/*SSH_FXF_APPEND|*/SSH_FXF_CREAT); + } + private void sendOPEN(byte[] path, int mode) throws Exception{ + packet.reset(); + putHEAD(SSH_FXP_OPEN, 17+path.length); + buf.putInt(seq++); + buf.putString(path); + buf.putInt(mode); + buf.putInt(0); // attrs + getSession().write(packet, this, 17+path.length+4); + } + private void sendPacketPath(byte fxp, byte[] path) throws Exception{ + sendPacketPath(fxp, path, (String)null); + } + private void sendPacketPath(byte fxp, byte[] path, String extension) throws Exception{ + packet.reset(); + int len = 9+path.length; + if(extension == null) { + putHEAD(fxp, len); + buf.putInt(seq++); + } + else { + len+=(4+extension.length()); + putHEAD(SSH_FXP_EXTENDED, len); + buf.putInt(seq++); + buf.putString(Util.str2byte(extension)); + } + buf.putString(path); // path + getSession().write(packet, this, len+4); + } + + private void sendPacketPath(byte fxp, byte[] p1, byte[] p2) throws Exception{ + sendPacketPath(fxp, p1, p2, null); + } + private void sendPacketPath(byte fxp, byte[] p1, byte[] p2, String extension) throws Exception{ + packet.reset(); + int len = 13+p1.length+p2.length; + if(extension==null){ + putHEAD(fxp, len); + buf.putInt(seq++); + } + else { + len+=(4+extension.length()); + putHEAD(SSH_FXP_EXTENDED, len); + buf.putInt(seq++); + buf.putString(Util.str2byte(extension)); + } + buf.putString(p1); + buf.putString(p2); + getSession().write(packet, this, len+4); + } + + private int sendWRITE(byte[] handle, long offset, + byte[] data, int start, int length) throws Exception{ + int _length=length; + opacket.reset(); + if(obuf.buffer.length0){ + if(length>0){ + buf.shift(); + int j=(buf.buffer.length>(buf.index+length)) ? length : (buf.buffer.length-buf.index); + i=io_in.read(buf.buffer, buf.index, j); + if(i<=0)break; + buf.index+=i; + length-=i; + } + + byte[] filename=buf.getString(); + //System.err.println("filename: "+new String(filename)); + if(server_version<=3){ + str=buf.getString(); // longname + } + SftpATTRS attrs=SftpATTRS.getATTR(buf); + + byte[] _filename=filename; + String f=null; + boolean found=false; + + if(!fEncoding_is_utf8){ + f=Util.byte2str(filename, fEncoding); + _filename=Util.str2byte(f, UTF8); + } + found=Util.glob(pattern, _filename); + + if(found){ + if(f==null){ + f=Util.byte2str(filename, fEncoding); + } + if(pdir==null){ + pdir=dir; + if(!pdir.endsWith("/")){ + pdir+="/"; + } + } + v.addElement(pdir+f); + } + count--; + } + } + if(_sendCLOSE(handle, header)) + return v; + return null; + } + + private boolean isPattern(byte[] path){ + int length=path.length; + int i=0; + while(i=0){ + if(path[i]!='*' && path[i]!='?'){ + i--; + continue; + } + if(!fs_is_bs && + i>0 && path[i-1]=='\\'){ + i--; + if(i>0 && path[i-1]=='\\'){ + i--; + i--; + continue; + } + } + break; + } + + if(i<0){ v.addElement(fs_is_bs ? _path : Util.unquote(_path)); return v;} + + while(i>=0){ + if(path[i]==file_separatorc || + (fs_is_bs && path[i]=='/')){ // On Windows, '/' is also the separator. + break; + } + i--; + } + + if(i<0){ v.addElement(fs_is_bs ? _path : Util.unquote(_path)); return v;} + + byte[] dir; + if(i==0){dir=new byte[]{(byte)file_separatorc};} + else{ + dir=new byte[i]; + System.arraycopy(path, 0, dir, 0, i); + } + + byte[] pattern=new byte[path.length-i-1]; + System.arraycopy(path, i+1, pattern, 0, pattern.length); + +//System.err.println("dir: "+new String(dir)+" pattern: "+new String(pattern)); + try{ + String[] children=(new File(Util.byte2str(dir, UTF8))).list(); + String pdir=Util.byte2str(dir)+file_separator; + for(int j=0; j=3 && // WindRiver's sftp will send invalid + buf.getLength()>=4){ // SSH_FXP_STATUS packet. + byte[] str=buf.getString(); + //byte[] tag=buf.getString(); + throw new SftpException(i, Util.byte2str(str, UTF8)); + } + else{ + throw new SftpException(i, "Failure"); + } + } + + private static boolean isLocalAbsolutePath(String path){ + return (new File(path)).isAbsolute(); + } + + public void disconnect(){ + super.disconnect(); + } + + private boolean isPattern(String path, byte[][] utf8){ + byte[] _path=Util.str2byte(path, UTF8); + if(utf8!=null) + utf8[0]=_path; + return isPattern(_path); + } + + private boolean isPattern(String path){ + return isPattern(path, null); + } + + private void fill(Buffer buf, int len) throws IOException{ + buf.reset(); + fill(buf.buffer, 0, len); + buf.skip(len); + } + + private int fill(byte[] buf, int s, int len) throws IOException{ + int i=0; + int foo=s; + while(len>0){ + i=io_in.read(buf, s, len); + if(i<=0){ + throw new IOException("inputstream is closed"); + //return (s-foo)==0 ? i : s-foo; + } + s+=i; + len-=i; + } + return s-foo; + } + private void skip(long foo) throws IOException{ + while(foo>0){ + long bar=io_in.skip(foo); + if(bar<=0) + break; + foo-=bar; + } + } + + class Header{ + int length; + int type; + int rid; + } + private Header header(Buffer buf, Header header) throws IOException{ + buf.rewind(); + int i=fill(buf.buffer, 0, 9); + header.length=buf.getInt()-5; + header.type=buf.getByte()&0xff; + header.rid=buf.getInt(); + return header; + } + + private String remoteAbsolutePath(String path) throws SftpException{ + if(path.charAt(0)=='/') return path; + String cwd=getCwd(); +// if(cwd.equals(getHome())) return path; + if(cwd.endsWith("/")) return cwd+path; + return cwd+"/"+path; + } + + private String localAbsolutePath(String path){ + if(isLocalAbsolutePath(path)) return path; + if(lcwd.endsWith(file_separator)) return lcwd+path; + return lcwd+file_separator+path; + } + + /** + * This method will check if the given string can be expanded to the + * unique string. If it can be expanded to mutiple files, SftpException + * will be thrown. + * @return the returned string is unquoted. + */ + private String isUnique(String path) throws SftpException, Exception{ + Vector v=glob_remote(path); + if(v.size()!=1){ + throw new SftpException(SSH_FX_FAILURE, path+" is not unique: "+v.toString()); + } + return (String)(v.elementAt(0)); + } + + public int getServerVersion() throws SftpException{ + if(!isConnected()){ + throw new SftpException(SSH_FX_FAILURE, "The channel is not connected."); + } + return server_version; + } + + public void setFilenameEncoding(String encoding) throws SftpException{ + int sversion=getServerVersion(); + if(3 <= sversion && sversion <= 5 && + !encoding.equals(UTF8)){ + throw new SftpException(SSH_FX_FAILURE, + "The encoding can not be changed for this sftp server."); + } + if(encoding.equals(UTF8)){ + encoding=UTF8; + } + fEncoding=encoding; + fEncoding_is_utf8=fEncoding.equals(UTF8); + } + + public String getExtension(String key){ + if(extensions==null) + return null; + return (String)extensions.get(key); + } + + public String realpath(String path) throws SftpException{ + try{ + byte[] _path=_realpath(remoteAbsolutePath(path)); + return Util.byte2str(_path, fEncoding); + } + catch(Exception e){ + if(e instanceof SftpException) throw (SftpException)e; + if(e instanceof Throwable) + throw new SftpException(SSH_FX_FAILURE, "", (Throwable)e); + throw new SftpException(SSH_FX_FAILURE, ""); + } + } + + public class LsEntry implements Comparable{ + private String filename; + private String longname; + private SftpATTRS attrs; + LsEntry(String filename, String longname, SftpATTRS attrs){ + setFilename(filename); + setLongname(longname); + setAttrs(attrs); + } + public String getFilename(){return filename;}; + void setFilename(String filename){this.filename = filename;}; + public String getLongname(){return longname;}; + void setLongname(String longname){this.longname = longname;}; + public SftpATTRS getAttrs(){return attrs;}; + void setAttrs(SftpATTRS attrs) {this.attrs = attrs;}; + public String toString(){ return longname; } + public int compareTo(Object o) throws ClassCastException{ + if(o instanceof LsEntry){ + return filename.compareTo(((LsEntry)o).getFilename()); + } + throw new ClassCastException("a decendent of LsEntry must be given."); + } + } + + /** + * This interface will be passed as an argument for ls method. + * + * @see ChannelSftp.LsEntry + * @see #ls(String, ChannelSftp.LsEntrySelector) + * @since 0.1.47 + */ + public interface LsEntrySelector { + public final int CONTINUE = 0; + public final int BREAK = 1; + + /** + *

The select method will be invoked in ls + * method for each file entry. If this method returns BREAK, + * ls will be canceled. + * + * @param entry one of entry from ls + * @return if BREAK is returned, the 'ls' operation will be canceled. + */ + public int select(LsEntry entry); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelShell.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelShell.java new file mode 100644 index 00000000..eeb24a39 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelShell.java @@ -0,0 +1,70 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.util.*; + +public class ChannelShell extends ChannelSession{ + + ChannelShell(){ + super(); + pty=true; + } + + public void start() throws JSchException{ + Session _session=getSession(); + try{ + sendRequests(); + + Request request=new RequestShell(); + request.request(_session, this); + } + catch(Exception e){ + if(e instanceof JSchException) throw (JSchException)e; + if(e instanceof Throwable) + throw new JSchException("ChannelShell", (Throwable)e); + throw new JSchException("ChannelShell"); + } + + if(io.in!=null){ + thread=new Thread(this); + thread.setName("Shell for "+_session.host); + if(_session.daemon_thread){ + thread.setDaemon(_session.daemon_thread); + } + thread.start(); + } + } + + void init() throws JSchException { + io.setInputStream(getSession().in); + io.setOutputStream(getSession().out); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelSubsystem.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelSubsystem.java new file mode 100644 index 00000000..3f33bf3e --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelSubsystem.java @@ -0,0 +1,83 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2005-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public class ChannelSubsystem extends ChannelSession{ + boolean xforwading=false; + boolean pty=false; + boolean want_reply=true; + String subsystem=""; + public void setXForwarding(boolean foo){ xforwading=foo; } + public void setPty(boolean foo){ pty=foo; } + public void setWantReply(boolean foo){ want_reply=foo; } + public void setSubsystem(String foo){ subsystem=foo; } + public void start() throws JSchException{ + Session _session=getSession(); + try{ + Request request; + if(xforwading){ + request=new RequestX11(); + request.request(_session, this); + } + if(pty){ + request=new RequestPtyReq(); + request.request(_session, this); + } + request=new RequestSubsystem(); + ((RequestSubsystem)request).request(_session, this, subsystem, want_reply); + } + catch(Exception e){ + if(e instanceof JSchException){ throw (JSchException)e; } + if(e instanceof Throwable) + throw new JSchException("ChannelSubsystem", (Throwable)e); + throw new JSchException("ChannelSubsystem"); + } + if(io.in!=null){ + thread=new Thread(this); + thread.setName("Subsystem for "+_session.host); + if(_session.daemon_thread){ + thread.setDaemon(_session.daemon_thread); + } + thread.start(); + } + } + + void init() throws JSchException { + io.setInputStream(getSession().in); + io.setOutputStream(getSession().out); + } + + public void setErrStream(java.io.OutputStream out){ + setExtOutputStream(out); + } + public java.io.InputStream getErrStream() throws java.io.IOException { + return getExtInputStream(); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelX11.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelX11.java new file mode 100644 index 00000000..393728c0 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/ChannelX11.java @@ -0,0 +1,273 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.net.*; + +class ChannelX11 extends Channel{ + + static private final int LOCAL_WINDOW_SIZE_MAX=0x20000; + static private final int LOCAL_MAXIMUM_PACKET_SIZE=0x4000; + + static private final int TIMEOUT=10*1000; + + private static String host="127.0.0.1"; + private static int port=6000; + + private boolean init=true; + + static byte[] cookie=null; + private static byte[] cookie_hex=null; + + private static java.util.Hashtable faked_cookie_pool=new java.util.Hashtable(); + private static java.util.Hashtable faked_cookie_hex_pool=new java.util.Hashtable(); + + private static byte[] table={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39, + 0x61,0x62,0x63,0x64,0x65,0x66}; + + private Socket socket = null; + + static int revtable(byte foo){ + for(int i=0; i>>4)&0xf]; + bar[2*i+1]=table[(foo[i])&0xf]; + } + faked_cookie_hex_pool.put(session, bar); + foo=bar; + } + return foo; + } + } + + static void removeFakedCookie(Session session){ + synchronized(faked_cookie_hex_pool){ + faked_cookie_hex_pool.remove(session); + faked_cookie_pool.remove(session); + } + } + + ChannelX11(){ + super(); + + setLocalWindowSizeMax(LOCAL_WINDOW_SIZE_MAX); + setLocalWindowSize(LOCAL_WINDOW_SIZE_MAX); + setLocalPacketSize(LOCAL_MAXIMUM_PACKET_SIZE); + + type=Util.str2byte("x11"); + + connected=true; + /* + try{ + socket=Util.createSocket(host, port, TIMEOUT); + socket.setTcpNoDelay(true); + io=new IO(); + io.setInputStream(socket.getInputStream()); + io.setOutputStream(socket.getOutputStream()); + } + catch(Exception e){ + //System.err.println(e); + } + */ + } + + public void run(){ + + try{ + socket=Util.createSocket(host, port, TIMEOUT); + socket.setTcpNoDelay(true); + io=new IO(); + io.setInputStream(socket.getInputStream()); + io.setOutputStream(socket.getOutputStream()); + sendOpenConfirmation(); + } + catch(Exception e){ + sendOpenFailure(SSH_OPEN_ADMINISTRATIVELY_PROHIBITED); + close=true; + disconnect(); + return; + } + + thread=Thread.currentThread(); + Buffer buf=new Buffer(rmpsize); + Packet packet=new Packet(buf); + int i=0; + try{ + while(thread!=null && + io!=null && + io.in!=null){ + i=io.in.read(buf.buffer, + 14, + buf.buffer.length-14-Session.buffer_margin); + if(i<=0){ + eof(); + break; + } + if(close)break; + packet.reset(); + buf.putByte((byte)Session.SSH_MSG_CHANNEL_DATA); + buf.putInt(recipient); + buf.putInt(i); + buf.skip(i); + getSession().write(packet, this, i); + } + } + catch(Exception e){ + //System.err.println(e); + } + disconnect(); + } + + private byte[] cache=new byte[0]; + private byte[] addCache(byte[] foo, int s, int l){ + byte[] bar=new byte[cache.length+l]; + System.arraycopy(foo, s, bar, cache.length, l); + if(cache.length>0) + System.arraycopy(cache, 0, bar, 0, cache.length); + cache=bar; + return cache; + } + + void write(byte[] foo, int s, int l) throws java.io.IOException { + //if(eof_local)return; + + if(init){ + + Session _session=null; + try{ + _session=getSession(); + } + catch(JSchException e){ + throw new java.io.IOException(e.toString()); + } + + foo=addCache(foo, s, l); + s=0; + l=foo.length; + + if(l<9) + return; + + int plen=(foo[s+6]&0xff)*256+(foo[s+7]&0xff); + int dlen=(foo[s+8]&0xff)*256+(foo[s+9]&0xff); + + if((foo[s]&0xff)==0x42){ + } + else if((foo[s]&0xff)==0x6c){ + plen=((plen>>>8)&0xff)|((plen<<8)&0xff00); + dlen=((dlen>>>8)&0xff)|((dlen<<8)&0xff00); + } + else{ + // ?? + } + + if(l<12+plen+((-plen)&3)+dlen) + return; + + byte[] bar=new byte[dlen]; + System.arraycopy(foo, s+12+plen+((-plen)&3), bar, 0, dlen); + byte[] faked_cookie=null; + + synchronized(faked_cookie_pool){ + faked_cookie=(byte[])faked_cookie_pool.get(_session); + } + + /* +System.err.print("faked_cookie: "); +for(int i=0; i "); //dump(H, 0, H.length); + + i=0; + j=0; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + String alg=Util.byte2str(K_S, i, j); + i+=j; + + boolean result=false; + + if(alg.equals("ssh-rsa")){ + byte[] tmp; + byte[] ee; + byte[] n; + + type=RSA; + + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + ee=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + n=tmp; + +// SignatureRSA sig=new SignatureRSA(); +// sig.init(); + + SignatureRSA sig=null; + try{ + Class c=Class.forName(session.getConfig("signature.rsa")); + sig=(SignatureRSA)(c.newInstance()); + sig.init(); + } + catch(Exception e){ + System.err.println(e); + } + + sig.setPubKey(ee, n); + sig.update(H); + result=sig.verify(sig_of_H); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "ssh_rsa_verify: signature "+result); + } + + } + else if(alg.equals("ssh-dss")){ + byte[] q=null; + byte[] tmp; + byte[] p; + byte[] g; + + type=DSS; + + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + p=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + q=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + g=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + f=tmp; +// SignatureDSA sig=new SignatureDSA(); +// sig.init(); + SignatureDSA sig=null; + try{ + Class c=Class.forName(session.getConfig("signature.dss")); + sig=(SignatureDSA)(c.newInstance()); + sig.init(); + } + catch(Exception e){ + System.err.println(e); + } + sig.setPubKey(f, p, q, g); + sig.update(H); + result=sig.verify(sig_of_H); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "ssh_dss_verify: signature "+result); + } + + } + else{ + System.err.println("unknown alg"); + } + state=STATE_END; + return result; + } + return false; + } + + public String getKeyType(){ + if(type==DSS) return "DSA"; + return "RSA"; + } + + public int getState(){return state; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/DHG14.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/DHG14.java new file mode 100644 index 00000000..044d7099 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/DHG14.java @@ -0,0 +1,310 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public class DHG14 extends KeyExchange{ + + static final byte[] g={ 2 }; + static final byte[] p={ +(byte)0x00, +(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF, +(byte)0xC9,(byte)0x0F,(byte)0xDA,(byte)0xA2,(byte)0x21,(byte)0x68,(byte)0xC2,(byte)0x34, +(byte)0xC4,(byte)0xC6,(byte)0x62,(byte)0x8B,(byte)0x80,(byte)0xDC,(byte)0x1C,(byte)0xD1, +(byte)0x29,(byte)0x02,(byte)0x4E,(byte)0x08,(byte)0x8A,(byte)0x67,(byte)0xCC,(byte)0x74, +(byte)0x02,(byte)0x0B,(byte)0xBE,(byte)0xA6,(byte)0x3B,(byte)0x13,(byte)0x9B,(byte)0x22, +(byte)0x51,(byte)0x4A,(byte)0x08,(byte)0x79,(byte)0x8E,(byte)0x34,(byte)0x04,(byte)0xDD, +(byte)0xEF,(byte)0x95,(byte)0x19,(byte)0xB3,(byte)0xCD,(byte)0x3A,(byte)0x43,(byte)0x1B, +(byte)0x30,(byte)0x2B,(byte)0x0A,(byte)0x6D,(byte)0xF2,(byte)0x5F,(byte)0x14,(byte)0x37, +(byte)0x4F,(byte)0xE1,(byte)0x35,(byte)0x6D,(byte)0x6D,(byte)0x51,(byte)0xC2,(byte)0x45, +(byte)0xE4,(byte)0x85,(byte)0xB5,(byte)0x76,(byte)0x62,(byte)0x5E,(byte)0x7E,(byte)0xC6, +(byte)0xF4,(byte)0x4C,(byte)0x42,(byte)0xE9,(byte)0xA6,(byte)0x37,(byte)0xED,(byte)0x6B, +(byte)0x0B,(byte)0xFF,(byte)0x5C,(byte)0xB6,(byte)0xF4,(byte)0x06,(byte)0xB7,(byte)0xED, +(byte)0xEE,(byte)0x38,(byte)0x6B,(byte)0xFB,(byte)0x5A,(byte)0x89,(byte)0x9F,(byte)0xA5, +(byte)0xAE,(byte)0x9F,(byte)0x24,(byte)0x11,(byte)0x7C,(byte)0x4B,(byte)0x1F,(byte)0xE6, +(byte)0x49,(byte)0x28,(byte)0x66,(byte)0x51,(byte)0xEC,(byte)0xE4,(byte)0x5B,(byte)0x3D, +(byte)0xC2,(byte)0x00,(byte)0x7C,(byte)0xB8,(byte)0xA1,(byte)0x63,(byte)0xBF,(byte)0x05, +(byte)0x98,(byte)0xDA,(byte)0x48,(byte)0x36,(byte)0x1C,(byte)0x55,(byte)0xD3,(byte)0x9A, +(byte)0x69,(byte)0x16,(byte)0x3F,(byte)0xA8,(byte)0xFD,(byte)0x24,(byte)0xCF,(byte)0x5F, +(byte)0x83,(byte)0x65,(byte)0x5D,(byte)0x23,(byte)0xDC,(byte)0xA3,(byte)0xAD,(byte)0x96, +(byte)0x1C,(byte)0x62,(byte)0xF3,(byte)0x56,(byte)0x20,(byte)0x85,(byte)0x52,(byte)0xBB, +(byte)0x9E,(byte)0xD5,(byte)0x29,(byte)0x07,(byte)0x70,(byte)0x96,(byte)0x96,(byte)0x6D, +(byte)0x67,(byte)0x0C,(byte)0x35,(byte)0x4E,(byte)0x4A,(byte)0xBC,(byte)0x98,(byte)0x04, +(byte)0xF1,(byte)0x74,(byte)0x6C,(byte)0x08,(byte)0xCA,(byte)0x18,(byte)0x21,(byte)0x7C, +(byte)0x32,(byte)0x90,(byte)0x5E,(byte)0x46,(byte)0x2E,(byte)0x36,(byte)0xCE,(byte)0x3B, +(byte)0xE3,(byte)0x9E,(byte)0x77,(byte)0x2C,(byte)0x18,(byte)0x0E,(byte)0x86,(byte)0x03, +(byte)0x9B,(byte)0x27,(byte)0x83,(byte)0xA2,(byte)0xEC,(byte)0x07,(byte)0xA2,(byte)0x8F, +(byte)0xB5,(byte)0xC5,(byte)0x5D,(byte)0xF0,(byte)0x6F,(byte)0x4C,(byte)0x52,(byte)0xC9, +(byte)0xDE,(byte)0x2B,(byte)0xCB,(byte)0xF6,(byte)0x95,(byte)0x58,(byte)0x17,(byte)0x18, +(byte)0x39,(byte)0x95,(byte)0x49,(byte)0x7C,(byte)0xEA,(byte)0x95,(byte)0x6A,(byte)0xE5, +(byte)0x15,(byte)0xD2,(byte)0x26,(byte)0x18,(byte)0x98,(byte)0xFA,(byte)0x05,(byte)0x10, +(byte)0x15,(byte)0x72,(byte)0x8E,(byte)0x5A,(byte)0x8A,(byte)0xAC,(byte)0xAA,(byte)0x68, +(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF +}; + + private static final int SSH_MSG_KEXDH_INIT= 30; + private static final int SSH_MSG_KEXDH_REPLY= 31; + + static final int RSA=0; + static final int DSS=1; + private int type=0; + + private int state; + + DH dh; + + byte[] V_S; + byte[] V_C; + byte[] I_S; + byte[] I_C; + + byte[] e; + + private Buffer buf; + private Packet packet; + + public void init(Session session, + byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{ + this.session=session; + this.V_S=V_S; + this.V_C=V_C; + this.I_S=I_S; + this.I_C=I_C; + + try{ + Class c=Class.forName(session.getConfig("sha-1")); + sha=(HASH)(c.newInstance()); + sha.init(); + } + catch(Exception e){ + System.err.println(e); + } + + buf=new Buffer(); + packet=new Packet(buf); + + try{ + Class c=Class.forName(session.getConfig("dh")); + dh=(DH)(c.newInstance()); + dh.init(); + } + catch(Exception e){ + //System.err.println(e); + throw e; + } + + dh.setP(p); + dh.setG(g); + // The client responds with: + // byte SSH_MSG_KEXDH_INIT(30) + // mpint e <- g^x mod p + // x is a random number (1 < x < (p-1)/2) + + e=dh.getE(); + packet.reset(); + buf.putByte((byte)SSH_MSG_KEXDH_INIT); + buf.putMPInt(e); + + if(V_S==null){ // This is a really ugly hack for Session.checkKexes ;-( + return; + } + + session.write(packet); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "SSH_MSG_KEXDH_INIT sent"); + JSch.getLogger().log(Logger.INFO, + "expecting SSH_MSG_KEXDH_REPLY"); + } + + state=SSH_MSG_KEXDH_REPLY; + } + + public boolean next(Buffer _buf) throws Exception{ + int i,j; + + switch(state){ + case SSH_MSG_KEXDH_REPLY: + // The server responds with: + // byte SSH_MSG_KEXDH_REPLY(31) + // string server public host key and certificates (K_S) + // mpint f + // string signature of H + j=_buf.getInt(); + j=_buf.getByte(); + j=_buf.getByte(); + if(j!=31){ + System.err.println("type: must be 31 "+j); + return false; + } + + K_S=_buf.getString(); + // K_S is server_key_blob, which includes .... + // string ssh-dss + // impint p of dsa + // impint q of dsa + // impint g of dsa + // impint pub_key of dsa + //System.err.print("K_S: "); //dump(K_S, 0, K_S.length); + byte[] f=_buf.getMPInt(); + byte[] sig_of_H=_buf.getString(); + + dh.setF(f); + K=normalize(dh.getK()); + + //The hash H is computed as the HASH hash of the concatenation of the + //following: + // string V_C, the client's version string (CR and NL excluded) + // string V_S, the server's version string (CR and NL excluded) + // string I_C, the payload of the client's SSH_MSG_KEXINIT + // string I_S, the payload of the server's SSH_MSG_KEXINIT + // string K_S, the host key + // mpint e, exchange value sent by the client + // mpint f, exchange value sent by the server + // mpint K, the shared secret + // This value is called the exchange hash, and it is used to authenti- + // cate the key exchange. + buf.reset(); + buf.putString(V_C); buf.putString(V_S); + buf.putString(I_C); buf.putString(I_S); + buf.putString(K_S); + buf.putMPInt(e); buf.putMPInt(f); + buf.putMPInt(K); + byte[] foo=new byte[buf.getLength()]; + buf.getByte(foo); + sha.update(foo, 0, foo.length); + H=sha.digest(); + //System.err.print("H -> "); //dump(H, 0, H.length); + + i=0; + j=0; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + String alg=Util.byte2str(K_S, i, j); + i+=j; + + boolean result=false; + + if(alg.equals("ssh-rsa")){ + byte[] tmp; + byte[] ee; + byte[] n; + + type=RSA; + + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + ee=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + n=tmp; + + SignatureRSA sig=null; + try{ + Class c=Class.forName(session.getConfig("signature.rsa")); + sig=(SignatureRSA)(c.newInstance()); + sig.init(); + } + catch(Exception e){ + System.err.println(e); + } + + sig.setPubKey(ee, n); + sig.update(H); + result=sig.verify(sig_of_H); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "ssh_rsa_verify: signature "+result); + } + + } + else if(alg.equals("ssh-dss")){ + byte[] q=null; + byte[] tmp; + byte[] p; + byte[] g; + + type=DSS; + + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + p=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + q=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + g=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + f=tmp; + + SignatureDSA sig=null; + try{ + Class c=Class.forName(session.getConfig("signature.dss")); + sig=(SignatureDSA)(c.newInstance()); + sig.init(); + } + catch(Exception e){ + System.err.println(e); + } + sig.setPubKey(f, p, q, g); + sig.update(H); + result=sig.verify(sig_of_H); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "ssh_dss_verify: signature "+result); + } + + } + else{ + System.err.println("unknown alg"); + } + state=STATE_END; + return result; + } + return false; + } + + public String getKeyType(){ + if(type==DSS) return "DSA"; + return "RSA"; + } + + public int getState(){return state; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/DHGEX.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/DHGEX.java new file mode 100644 index 00000000..d067a657 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/DHGEX.java @@ -0,0 +1,340 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public class DHGEX extends KeyExchange{ + + private static final int SSH_MSG_KEX_DH_GEX_GROUP= 31; + private static final int SSH_MSG_KEX_DH_GEX_INIT= 32; + private static final int SSH_MSG_KEX_DH_GEX_REPLY= 33; + private static final int SSH_MSG_KEX_DH_GEX_REQUEST= 34; + + static int min=1024; + +// static int min=512; + static int preferred=1024; + static int max=1024; + +// static int preferred=1024; +// static int max=2000; + + static final int RSA=0; + static final int DSS=1; + private int type=0; + + private int state; + +// com.jcraft.jsch.DH dh; + DH dh; + + byte[] V_S; + byte[] V_C; + byte[] I_S; + byte[] I_C; + + private Buffer buf; + private Packet packet; + + private byte[] p; + private byte[] g; + private byte[] e; + //private byte[] f; + + public void init(Session session, + byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{ + this.session=session; + this.V_S=V_S; + this.V_C=V_C; + this.I_S=I_S; + this.I_C=I_C; + + try{ + Class c=Class.forName(session.getConfig("sha-1")); + sha=(HASH)(c.newInstance()); + sha.init(); + } + catch(Exception e){ + System.err.println(e); + } + + buf=new Buffer(); + packet=new Packet(buf); + + try{ + Class c=Class.forName(session.getConfig("dh")); + dh=(com.jcraft.jsch.DH)(c.newInstance()); + dh.init(); + } + catch(Exception e){ +// System.err.println(e); + throw e; + } + + packet.reset(); + buf.putByte((byte)SSH_MSG_KEX_DH_GEX_REQUEST); + buf.putInt(min); + buf.putInt(preferred); + buf.putInt(max); + session.write(packet); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "SSH_MSG_KEX_DH_GEX_REQUEST("+min+"<"+preferred+"<"+max+") sent"); + JSch.getLogger().log(Logger.INFO, + "expecting SSH_MSG_KEX_DH_GEX_GROUP"); + } + + state=SSH_MSG_KEX_DH_GEX_GROUP; + } + + public boolean next(Buffer _buf) throws Exception{ + int i,j; + switch(state){ + case SSH_MSG_KEX_DH_GEX_GROUP: + // byte SSH_MSG_KEX_DH_GEX_GROUP(31) + // mpint p, safe prime + // mpint g, generator for subgroup in GF (p) + _buf.getInt(); + _buf.getByte(); + j=_buf.getByte(); + if(j!=SSH_MSG_KEX_DH_GEX_GROUP){ + System.err.println("type: must be SSH_MSG_KEX_DH_GEX_GROUP "+j); + return false; + } + + p=_buf.getMPInt(); + g=_buf.getMPInt(); + /* +for(int iii=0; iii "); dump(H, 0, H.length); + + i=0; + j=0; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + String alg=Util.byte2str(K_S, i, j); + i+=j; + + boolean result=false; + if(alg.equals("ssh-rsa")){ + byte[] tmp; + byte[] ee; + byte[] n; + + type=RSA; + + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + ee=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + n=tmp; + +// SignatureRSA sig=new SignatureRSA(); +// sig.init(); + + SignatureRSA sig=null; + try{ + Class c=Class.forName(session.getConfig("signature.rsa")); + sig=(SignatureRSA)(c.newInstance()); + sig.init(); + } + catch(Exception e){ + System.err.println(e); + } + + sig.setPubKey(ee, n); + sig.update(H); + result=sig.verify(sig_of_H); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "ssh_rsa_verify: signature "+result); + } + + } + else if(alg.equals("ssh-dss")){ + byte[] q=null; + byte[] tmp; + + type=DSS; + + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + p=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + q=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + g=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + f=tmp; + +// SignatureDSA sig=new SignatureDSA(); +// sig.init(); + + SignatureDSA sig=null; + try{ + Class c=Class.forName(session.getConfig("signature.dss")); + sig=(SignatureDSA)(c.newInstance()); + sig.init(); + } + catch(Exception e){ + System.err.println(e); + } + + sig.setPubKey(f, p, q, g); + sig.update(H); + result=sig.verify(sig_of_H); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "ssh_dss_verify: signature "+result); + } + + } + else{ + System.err.println("unknown alg"); + } + state=STATE_END; + return result; + } + return false; + } + + public String getKeyType(){ + if(type==DSS) return "DSA"; + return "RSA"; + } + + public int getState(){return state; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/DHGEX256.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/DHGEX256.java new file mode 100644 index 00000000..f0db18e8 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/DHGEX256.java @@ -0,0 +1,340 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public class DHGEX256 extends KeyExchange{ + + private static final int SSH_MSG_KEX_DH_GEX_GROUP= 31; + private static final int SSH_MSG_KEX_DH_GEX_INIT= 32; + private static final int SSH_MSG_KEX_DH_GEX_REPLY= 33; + private static final int SSH_MSG_KEX_DH_GEX_REQUEST= 34; + + static int min=1024; + +// static int min=512; + static int preferred=1024; + static int max=1024; + +// static int preferred=1024; +// static int max=2000; + + static final int RSA=0; + static final int DSS=1; + private int type=0; + + private int state; + +// com.jcraft.jsch.DH dh; + DH dh; + + byte[] V_S; + byte[] V_C; + byte[] I_S; + byte[] I_C; + + private Buffer buf; + private Packet packet; + + private byte[] p; + private byte[] g; + private byte[] e; + //private byte[] f; + + public void init(Session session, + byte[] V_S, byte[] V_C, byte[] I_S, byte[] I_C) throws Exception{ + this.session=session; + this.V_S=V_S; + this.V_C=V_C; + this.I_S=I_S; + this.I_C=I_C; + + try{ + Class c=Class.forName(session.getConfig("sha-256")); + sha=(HASH)(c.newInstance()); + sha.init(); + } + catch(Exception e){ + System.err.println(e); + } + + buf=new Buffer(); + packet=new Packet(buf); + + try{ + Class c=Class.forName(session.getConfig("dh")); + dh=(com.jcraft.jsch.DH)(c.newInstance()); + dh.init(); + } + catch(Exception e){ +// System.err.println(e); + throw e; + } + + packet.reset(); + buf.putByte((byte)SSH_MSG_KEX_DH_GEX_REQUEST); + buf.putInt(min); + buf.putInt(preferred); + buf.putInt(max); + session.write(packet); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "SSH_MSG_KEX_DH_GEX_REQUEST("+min+"<"+preferred+"<"+max+") sent"); + JSch.getLogger().log(Logger.INFO, + "expecting SSH_MSG_KEX_DH_GEX_GROUP"); + } + + state=SSH_MSG_KEX_DH_GEX_GROUP; + } + + public boolean next(Buffer _buf) throws Exception{ + int i,j; + switch(state){ + case SSH_MSG_KEX_DH_GEX_GROUP: + // byte SSH_MSG_KEX_DH_GEX_GROUP(31) + // mpint p, safe prime + // mpint g, generator for subgroup in GF (p) + _buf.getInt(); + _buf.getByte(); + j=_buf.getByte(); + if(j!=SSH_MSG_KEX_DH_GEX_GROUP){ + System.err.println("type: must be SSH_MSG_KEX_DH_GEX_GROUP "+j); + return false; + } + + p=_buf.getMPInt(); + g=_buf.getMPInt(); + /* +for(int iii=0; iii "); dump(H, 0, H.length); + + i=0; + j=0; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + String alg=Util.byte2str(K_S, i, j); + i+=j; + + boolean result=false; + if(alg.equals("ssh-rsa")){ + byte[] tmp; + byte[] ee; + byte[] n; + + type=RSA; + + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + ee=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + n=tmp; + +// SignatureRSA sig=new SignatureRSA(); +// sig.init(); + + SignatureRSA sig=null; + try{ + Class c=Class.forName(session.getConfig("signature.rsa")); + sig=(SignatureRSA)(c.newInstance()); + sig.init(); + } + catch(Exception e){ + System.err.println(e); + } + + sig.setPubKey(ee, n); + sig.update(H); + result=sig.verify(sig_of_H); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "ssh_rsa_verify: signature "+result); + } + + } + else if(alg.equals("ssh-dss")){ + byte[] q=null; + byte[] tmp; + + type=DSS; + + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + p=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + q=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + g=tmp; + j=((K_S[i++]<<24)&0xff000000)|((K_S[i++]<<16)&0x00ff0000)| + ((K_S[i++]<<8)&0x0000ff00)|((K_S[i++])&0x000000ff); + tmp=new byte[j]; System.arraycopy(K_S, i, tmp, 0, j); i+=j; + f=tmp; + +// SignatureDSA sig=new SignatureDSA(); +// sig.init(); + + SignatureDSA sig=null; + try{ + Class c=Class.forName(session.getConfig("signature.dss")); + sig=(SignatureDSA)(c.newInstance()); + sig.init(); + } + catch(Exception e){ + System.err.println(e); + } + + sig.setPubKey(f, p, q, g); + sig.update(H); + result=sig.verify(sig_of_H); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "ssh_dss_verify: signature "+result); + } + + } + else{ + System.err.println("unknown alg"); + } + state=STATE_END; + return result; + } + return false; + } + + public String getKeyType(){ + if(type==DSS) return "DSA"; + return "RSA"; + } + + public int getState(){return state; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/ForwardedTCPIPDaemon.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/ForwardedTCPIPDaemon.java new file mode 100644 index 00000000..4176aef4 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/ForwardedTCPIPDaemon.java @@ -0,0 +1,36 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; +import java.io.*; + +public interface ForwardedTCPIPDaemon extends Runnable{ + void setChannel(ChannelForwardedTCPIP channel, InputStream in, OutputStream out); + void setArg(Object[] arg); +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/GSSContext.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/GSSContext.java new file mode 100644 index 00000000..23c58ee3 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/GSSContext.java @@ -0,0 +1,38 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2004-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public interface GSSContext{ + public void create(String user, String host) throws JSchException; + public boolean isEstablished(); + public byte[] init(byte[] token, int s, int l) throws JSchException; + public byte[] getMIC(byte[] message, int s, int l); + public void dispose(); +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/HASH.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/HASH.java new file mode 100644 index 00000000..6bfff886 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/HASH.java @@ -0,0 +1,37 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public interface HASH{ + void init() throws Exception; + int getBlockSize(); + void update(byte[] foo, int start, int len) throws Exception; + byte[] digest() throws Exception; +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/HostKey.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/HostKey.java new file mode 100644 index 00000000..8a4c6f50 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/HostKey.java @@ -0,0 +1,116 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public class HostKey{ + private static final byte[] sshdss=Util.str2byte("ssh-dss"); + private static final byte[] sshrsa=Util.str2byte("ssh-rsa"); + + protected static final int GUESS=0; + public static final int SSHDSS=1; + public static final int SSHRSA=2; + static final int UNKNOWN=3; + + protected String marker; + protected String host; + protected int type; + protected byte[] key; + protected String comment; + + public HostKey(String host, byte[] key) throws JSchException { + this(host, GUESS, key); + } + + public HostKey(String host, int type, byte[] key) throws JSchException { + this(host, type, key, null); + } + public HostKey(String host, int type, byte[] key, String comment) throws JSchException { + this("", host, type, key, comment); + } + public HostKey(String marker, String host, int type, byte[] key, String comment) throws JSchException { + this.marker=marker; + this.host=host; + if(type==GUESS){ + if(key[8]=='d'){ this.type=SSHDSS; } + else if(key[8]=='r'){ this.type=SSHRSA; } + else { throw new JSchException("invalid key type");} + } + else{ + this.type=type; + } + this.key=key; + this.comment=comment; + } + + public String getHost(){ return host; } + public String getType(){ + if(type==SSHDSS){ return Util.byte2str(sshdss); } + if(type==SSHRSA){ return Util.byte2str(sshrsa);} + return "UNKNOWN"; + } + public String getKey(){ + return Util.byte2str(Util.toBase64(key, 0, key.length)); + } + public String getFingerPrint(JSch jsch){ + HASH hash=null; + try{ + Class c=Class.forName(jsch.getConfig("md5")); + hash=(HASH)(c.newInstance()); + } + catch(Exception e){ System.err.println("getFingerPrint: "+e); } + return Util.getFingerPrint(hash, key); + } + public String getComment(){ return comment; } + public String getMarker(){ return marker; } + + boolean isMatched(String _host){ + return isIncluded(_host); + } + + private boolean isIncluded(String _host){ + int i=0; + String hosts=this.host; + int hostslen=hosts.length(); + int hostlen=_host.length(); + int j; + while(i0); + } + + void out_close(){ + try{ + if(out!=null && !out_dontclose) out.close(); + out=null; + } + catch(Exception ee){} + } + + public void close(){ + try{ + if(in!=null && !in_dontclose) in.close(); + in=null; + } + catch(Exception ee){} + + out_close(); + + try{ + if(out_ext!=null && !out_ext_dontclose) out_ext.close(); + out_ext=null; + } + catch(Exception ee){} + } + + /* + public void finalize() throws Throwable{ + try{ + if(in!=null) in.close(); + } + catch(Exception ee){} + try{ + if(out!=null) out.close(); + } + catch(Exception ee){} + try{ + if(out_ext!=null) out_ext.close(); + } + catch(Exception ee){} + } + */ +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/Identity.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/Identity.java new file mode 100644 index 00000000..b803dd91 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/Identity.java @@ -0,0 +1,83 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public interface Identity{ + + /** + * Decrypts this identity with the specified pass-phrase. + * @param passphrase the pass-phrase for this identity. + * @return true if the decryption is succeeded + * or this identity is not cyphered. + */ + public boolean setPassphrase(byte[] passphrase) throws JSchException; + + /** + * Returns the public-key blob. + * @return the public-key blob + */ + public byte[] getPublicKeyBlob(); + + /** + * Signs on data with this identity, and returns the result. + * @param data data to be signed + * @return the signature + */ + public byte[] getSignature(byte[] data); + + /** + * @deprecated The decryption should be done automatically in #setPassphase(byte[] passphrase) + * @see #setPassphrase(byte[] passphrase) + */ + public boolean decrypt(); + + /** + * Returns the name of the key algorithm. + * @return "ssh-rsa" or "ssh-dss" + */ + public String getAlgName(); + + /** + * Returns the name of this identity. + * It will be useful to identify this object in the {@link IdentityRepository}. + */ + public String getName(); + + /** + * Returns true if this identity is cyphered. + * @return true if this identity is cyphered. + */ + public boolean isEncrypted(); + + /** + * Disposes internally allocated data, like byte array for the private key. + */ + public void clear(); +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/IdentityFile.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/IdentityFile.java new file mode 100644 index 00000000..9127ceb0 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/IdentityFile.java @@ -0,0 +1,129 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.io.*; + +class IdentityFile implements Identity{ + private JSch jsch; + private KeyPair kpair; + private String identity; + + static IdentityFile newInstance(String prvfile, String pubfile, JSch jsch) throws JSchException{ + KeyPair kpair = KeyPair.load(jsch, prvfile, pubfile); + return new IdentityFile(jsch, prvfile, kpair); + } + + static IdentityFile newInstance(String name, byte[] prvkey, byte[] pubkey, JSch jsch) throws JSchException{ + KeyPair kpair = KeyPair.load(jsch, prvkey, pubkey); + return new IdentityFile(jsch, name, kpair); + } + + private IdentityFile(JSch jsch, String name, KeyPair kpair) throws JSchException{ + this.jsch = jsch; + this.identity = name; + this.kpair = kpair; + } + + /** + * Decrypts this identity with the specified pass-phrase. + * @param passphrase the pass-phrase for this identity. + * @return true if the decryption is succeeded + * or this identity is not cyphered. + */ + public boolean setPassphrase(byte[] passphrase) throws JSchException{ + return kpair.decrypt(passphrase); + } + + /** + * Returns the public-key blob. + * @return the public-key blob + */ + public byte[] getPublicKeyBlob(){ + return kpair.getPublicKeyBlob(); + } + + /** + * Signs on data with this identity, and returns the result. + * @param data data to be signed + * @return the signature + */ + public byte[] getSignature(byte[] data){ + return kpair.getSignature(data); + } + + /** + * @deprecated This method should not be invoked. + * @see #setPassphrase(byte[] passphrase) + */ + public boolean decrypt(){ + throw new RuntimeException("not implemented"); + } + + /** + * Returns the name of the key algorithm. + * @return "ssh-rsa" or "ssh-dss" + */ + public String getAlgName(){ + return new String(kpair.getKeyTypeName()); + } + + /** + * Returns the name of this identity. + * It will be useful to identify this object in the {@link IdentityRepository}. + */ + public String getName(){ + return identity; + } + + /** + * Returns true if this identity is cyphered. + * @return true if this identity is cyphered. + */ + public boolean isEncrypted(){ + return kpair.isEncrypted(); + } + + /** + * Disposes internally allocated data, like byte array for the private key. + */ + public void clear(){ + kpair.dispose(); + kpair = null; + } + + /** + * Returns an instance of {@link KeyPair} used in this {@link Identity}. + * @return an instance of {@link KeyPair} used in this {@link Identity}. + */ + public KeyPair getKeyPair(){ + return kpair; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/IdentityRepository.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/IdentityRepository.java new file mode 100644 index 00000000..7ec71302 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/IdentityRepository.java @@ -0,0 +1,115 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.util.Vector; + +public interface IdentityRepository { + public static final int UNAVAILABLE=0; + public static final int NOTRUNNING=1; + public static final int RUNNING=2; + public String getName(); + public int getStatus(); + public Vector getIdentities(); + public boolean add(byte[] identity); + public boolean remove(byte[] blob); + public void removeAll(); + + /** + * JSch will accept ciphered keys, but some implementations of + * IdentityRepository can not. For example, IdentityRepository for + * ssh-agent and pageant only accept plain keys. The following class has + * been introduced to cache ciphered keys for them, and pass them + * whenever they are de-ciphered. + */ + static class Wrapper implements IdentityRepository { + private IdentityRepository ir; + private Vector cache = new Vector(); + private boolean keep_in_cache = false; + Wrapper(IdentityRepository ir){ + this(ir, false); + } + Wrapper(IdentityRepository ir, boolean keep_in_cache){ + this.ir = ir; + this.keep_in_cache = keep_in_cache; + } + public String getName() { + return ir.getName(); + } + public int getStatus() { + return ir.getStatus(); + } + public boolean add(byte[] identity) { + return ir.add(identity); + } + public boolean remove(byte[] blob) { + return ir.remove(blob); + } + public void removeAll() { + cache.removeAllElements(); + ir.removeAll(); + } + public Vector getIdentities() { + Vector result = new Vector(); + for(int i = 0; i< cache.size(); i++){ + Identity identity = (Identity)(cache.elementAt(i)); + result.add(identity); + } + Vector tmp = ir.getIdentities(); + for(int i = 0; i< tmp.size(); i++){ + result.add(tmp.elementAt(i)); + } + return result; + } + void add(Identity identity) { + if(!keep_in_cache && + !identity.isEncrypted() && (identity instanceof IdentityFile)) { + try { + ir.add(((IdentityFile)identity).getKeyPair().forSSHAgent()); + } + catch(JSchException e){ + // an exception will not be thrown. + } + } + else + cache.addElement(identity); + } + void check() { + if(cache.size() > 0){ + Object[] identities = cache.toArray(); + for(int i = 0; i < identities.length; i++){ + Identity identity = (Identity)(identities[i]); + cache.removeElement(identity); + add(identity); + } + } + } + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/JSch.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/JSch.java new file mode 100644 index 00000000..ddca7ffc --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/JSch.java @@ -0,0 +1,573 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.io.InputStream; +import java.util.Vector; + +public class JSch{ + /** + * The version number. + */ + public static final String VERSION = "0.1.50"; + + static java.util.Hashtable config=new java.util.Hashtable(); + static{ + config.put("kex", "diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1"); + config.put("server_host_key", "ssh-rsa,ssh-dss"); + + config.put("cipher.s2c", + "aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc"); + config.put("cipher.c2s", + "aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-cbc,aes256-cbc"); + + config.put("mac.s2c", "hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96"); + config.put("mac.c2s", "hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96"); + config.put("compression.s2c", "none"); + config.put("compression.c2s", "none"); + + config.put("lang.s2c", ""); + config.put("lang.c2s", ""); + + config.put("compression_level", "6"); + + config.put("diffie-hellman-group-exchange-sha1", + "com.jcraft.jsch.DHGEX"); + config.put("diffie-hellman-group1-sha1", + "com.jcraft.jsch.DHG1"); + config.put("diffie-hellman-group14-sha1", + "com.jcraft.jsch.DHG14"); + config.put("diffie-hellman-group-exchange-sha256", + "com.jcraft.jsch.DHGEX256"); // avaibale since JDK1.4.2. + + config.put("dh", "com.jcraft.jsch.jce.DH"); + config.put("3des-cbc", "com.jcraft.jsch.jce.TripleDESCBC"); + config.put("blowfish-cbc", "com.jcraft.jsch.jce.BlowfishCBC"); + config.put("hmac-sha1", "com.jcraft.jsch.jce.HMACSHA1"); + config.put("hmac-sha1-96", "com.jcraft.jsch.jce.HMACSHA196"); + config.put("hmac-sha2-256", "com.jcraft.jsch.jce.HMACSHA256"); + // The "hmac-sha2-512" will require the key-length 2048 for DH, + // but Sun's JCE has not allowed to use such a long key. + //config.put("hmac-sha2-512", "com.jcraft.jsch.jce.HMACSHA512"); + config.put("hmac-md5", "com.jcraft.jsch.jce.HMACMD5"); + config.put("hmac-md5-96", "com.jcraft.jsch.jce.HMACMD596"); + config.put("sha-1", "com.jcraft.jsch.jce.SHA1"); + config.put("sha-256", "com.jcraft.jsch.jce.SHA256"); + config.put("md5", "com.jcraft.jsch.jce.MD5"); + config.put("signature.dss", "com.jcraft.jsch.jce.SignatureDSA"); + config.put("signature.rsa", "com.jcraft.jsch.jce.SignatureRSA"); + config.put("keypairgen.dsa", "com.jcraft.jsch.jce.KeyPairGenDSA"); + config.put("keypairgen.rsa", "com.jcraft.jsch.jce.KeyPairGenRSA"); + config.put("random", "com.jcraft.jsch.jce.Random"); + + config.put("none", "com.jcraft.jsch.CipherNone"); + + config.put("aes128-cbc", "com.jcraft.jsch.jce.AES128CBC"); + config.put("aes192-cbc", "com.jcraft.jsch.jce.AES192CBC"); + config.put("aes256-cbc", "com.jcraft.jsch.jce.AES256CBC"); + + config.put("aes128-ctr", "com.jcraft.jsch.jce.AES128CTR"); + config.put("aes192-ctr", "com.jcraft.jsch.jce.AES192CTR"); + config.put("aes256-ctr", "com.jcraft.jsch.jce.AES256CTR"); + config.put("3des-ctr", "com.jcraft.jsch.jce.TripleDESCTR"); + config.put("arcfour", "com.jcraft.jsch.jce.ARCFOUR"); + config.put("arcfour128", "com.jcraft.jsch.jce.ARCFOUR128"); + config.put("arcfour256", "com.jcraft.jsch.jce.ARCFOUR256"); + + config.put("userauth.none", "com.jcraft.jsch.UserAuthNone"); + config.put("userauth.password", "com.jcraft.jsch.UserAuthPassword"); + config.put("userauth.keyboard-interactive", "com.jcraft.jsch.UserAuthKeyboardInteractive"); + config.put("userauth.publickey", "com.jcraft.jsch.UserAuthPublicKey"); + config.put("userauth.gssapi-with-mic", "com.jcraft.jsch.UserAuthGSSAPIWithMIC"); + config.put("gssapi-with-mic.krb5", "com.jcraft.jsch.jgss.GSSContextKrb5"); + + config.put("zlib", "com.jcraft.jsch.jcraft.Compression"); + config.put("zlib@openssh.com", "com.jcraft.jsch.jcraft.Compression"); + + config.put("StrictHostKeyChecking", "ask"); + config.put("HashKnownHosts", "no"); + + config.put("PreferredAuthentications", "gssapi-with-mic,publickey,keyboard-interactive,password"); + + config.put("CheckCiphers", "aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256"); + config.put("CheckKexes", "diffie-hellman-group14-sha1"); + + config.put("MaxAuthTries", "6"); + config.put("ClearAllForwardings", "no"); + } + + private java.util.Vector sessionPool = new java.util.Vector(); + + private IdentityRepository defaultIdentityRepository = + new LocalIdentityRepository(this); + + private IdentityRepository identityRepository = defaultIdentityRepository; + + private ConfigRepository configRepository = null; + + /** + * Sets the identityRepository, which will be referred + * in the public key authentication. + * + * @param identityRepository if null is given, + * the default repository, which usually refers to ~/.ssh/, will be used. + * + * @see #getIdentityRepository() + */ + public synchronized void setIdentityRepository(IdentityRepository identityRepository){ + if(identityRepository == null){ + this.identityRepository = defaultIdentityRepository; + } + else{ + this.identityRepository = identityRepository; + } + } + + public synchronized IdentityRepository getIdentityRepository(){ + return this.identityRepository; + } + + public ConfigRepository getConfigRepository() { + return this.configRepository; + } + + public void setConfigRepository(ConfigRepository configRepository) { + this.configRepository = configRepository; + } + + private HostKeyRepository known_hosts=null; + + private static final Logger DEVNULL=new Logger(){ + public boolean isEnabled(int level){return false;} + public void log(int level, String message){} + }; + static Logger logger=DEVNULL; + + public JSch(){ + + try{ + String osname=(String)(System.getProperties().get("os.name")); + if(osname!=null && osname.equals("Mac OS X")){ + config.put("hmac-sha1", "com.jcraft.jsch.jcraft.HMACSHA1"); + config.put("hmac-md5", "com.jcraft.jsch.jcraft.HMACMD5"); + config.put("hmac-md5-96", "com.jcraft.jsch.jcraft.HMACMD596"); + config.put("hmac-sha1-96", "com.jcraft.jsch.jcraft.HMACSHA196"); + } + } + catch(Exception e){ + } + + } + + /** + * Instantiates the Session object with + * host. The user name and port number will be retrieved from + * ConfigRepository. If user name is not given, + * the system property "user.name" will be referred. + * + * @param host hostname + * + * @throws JSchException + * if username or host are invalid. + * + * @return the instance of Session class. + * + * @see #getSession(String username, String host, int port) + * @see com.jcraft.jsch.Session + * @see com.jcraft.jsch.ConfigRepository + */ + public Session getSession(String host) + throws JSchException { + return getSession(null, host, 22); + } + + /** + * Instantiates the Session object with + * username and host. + * The TCP port 22 will be used in making the connection. + * Note that the TCP connection must not be established + * until Session#connect(). + * + * @param username user name + * @param host hostname + * + * @throws JSchException + * if username or host are invalid. + * + * @return the instance of Session class. + * + * @see #getSession(String username, String host, int port) + * @see com.jcraft.jsch.Session + */ + public Session getSession(String username, String host) + throws JSchException { + return getSession(username, host, 22); + } + + /** + * Instantiates the Session object with given + * username, host and port. + * Note that the TCP connection must not be established + * until Session#connect(). + * + * @param username user name + * @param host hostname + * @param port port number + * + * @throws JSchException + * if username or host are invalid. + * + * @return the instance of Session class. + * + * @see #getSession(String username, String host, int port) + * @see com.jcraft.jsch.Session + */ + public Session getSession(String username, String host, int port) throws JSchException { + if(host==null){ + throw new JSchException("host must not be null."); + } + Session s = new Session(this, username, host, port); + return s; + } + + protected void addSession(Session session){ + synchronized(sessionPool){ + sessionPool.addElement(session); + } + } + + protected boolean removeSession(Session session){ + synchronized(sessionPool){ + return sessionPool.remove(session); + } + } + + /** + * Sets the hostkey repository. + * + * @param hkrepo + * + * @see com.jcraft.jsch.HostKeyRepository + * @see com.jcraft.jsch.KnownHosts + */ + public void setHostKeyRepository(HostKeyRepository hkrepo){ + known_hosts=hkrepo; + } + + /** + * Sets the instance of KnownHosts, which refers + * to filename. + * + * @param filename filename of known_hosts file. + * + * @throws JSchException + * if the given filename is invalid. + * + * @see com.jcraft.jsch.KnownHosts + */ + public void setKnownHosts(String filename) throws JSchException{ + if(known_hosts==null) known_hosts=new KnownHosts(this); + if(known_hosts instanceof KnownHosts){ + synchronized(known_hosts){ + ((KnownHosts)known_hosts).setKnownHosts(filename); + } + } + } + + /** + * Sets the instance of KnownHosts generated with + * stream. + * + * @param stream the instance of InputStream from known_hosts file. + * + * @throws JSchException + * if an I/O error occurs. + * + * @see com.jcraft.jsch.KnownHosts + */ + public void setKnownHosts(InputStream stream) throws JSchException{ + if(known_hosts==null) known_hosts=new KnownHosts(this); + if(known_hosts instanceof KnownHosts){ + synchronized(known_hosts){ + ((KnownHosts)known_hosts).setKnownHosts(stream); + } + } + } + + /** + * Returns the current hostkey repository. + * By the default, this method will the instance of KnownHosts. + * + * @return current hostkey repository. + * + * @see com.jcraft.jsch.HostKeyRepository + * @see com.jcraft.jsch.KnownHosts + */ + public HostKeyRepository getHostKeyRepository(){ + if(known_hosts==null) known_hosts=new KnownHosts(this); + return known_hosts; + } + + /** + * Sets the private key, which will be referred in + * the public key authentication. + * + * @param prvkey filename of the private key. + * + * @throws JSchException if prvkey is invalid. + * + * @see #addIdentity(String prvkey, String passphrase) + */ + public void addIdentity(String prvkey) throws JSchException{ + addIdentity(prvkey, (byte[])null); + } + + /** + * Sets the private key, which will be referred in + * the public key authentication. + * Before registering it into identityRepository, + * it will be deciphered with passphrase. + * + * @param prvkey filename of the private key. + * @param passphrase passphrase for prvkey. + * + * @throws JSchException if passphrase is not right. + * + * @see #addIdentity(String prvkey, byte[] passphrase) + */ + public void addIdentity(String prvkey, String passphrase) throws JSchException{ + byte[] _passphrase=null; + if(passphrase!=null){ + _passphrase=Util.str2byte(passphrase); + } + addIdentity(prvkey, _passphrase); + if(_passphrase!=null) + Util.bzero(_passphrase); + } + + /** + * Sets the private key, which will be referred in + * the public key authentication. + * Before registering it into identityRepository, + * it will be deciphered with passphrase. + * + * @param prvkey filename of the private key. + * @param passphrase passphrase for prvkey. + * + * @throws JSchException if passphrase is not right. + * + * @see #addIdentity(String prvkey, String pubkey, byte[] passphrase) + */ + public void addIdentity(String prvkey, byte[] passphrase) throws JSchException{ + Identity identity=IdentityFile.newInstance(prvkey, null, this); + addIdentity(identity, passphrase); + } + + /** + * Sets the private key, which will be referred in + * the public key authentication. + * Before registering it into identityRepository, + * it will be deciphered with passphrase. + * + * @param prvkey filename of the private key. + * @param pubkey filename of the public key. + * @param passphrase passphrase for prvkey. + * + * @throws JSchException if passphrase is not right. + */ + public void addIdentity(String prvkey, String pubkey, byte[] passphrase) throws JSchException{ + Identity identity=IdentityFile.newInstance(prvkey, pubkey, this); + addIdentity(identity, passphrase); + } + + /** + * Sets the private key, which will be referred in + * the public key authentication. + * Before registering it into identityRepository, + * it will be deciphered with passphrase. + * + * @param name name of the identity to be used to + retrieve it in the identityRepository. + * @param prvkey private key in byte array. + * @param pubkey public key in byte array. + * @param passphrase passphrase for prvkey. + * + */ + public void addIdentity(String name, byte[]prvkey, byte[]pubkey, byte[] passphrase) throws JSchException{ + Identity identity=IdentityFile.newInstance(name, prvkey, pubkey, this); + addIdentity(identity, passphrase); + } + + /** + * Sets the private key, which will be referred in + * the public key authentication. + * Before registering it into identityRepository, + * it will be deciphered with passphrase. + * + * @param identity private key. + * @param passphrase passphrase for identity. + * + * @throws JSchException if passphrase is not right. + */ + public void addIdentity(Identity identity, byte[] passphrase) throws JSchException{ + if(passphrase!=null){ + try{ + byte[] goo=new byte[passphrase.length]; + System.arraycopy(passphrase, 0, goo, 0, passphrase.length); + passphrase=goo; + identity.setPassphrase(passphrase); + } + finally{ + Util.bzero(passphrase); + } + } + + if(identityRepository instanceof LocalIdentityRepository){ + ((LocalIdentityRepository)identityRepository).add(identity); + } + else if(identity instanceof IdentityFile && !identity.isEncrypted()) { + identityRepository.add(((IdentityFile)identity).getKeyPair().forSSHAgent()); + } + else { + synchronized(this){ + if(!(identityRepository instanceof IdentityRepository.Wrapper)){ + setIdentityRepository(new IdentityRepository.Wrapper(identityRepository)); + } + } + ((IdentityRepository.Wrapper)identityRepository).add(identity); + } + } + + /** + * @deprecated use #removeIdentity(Identity identity) + */ + public void removeIdentity(String name) throws JSchException{ + Vector identities = identityRepository.getIdentities(); + for(int i=0; iidentity is invalid. + */ + public void removeIdentity(Identity identity) throws JSchException{ + identityRepository.remove(identity.getPublicKeyBlob()); + } + + /** + * Lists names of identities included in the identityRepository. + * + * @return names of identities + * + * @throws JSchException if identityReposory has problems. + */ + public Vector getIdentityNames() throws JSchException{ + Vector foo=new Vector(); + Vector identities = identityRepository.getIdentities(); + for(int i=0; iclient"+ + " "+guess[PROPOSAL_ENC_ALGS_STOC]+ + " "+guess[PROPOSAL_MAC_ALGS_STOC]+ + " "+guess[PROPOSAL_COMP_ALGS_STOC]); + JSch.getLogger().log(Logger.INFO, + "kex: client->server"+ + " "+guess[PROPOSAL_ENC_ALGS_CTOS]+ + " "+guess[PROPOSAL_MAC_ALGS_CTOS]+ + " "+guess[PROPOSAL_COMP_ALGS_CTOS]); + } + + return guess; + } + + public String getFingerPrint(){ + HASH hash=null; + try{ + Class c=Class.forName(session.getConfig("md5")); + hash=(HASH)(c.newInstance()); + } + catch(Exception e){ System.err.println("getFingerPrint: "+e); } + return Util.getFingerPrint(hash, getHostKey()); + } + byte[] getK(){ return K; } + byte[] getH(){ return H; } + HASH getHash(){ return sha; } + byte[] getHostKey(){ return K_S; } + + /* + * It seems JCE included in Oracle's Java7u6(and later) has suddenly changed + * its behavior. The secrete generated by KeyAgreement#generateSecret() + * may start with 0, even if it is a positive value. + */ + protected byte[] normalize(byte[] secret) { + if(secret.length > 1 && + secret[0] == 0 && (secret[1]&0x80) == 0) { + byte[] tmp=new byte[secret.length-1]; + System.arraycopy(secret, 1, tmp, 0, tmp.length); + secret=tmp; + } + return secret; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPair.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPair.java new file mode 100644 index 00000000..6a905de5 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPair.java @@ -0,0 +1,1104 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.io.FileOutputStream; +import java.io.FileInputStream; +import java.io.File; +import java.io.IOException; + +public abstract class KeyPair{ + public static final int ERROR=0; + public static final int DSA=1; + public static final int RSA=2; + public static final int UNKNOWN=3; + + static final int VENDOR_OPENSSH=0; + static final int VENDOR_FSECURE=1; + static final int VENDOR_PUTTY=2; + + int vendor=VENDOR_OPENSSH; + + private static final byte[] cr=Util.str2byte("\n"); + + public static KeyPair genKeyPair(JSch jsch, int type) throws JSchException{ + return genKeyPair(jsch, type, 1024); + } + public static KeyPair genKeyPair(JSch jsch, int type, int key_size) throws JSchException{ + KeyPair kpair=null; + if(type==DSA){ kpair=new KeyPairDSA(jsch); } + else if(type==RSA){ kpair=new KeyPairRSA(jsch); } + if(kpair!=null){ + kpair.generate(key_size); + } + return kpair; + } + + abstract void generate(int key_size) throws JSchException; + + abstract byte[] getBegin(); + abstract byte[] getEnd(); + abstract int getKeySize(); + + public abstract byte[] getSignature(byte[] data); + public abstract Signature getVerifier(); + + public abstract byte[] forSSHAgent() throws JSchException; + + public String getPublicKeyComment(){ + return publicKeyComment; + } + + public void setPublicKeyComment(String publicKeyComment){ + this.publicKeyComment = publicKeyComment; + } + + protected String publicKeyComment = "no comment"; + + JSch jsch=null; + private Cipher cipher; + private HASH hash; + private Random random; + + private byte[] passphrase; + + public KeyPair(JSch jsch){ + this.jsch=jsch; + } + + static byte[][] header={Util.str2byte("Proc-Type: 4,ENCRYPTED"), + Util.str2byte("DEK-Info: DES-EDE3-CBC,")}; + + abstract byte[] getPrivateKey(); + + /** + * Writes the plain private key to the given output stream. + * @param out output stream + * @see #writePrivateKey(java.io.OutputStream out, byte[] passphrase) + */ + public void writePrivateKey(java.io.OutputStream out){ + this.writePrivateKey(out, null); + } + + /** + * Writes the cyphered private key to the given output stream. + * @param out output stream + * @param passphrase a passphrase to encrypt the private key + */ + public void writePrivateKey(java.io.OutputStream out, byte[] passphrase){ + if(passphrase == null) + passphrase = this.passphrase; + + byte[] plain=getPrivateKey(); + byte[][] _iv=new byte[1][]; + byte[] encoded=encrypt(plain, _iv, passphrase); + if(encoded!=plain) + Util.bzero(plain); + byte[] iv=_iv[0]; + byte[] prv=Util.toBase64(encoded, 0, encoded.length); + + try{ + out.write(getBegin()); out.write(cr); + if(passphrase!=null){ + out.write(header[0]); out.write(cr); + out.write(header[1]); + for(int i=0; i>>4)&0x0f))); + out.write(b2a((byte)(iv[i]&0x0f))); + } + out.write(cr); + out.write(cr); + } + int i=0; + while(i0){ + len>>>=8; + i++; + } + return i; + } + + int writeLength(byte[] data, int index, int len){ + int i=countLength(len)-1; + if(i==0){ + data[index++]=(byte)len; + return index; + } + data[index++]=(byte)(0x80|i); + int j=index+i; + while(i>0){ + data[index+i-1]=(byte)(len&0xff); + len>>>=8; + i--; + } + return j; + } + + private Random genRandom(){ + if(random==null){ + try{ + Class c=Class.forName(jsch.getConfig("random")); + random=(Random)(c.newInstance()); + } + catch(Exception e){ System.err.println("connect: random "+e); } + } + return random; + } + + private HASH genHash(){ + try{ + Class c=Class.forName(jsch.getConfig("md5")); + hash=(HASH)(c.newInstance()); + hash.init(); + } + catch(Exception e){ + } + return hash; + } + private Cipher genCipher(){ + try{ + Class c; + c=Class.forName(jsch.getConfig("3des-cbc")); + cipher=(Cipher)(c.newInstance()); + } + catch(Exception e){ + } + return cipher; + } + + /* + hash is MD5 + h(0) <- hash(passphrase, iv); + h(n) <- hash(h(n-1), passphrase, iv); + key <- (h(0),...,h(n))[0,..,key.length]; + */ + synchronized byte[] genKey(byte[] passphrase, byte[] iv){ + if(cipher==null) cipher=genCipher(); + if(hash==null) hash=genHash(); + + byte[] key=new byte[cipher.getBlockSize()]; + int hsize=hash.getBlockSize(); + byte[] hn=new byte[key.length/hsize*hsize+ + (key.length%hsize==0?0:hsize)]; + try{ + byte[] tmp=null; + if(vendor==VENDOR_OPENSSH){ + for(int index=0; index+hsize<=hn.length;){ + if(tmp!=null){ hash.update(tmp, 0, tmp.length); } + hash.update(passphrase, 0, passphrase.length); + hash.update(iv, 0, iv.length > 8 ? 8: iv.length); + tmp=hash.digest(); + System.arraycopy(tmp, 0, hn, index, tmp.length); + index+=tmp.length; + } + System.arraycopy(hn, 0, key, 0, key.length); + } + else if(vendor==VENDOR_FSECURE){ + for(int index=0; index+hsize<=hn.length;){ + if(tmp!=null){ hash.update(tmp, 0, tmp.length); } + hash.update(passphrase, 0, passphrase.length); + tmp=hash.digest(); + System.arraycopy(tmp, 0, hn, index, tmp.length); + index+=tmp.length; + } + System.arraycopy(hn, 0, key, 0, key.length); + } + else if(vendor==VENDOR_PUTTY){ + Class c=Class.forName((String)jsch.getConfig("sha-1")); + HASH sha1=(HASH)(c.newInstance()); + tmp = new byte[4]; + key = new byte[20*2]; + for(int i = 0; i < 2; i++){ + sha1.init(); + tmp[3]=(byte)i; + sha1.update(tmp, 0, tmp.length); + sha1.update(passphrase, 0, passphrase.length); + System.arraycopy(sha1.digest(), 0, key, i*20, 20); + } + } + } + catch(Exception e){ + System.err.println(e); + } + return key; + } + + /** + * @deprecated use #writePrivateKey(java.io.OutputStream out, byte[] passphrase) + */ + public void setPassphrase(String passphrase){ + if(passphrase==null || passphrase.length()==0){ + setPassphrase((byte[])null); + } + else{ + setPassphrase(Util.str2byte(passphrase)); + } + } + + /** + * @deprecated use #writePrivateKey(String name, byte[] passphrase) + */ + public void setPassphrase(byte[] passphrase){ + if(passphrase!=null && passphrase.length==0) + passphrase=null; + this.passphrase=passphrase; + } + + private boolean encrypted=false; + private byte[] data=null; + private byte[] iv=null; + private byte[] publickeyblob=null; + + public boolean isEncrypted(){ return encrypted; } + public boolean decrypt(String _passphrase){ + if(_passphrase==null || _passphrase.length()==0){ + return !encrypted; + } + return decrypt(Util.str2byte(_passphrase)); + } + public boolean decrypt(byte[] _passphrase){ + + if(!encrypted){ + return true; + } + if(_passphrase==null){ + return !encrypted; + } + byte[] bar=new byte[_passphrase.length]; + System.arraycopy(_passphrase, 0, bar, 0, bar.length); + _passphrase=bar; + byte[] foo=decrypt(data, _passphrase, iv); + Util.bzero(_passphrase); + if(parse(foo)){ + encrypted=false; + } + return !encrypted; + } + + public static KeyPair load(JSch jsch, String prvkey) throws JSchException{ + String pubkey=prvkey+".pub"; + if(!new File(pubkey).exists()){ + pubkey=null; + } + return load(jsch, prvkey, pubkey); + } + public static KeyPair load(JSch jsch, String prvfile, String pubfile) throws JSchException{ + + byte[] prvkey=null; + byte[] pubkey=null; + + try{ + prvkey = Util.fromFile(prvfile); + } + catch(IOException e){ + throw new JSchException(e.toString(), (Throwable)e); + } + + String _pubfile=pubfile; + if(pubfile==null){ + _pubfile=prvfile+".pub"; + } + + try{ + pubkey = Util.fromFile(_pubfile); + } + catch(IOException e){ + if(pubfile!=null){ + throw new JSchException(e.toString(), (Throwable)e); + } + } + + try { + return load(jsch, prvkey, pubkey); + } + finally { + Util.bzero(prvkey); + } + } + + public static KeyPair load(JSch jsch, byte[] prvkey, byte[] pubkey) throws JSchException{ + + byte[] iv=new byte[8]; // 8 + boolean encrypted=true; + byte[] data=null; + + byte[] publickeyblob=null; + + int type=ERROR; + int vendor=VENDOR_OPENSSH; + String publicKeyComment = ""; + Cipher cipher=null; + + // prvkey from "ssh-add" command on the remote. + if(pubkey==null && + prvkey!=null && + (prvkey.length>11 && + prvkey[0]==0 && prvkey[1]==0 && prvkey[2]==0 && prvkey[3]==7)){ + + Buffer buf=new Buffer(prvkey); + buf.skip(prvkey.length); // for using Buffer#available() + String _type = new String(buf.getString()); // ssh-rsa or ssh-dss + buf.rewind(); + + KeyPair kpair=null; + if(_type.equals("ssh-rsa")){ + kpair=KeyPairRSA.fromSSHAgent(jsch, buf); + } + else if(_type.equals("ssh-dss")){ + kpair=KeyPairDSA.fromSSHAgent(jsch, buf); + } + else{ + throw new JSchException("privatekey: invalid key "+new String(prvkey, 4, 7)); + } + return kpair; + } + + try{ + byte[] buf=prvkey; + + if(buf!=null){ + KeyPair ppk = loadPPK(jsch, buf); + if(ppk !=null) + return ppk; + } + + int len = (buf!=null ? buf.length : 0); + int i=0; + + // skip garbage lines. + while(i= len) + throw new JSchException("invalid privatekey: "+prvkey); + if(buf[i]=='D'&& buf[i+1]=='S'&& buf[i+2]=='A'){ type=DSA; } + else if(buf[i]=='R'&& buf[i+1]=='S'&& buf[i+2]=='A'){ type=RSA; } + else if(buf[i]=='S'&& buf[i+1]=='S'&& buf[i+2]=='H'){ // FSecure + type=UNKNOWN; + vendor=VENDOR_FSECURE; + } + else{ + throw new JSchException("invalid privatekey: "+prvkey); + } + i+=3; + continue; + } + if(buf[i]=='A'&& i+7 0) + data=Util.fromBase64(_buf, start, i-start); + + Util.bzero(_buf); + } + + if(data!=null && + data.length>4 && // FSecure + data[0]==(byte)0x3f && + data[1]==(byte)0x6f && + data[2]==(byte)0xf9 && + data[3]==(byte)0xeb){ + + Buffer _buf=new Buffer(data); + _buf.getInt(); // 0x3f6ff9be + _buf.getInt(); + byte[]_type=_buf.getString(); + //System.err.println("type: "+new String(_type)); + String _cipher=Util.byte2str(_buf.getString()); + //System.err.println("cipher: "+_cipher); + if(_cipher.equals("3des-cbc")){ + _buf.getInt(); + byte[] foo=new byte[data.length-_buf.getOffSet()]; + _buf.getByte(foo); + data=foo; + encrypted=true; + throw new JSchException("unknown privatekey format: "+prvkey); + } + else if(_cipher.equals("none")){ + _buf.getInt(); + _buf.getInt(); + + encrypted=false; + + byte[] foo=new byte[data.length-_buf.getOffSet()]; + _buf.getByte(foo); + data=foo; + } + } + + if(pubkey!=null){ + try{ + buf=pubkey; + len=buf.length; + if(buf.length>4 && // FSecure's public key + buf[0]=='-' && buf[1]=='-' && buf[2]=='-' && buf[3]=='-'){ + + boolean valid=true; + i=0; + do{i++;}while(buf.length>i && buf[i]!=0x0a); + if(buf.length<=i) {valid=false;} + + while(valid){ + if(buf[i]==0x0a){ + boolean inheader=false; + for(int j=i+1; j7){ + if(buf[4]=='d'){ type=DSA; } + else if(buf[4]=='r'){ type=RSA; } + } + i=0; + while(i0){ + while(buf.length > i){ + if(buf[i++] == 0x0d){ + if(data == null){ + data = new byte[i - index - 1]; + System.arraycopy(buf, index, data, 0, i - index - 1); + } + else { + byte[] tmp = new byte[data.length + i - index - 1]; + System.arraycopy(data, 0, tmp, 0, data.length); + System.arraycopy(buf, index, tmp, data.length, i - index -1); + for(int j = 0; j < data.length; j++) data[j] = 0; // clear + data = tmp; + } + break; + } + } + if(buf[i]==0x0a) + i++; + index=i; + } + + if(data != null) + buffer.index = index; + + return data; + } + + private static boolean parseHeader(Buffer buffer, java.util.Hashtable v){ + byte[] buf = buffer.buffer; + int index = buffer.index; + String key = null; + String value = null; + for(int i = index; i < buf.length; i++){ + if(buf[i] == 0x0d){ + break; + } + if(buf[i] == ':'){ + key = new String(buf, index, i - index); + i++; + if(i < buf.length && buf[i] == ' '){ + i++; + } + index = i; + break; + } + } + + if(key == null) + return false; + + for(int i = index; i < buf.length; i++){ + if(buf[i] == 0x0d){ + value = new String(buf, index, i - index); + i++; + if(i < buf.length && buf[i] == 0x0a){ + i++; + } + index = i; + break; + } + } + + if(value != null){ + v.put(key, value); + buffer.index = index; + } + + return (key != null && value != null); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairDSA.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairDSA.java new file mode 100644 index 00000000..4b85dfe8 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairDSA.java @@ -0,0 +1,332 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public class KeyPairDSA extends KeyPair{ + private byte[] P_array; + private byte[] Q_array; + private byte[] G_array; + private byte[] pub_array; + private byte[] prv_array; + + //private int key_size=0; + private int key_size=1024; + + public KeyPairDSA(JSch jsch){ + this(jsch, null, null, null, null, null); + } + + public KeyPairDSA(JSch jsch, + byte[] P_array, + byte[] Q_array, + byte[] G_array, + byte[] pub_array, + byte[] prv_array){ + super(jsch); + this.P_array = P_array; + this.Q_array = Q_array; + this.G_array = G_array; + this.pub_array = pub_array; + this.prv_array = prv_array; + if(P_array!=null) + key_size = (new java.math.BigInteger(P_array)).bitLength(); + } + + void generate(int key_size) throws JSchException{ + this.key_size=key_size; + try{ + Class c=Class.forName(jsch.getConfig("keypairgen.dsa")); + KeyPairGenDSA keypairgen=(KeyPairGenDSA)(c.newInstance()); + keypairgen.init(key_size); + P_array=keypairgen.getP(); + Q_array=keypairgen.getQ(); + G_array=keypairgen.getG(); + pub_array=keypairgen.getY(); + prv_array=keypairgen.getX(); + + keypairgen=null; + } + catch(Exception e){ + //System.err.println("KeyPairDSA: "+e); + if(e instanceof Throwable) + throw new JSchException(e.toString(), (Throwable)e); + throw new JSchException(e.toString()); + } + } + + private static final byte[] begin=Util.str2byte("-----BEGIN DSA PRIVATE KEY-----"); + private static final byte[] end=Util.str2byte("-----END DSA PRIVATE KEY-----"); + + byte[] getBegin(){ return begin; } + byte[] getEnd(){ return end; } + + byte[] getPrivateKey(){ + int content= + 1+countLength(1) + 1 + // INTEGER + 1+countLength(P_array.length) + P_array.length + // INTEGER P + 1+countLength(Q_array.length) + Q_array.length + // INTEGER Q + 1+countLength(G_array.length) + G_array.length + // INTEGER G + 1+countLength(pub_array.length) + pub_array.length + // INTEGER pub + 1+countLength(prv_array.length) + prv_array.length; // INTEGER prv + + int total= + 1+countLength(content)+content; // SEQUENCE + + byte[] plain=new byte[total]; + int index=0; + index=writeSEQUENCE(plain, index, content); + index=writeINTEGER(plain, index, new byte[1]); // 0 + index=writeINTEGER(plain, index, P_array); + index=writeINTEGER(plain, index, Q_array); + index=writeINTEGER(plain, index, G_array); + index=writeINTEGER(plain, index, pub_array); + index=writeINTEGER(plain, index, prv_array); + return plain; + } + + boolean parse(byte[] plain){ + try{ + + if(vendor==VENDOR_FSECURE){ + if(plain[0]!=0x30){ // FSecure + Buffer buf=new Buffer(plain); + buf.getInt(); + P_array=buf.getMPIntBits(); + G_array=buf.getMPIntBits(); + Q_array=buf.getMPIntBits(); + pub_array=buf.getMPIntBits(); + prv_array=buf.getMPIntBits(); + if(P_array!=null) + key_size = (new java.math.BigInteger(P_array)).bitLength(); + return true; + } + return false; + } + else if(vendor==VENDOR_PUTTY){ + Buffer buf=new Buffer(plain); + buf.skip(plain.length); + + try { + byte[][] tmp = buf.getBytes(1, ""); + prv_array = tmp[0]; + } + catch(JSchException e){ + return false; + } + + return true; + } + + int index=0; + int length=0; + + if(plain[index]!=0x30)return false; + index++; // SEQUENCE + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + + if(plain[index]!=0x02)return false; + index++; // INTEGER + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + P_array=new byte[length]; + System.arraycopy(plain, index, P_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + Q_array=new byte[length]; + System.arraycopy(plain, index, Q_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + G_array=new byte[length]; + System.arraycopy(plain, index, G_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + pub_array=new byte[length]; + System.arraycopy(plain, index, pub_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + prv_array=new byte[length]; + System.arraycopy(plain, index, prv_array, 0, length); + index+=length; + + if(P_array!=null) + key_size = (new java.math.BigInteger(P_array)).bitLength(); + } + catch(Exception e){ + //System.err.println(e); + //e.printStackTrace(); + return false; + } + return true; + } + + public byte[] getPublicKeyBlob(){ + byte[] foo=super.getPublicKeyBlob(); + if(foo!=null) return foo; + + if(P_array==null) return null; + byte[][] tmp = new byte[5][]; + tmp[0] = sshdss; + tmp[1] = P_array; + tmp[2] = Q_array; + tmp[3] = G_array; + tmp[4] = pub_array; + return Buffer.fromBytes(tmp).buffer; + } + + private static final byte[] sshdss=Util.str2byte("ssh-dss"); + byte[] getKeyTypeName(){return sshdss;} + public int getKeyType(){return DSA;} + + public int getKeySize(){ + return key_size; + } + + public byte[] getSignature(byte[] data){ + try{ + Class c=Class.forName((String)jsch.getConfig("signature.dss")); + SignatureDSA dsa=(SignatureDSA)(c.newInstance()); + dsa.init(); + dsa.setPrvKey(prv_array, P_array, Q_array, G_array); + + dsa.update(data); + byte[] sig = dsa.sign(); + byte[][] tmp = new byte[2][]; + tmp[0] = sshdss; + tmp[1] = sig; + return Buffer.fromBytes(tmp).buffer; + } + catch(Exception e){ + //System.err.println("e "+e); + } + return null; + } + + public Signature getVerifier(){ + try{ + Class c=Class.forName((String)jsch.getConfig("signature.dss")); + SignatureDSA dsa=(SignatureDSA)(c.newInstance()); + dsa.init(); + + if(pub_array == null && P_array == null && getPublicKeyBlob()!=null){ + Buffer buf = new Buffer(getPublicKeyBlob()); + buf.getString(); + P_array = buf.getString(); + Q_array = buf.getString(); + G_array = buf.getString(); + pub_array = buf.getString(); + } + + dsa.setPubKey(pub_array, P_array, Q_array, G_array); + return dsa; + } + catch(Exception e){ + //System.err.println("e "+e); + } + return null; + } + + static KeyPair fromSSHAgent(JSch jsch, Buffer buf) throws JSchException { + + byte[][] tmp = buf.getBytes(7, "invalid key format"); + + byte[] P_array = tmp[1]; + byte[] Q_array = tmp[2]; + byte[] G_array = tmp[3]; + byte[] pub_array = tmp[4]; + byte[] prv_array = tmp[5]; + KeyPairDSA kpair = new KeyPairDSA(jsch, + P_array, Q_array, G_array, + pub_array, prv_array); + kpair.publicKeyComment = new String(tmp[6]); + kpair.vendor=VENDOR_OPENSSH; + return kpair; + } + + public byte[] forSSHAgent() throws JSchException { + if(isEncrypted()){ + throw new JSchException("key is encrypted."); + } + Buffer buf = new Buffer(); + buf.putString(sshdss); + buf.putString(P_array); + buf.putString(Q_array); + buf.putString(G_array); + buf.putString(pub_array); + buf.putString(prv_array); + buf.putString(Util.str2byte(publicKeyComment)); + byte[] result = new byte[buf.getLength()]; + buf.getByte(result, 0, result.length); + return result; + } + + public void dispose(){ + super.dispose(); + Util.bzero(prv_array); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairGenDSA.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairGenDSA.java new file mode 100644 index 00000000..f6507f24 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairGenDSA.java @@ -0,0 +1,39 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public interface KeyPairGenDSA{ + void init(int key_size) throws Exception; + byte[] getX(); + byte[] getY(); + byte[] getP(); + byte[] getQ(); + byte[] getG(); +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairGenRSA.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairGenRSA.java new file mode 100644 index 00000000..3a849074 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairGenRSA.java @@ -0,0 +1,43 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public interface KeyPairGenRSA{ + void init(int key_size) throws Exception; + byte[] getD(); + byte[] getE(); + byte[] getN(); + + byte[] getC(); + byte[] getEP(); + byte[] getEQ(); + byte[] getP(); + byte[] getQ(); +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairRSA.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairRSA.java new file mode 100644 index 00000000..45fd70a5 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/KeyPairRSA.java @@ -0,0 +1,418 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.math.BigInteger; + +public class KeyPairRSA extends KeyPair{ + private byte[] n_array; // modulus p multiply q + private byte[] pub_array; // e + private byte[] prv_array; // d e^-1 mod (p-1)(q-1) + + private byte[] p_array; // prime p + private byte[] q_array; // prime q + private byte[] ep_array; // prime exponent p dmp1 == prv mod (p-1) + private byte[] eq_array; // prime exponent q dmq1 == prv mod (q-1) + private byte[] c_array; // coefficient iqmp == modinv(q, p) == q^-1 mod p + + private int key_size=1024; + + public KeyPairRSA(JSch jsch){ + this(jsch, null, null, null); + } + + public KeyPairRSA(JSch jsch, + byte[] n_array, + byte[] pub_array, + byte[] prv_array){ + super(jsch); + this.n_array = n_array; + this.pub_array = pub_array; + this.prv_array = prv_array; + if(n_array!=null){ + key_size = (new java.math.BigInteger(n_array)).bitLength(); + } + } + + void generate(int key_size) throws JSchException{ + this.key_size=key_size; + try{ + Class c=Class.forName(jsch.getConfig("keypairgen.rsa")); + KeyPairGenRSA keypairgen=(KeyPairGenRSA)(c.newInstance()); + keypairgen.init(key_size); + pub_array=keypairgen.getE(); + prv_array=keypairgen.getD(); + n_array=keypairgen.getN(); + + p_array=keypairgen.getP(); + q_array=keypairgen.getQ(); + ep_array=keypairgen.getEP(); + eq_array=keypairgen.getEQ(); + c_array=keypairgen.getC(); + + keypairgen=null; + } + catch(Exception e){ + //System.err.println("KeyPairRSA: "+e); + if(e instanceof Throwable) + throw new JSchException(e.toString(), (Throwable)e); + throw new JSchException(e.toString()); + } + } + + private static final byte[] begin=Util.str2byte("-----BEGIN RSA PRIVATE KEY-----"); + private static final byte[] end=Util.str2byte("-----END RSA PRIVATE KEY-----"); + + byte[] getBegin(){ return begin; } + byte[] getEnd(){ return end; } + + byte[] getPrivateKey(){ + int content= + 1+countLength(1) + 1 + // INTEGER + 1+countLength(n_array.length) + n_array.length + // INTEGER N + 1+countLength(pub_array.length) + pub_array.length + // INTEGER pub + 1+countLength(prv_array.length) + prv_array.length+ // INTEGER prv + 1+countLength(p_array.length) + p_array.length+ // INTEGER p + 1+countLength(q_array.length) + q_array.length+ // INTEGER q + 1+countLength(ep_array.length) + ep_array.length+ // INTEGER ep + 1+countLength(eq_array.length) + eq_array.length+ // INTEGER eq + 1+countLength(c_array.length) + c_array.length; // INTEGER c + + int total= + 1+countLength(content)+content; // SEQUENCE + + byte[] plain=new byte[total]; + int index=0; + index=writeSEQUENCE(plain, index, content); + index=writeINTEGER(plain, index, new byte[1]); // 0 + index=writeINTEGER(plain, index, n_array); + index=writeINTEGER(plain, index, pub_array); + index=writeINTEGER(plain, index, prv_array); + index=writeINTEGER(plain, index, p_array); + index=writeINTEGER(plain, index, q_array); + index=writeINTEGER(plain, index, ep_array); + index=writeINTEGER(plain, index, eq_array); + index=writeINTEGER(plain, index, c_array); + return plain; + } + + boolean parse(byte [] plain){ + + try{ + int index=0; + int length=0; + + if(vendor==VENDOR_PUTTY){ + Buffer buf = new Buffer(plain); + buf.skip(plain.length); + + try { + byte[][] tmp = buf.getBytes(4, ""); + prv_array = tmp[0]; + p_array = tmp[1]; + q_array = tmp[2]; + c_array = tmp[3]; + } + catch(JSchException e){ + return false; + } + + getEPArray(); + getEQArray(); + + return true; + } + + if(vendor==VENDOR_FSECURE){ + if(plain[index]!=0x30){ // FSecure + Buffer buf=new Buffer(plain); + pub_array=buf.getMPIntBits(); + prv_array=buf.getMPIntBits(); + n_array=buf.getMPIntBits(); + byte[] u_array=buf.getMPIntBits(); + p_array=buf.getMPIntBits(); + q_array=buf.getMPIntBits(); + if(n_array!=null){ + key_size = (new java.math.BigInteger(n_array)).bitLength(); + } + + getEPArray(); + getEQArray(); + getCArray(); + + return true; + } + return false; + } + + /* + Key must be in the following ASN.1 DER encoding, + RSAPrivateKey ::= SEQUENCE { + version Version, + modulus INTEGER, -- n + publicExponent INTEGER, -- e + privateExponent INTEGER, -- d + prime1 INTEGER, -- p + prime2 INTEGER, -- q + exponent1 INTEGER, -- d mod (p-1) + exponent2 INTEGER, -- d mod (q-1) + coefficient INTEGER, -- (inverse of q) mod p + otherPrimeInfos OtherPrimeInfos OPTIONAL + } + */ + + index++; // SEQUENCE + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + + if(plain[index]!=0x02)return false; + index++; // INTEGER + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + n_array=new byte[length]; + System.arraycopy(plain, index, n_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + pub_array=new byte[length]; + System.arraycopy(plain, index, pub_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + prv_array=new byte[length]; + System.arraycopy(plain, index, prv_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + p_array=new byte[length]; + System.arraycopy(plain, index, p_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + q_array=new byte[length]; + System.arraycopy(plain, index, q_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + ep_array=new byte[length]; + System.arraycopy(plain, index, ep_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + eq_array=new byte[length]; + System.arraycopy(plain, index, eq_array, 0, length); + index+=length; + + index++; + length=plain[index++]&0xff; + if((length&0x80)!=0){ + int foo=length&0x7f; length=0; + while(foo-->0){ length=(length<<8)+(plain[index++]&0xff); } + } + c_array=new byte[length]; + System.arraycopy(plain, index, c_array, 0, length); + index+=length; + + if(n_array!=null){ + key_size = (new java.math.BigInteger(n_array)).bitLength(); + } + + } + catch(Exception e){ + //System.err.println(e); + return false; + } + return true; + } + + public byte[] getPublicKeyBlob(){ + byte[] foo=super.getPublicKeyBlob(); + if(foo!=null) return foo; + + if(pub_array==null) return null; + byte[][] tmp = new byte[3][]; + tmp[0] = sshrsa; + tmp[1] = pub_array; + tmp[2] = n_array; + return Buffer.fromBytes(tmp).buffer; + } + + private static final byte[] sshrsa=Util.str2byte("ssh-rsa"); + byte[] getKeyTypeName(){return sshrsa;} + public int getKeyType(){return RSA;} + + public int getKeySize(){ + return key_size; + } + + public byte[] getSignature(byte[] data){ + try{ + Class c=Class.forName((String)jsch.getConfig("signature.rsa")); + SignatureRSA rsa=(SignatureRSA)(c.newInstance()); + rsa.init(); + rsa.setPrvKey(prv_array, n_array); + + rsa.update(data); + byte[] sig = rsa.sign(); + byte[][] tmp = new byte[2][]; + tmp[0] = sshrsa; + tmp[1] = sig; + return Buffer.fromBytes(tmp).buffer; + } + catch(Exception e){ + } + return null; + } + + public Signature getVerifier(){ + try{ + Class c=Class.forName((String)jsch.getConfig("signature.rsa")); + SignatureRSA rsa=(SignatureRSA)(c.newInstance()); + rsa.init(); + + if(pub_array == null && n_array == null && getPublicKeyBlob()!=null){ + Buffer buf = new Buffer(getPublicKeyBlob()); + buf.getString(); + pub_array = buf.getString(); + n_array = buf.getString(); + } + + rsa.setPubKey(pub_array, n_array); + return rsa; + } + catch(Exception e){ + } + return null; + } + + static KeyPair fromSSHAgent(JSch jsch, Buffer buf) throws JSchException { + + byte[][] tmp = buf.getBytes(8, "invalid key format"); + + byte[] n_array = tmp[1]; + byte[] pub_array = tmp[2]; + byte[] prv_array = tmp[3]; + KeyPairRSA kpair = new KeyPairRSA(jsch, n_array, pub_array, prv_array); + kpair.c_array = tmp[4]; // iqmp + kpair.p_array = tmp[5]; + kpair.q_array = tmp[6]; + kpair.publicKeyComment = new String(tmp[7]); + kpair.vendor=VENDOR_OPENSSH; + return kpair; + } + + public byte[] forSSHAgent() throws JSchException { + if(isEncrypted()){ + throw new JSchException("key is encrypted."); + } + Buffer buf = new Buffer(); + buf.putString(sshrsa); + buf.putString(n_array); + buf.putString(pub_array); + buf.putString(prv_array); + buf.putString(getCArray()); + buf.putString(p_array); + buf.putString(q_array); + buf.putString(Util.str2byte(publicKeyComment)); + byte[] result = new byte[buf.getLength()]; + buf.getByte(result, 0, result.length); + return result; + } + + private byte[] getEPArray(){ + if(ep_array==null){ + ep_array=(new BigInteger(prv_array)).mod(new BigInteger(p_array).subtract(BigInteger.ONE)).toByteArray(); + } + return ep_array; + } + + private byte[] getEQArray(){ + if(eq_array==null){ + eq_array=(new BigInteger(prv_array)).mod(new BigInteger(q_array).subtract(BigInteger.ONE)).toByteArray(); + } + return eq_array; + } + + private byte[] getCArray(){ + if(c_array==null){ + c_array=(new BigInteger(q_array)).modInverse(new BigInteger(p_array)).toByteArray(); + } + return c_array; + } + + public void dispose(){ + super.dispose(); + Util.bzero(prv_array); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/KnownHosts.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/KnownHosts.java new file mode 100644 index 00000000..6fd577ea --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/KnownHosts.java @@ -0,0 +1,584 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.io.*; + +public +class KnownHosts implements HostKeyRepository{ + private static final String _known_hosts="known_hosts"; + + /* + static final int SSHDSS=0; + static final int SSHRSA=1; + static final int UNKNOWN=2; + */ + + private JSch jsch=null; + private String known_hosts=null; + private java.util.Vector pool=null; + + private MAC hmacsha1=null; + + KnownHosts(JSch jsch){ + super(); + this.jsch=jsch; + pool=new java.util.Vector(); + } + + void setKnownHosts(String foo) throws JSchException{ + try{ + known_hosts = foo; + FileInputStream fis=new FileInputStream(Util.checkTilde(foo)); + setKnownHosts(fis); + } + catch(FileNotFoundException e){ + } + } + void setKnownHosts(InputStream foo) throws JSchException{ + pool.removeAllElements(); + StringBuffer sb=new StringBuffer(); + byte i; + int j; + boolean error=false; + try{ + InputStream fis=foo; + String host; + String key=null; + int type; + byte[] buf=new byte[1024]; + int bufl=0; +loop: + while(true){ + bufl=0; + while(true){ + j=fis.read(); + if(j==-1){ + if(bufl==0){ break loop; } + else{ break; } + } + if(j==0x0d){ continue; } + if(j==0x0a){ break; } + if(buf.length<=bufl){ + if(bufl>1024*10) break; // too long... + byte[] newbuf=new byte[buf.length*2]; + System.arraycopy(buf, 0, newbuf, 0, buf.length); + buf=newbuf; + } + buf[bufl++]=(byte)j; + } + + j=0; + while(j=bufl){ + addInvalidLine(Util.byte2str(buf, 0, bufl)); + continue loop; + } + + sb.setLength(0); + while(j=bufl || host.length()==0){ + addInvalidLine(Util.byte2str(buf, 0, bufl)); + continue loop; + } + + while(j=bufl || host.length()==0){ + addInvalidLine(Util.byte2str(buf, 0, bufl)); + continue loop; + } + + while(j=bufl){ + addInvalidLine(Util.byte2str(buf, 0, bufl)); + continue loop; + } + + while(j1 + ){ + return check(host.substring(1, host.indexOf("]:")), key); + } + + return result; + } + + public void add(HostKey hostkey, UserInfo userinfo){ + int type=hostkey.type; + String host=hostkey.getHost(); + byte[] key=hostkey.key; + + HostKey hk=null; + synchronized(pool){ + for(int i=0; i0){ + String data=this.host.substring(HASH_MAGIC.length()); + String _salt=data.substring(0, data.indexOf(HASH_DELIM)); + String _hash=data.substring(data.indexOf(HASH_DELIM)+1); + salt=Util.fromBase64(Util.str2byte(_salt), 0, _salt.length()); + hash=Util.fromBase64(Util.str2byte(_hash), 0, _hash.length()); + if(salt.length!=20 || // block size of hmac-sha1 + hash.length!=20){ + salt=null; + hash=null; + return; + } + hashed=true; + } + } + + boolean isMatched(String _host){ + if(!hashed){ + return super.isMatched(_host); + } + MAC macsha1=getHMACSHA1(); + try{ + synchronized(macsha1){ + macsha1.init(salt); + byte[] foo=Util.str2byte(_host); + macsha1.update(foo, 0, foo.length); + byte[] bar=new byte[macsha1.getBlockSize()]; + macsha1.doFinal(bar, 0); + return Util.array_equals(hash, bar); + } + } + catch(Exception e){ + System.out.println(e); + } + return false; + } + + boolean isHashed(){ + return hashed; + } + + void hash(){ + if(hashed) + return; + MAC macsha1=getHMACSHA1(); + if(salt==null){ + Random random=Session.random; + synchronized(random){ + salt=new byte[macsha1.getBlockSize()]; + random.fill(salt, 0, salt.length); + } + } + try{ + synchronized(macsha1){ + macsha1.init(salt); + byte[] foo=Util.str2byte(host); + macsha1.update(foo, 0, foo.length); + hash=new byte[macsha1.getBlockSize()]; + macsha1.doFinal(hash, 0); + } + } + catch(Exception e){ + } + host=HASH_MAGIC+Util.byte2str(Util.toBase64(salt, 0, salt.length))+ + HASH_DELIM+Util.byte2str(Util.toBase64(hash, 0, hash.length)); + hashed=true; + } + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/LocalIdentityRepository.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/LocalIdentityRepository.java new file mode 100644 index 00000000..3b83f2ef --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/LocalIdentityRepository.java @@ -0,0 +1,103 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.util.Vector; + +class LocalIdentityRepository implements IdentityRepository { + private static final String name = "Local Identity Repository"; + + private Vector identities = new Vector(); + private JSch jsch; + + LocalIdentityRepository(JSch jsch){ + this.jsch = jsch; + } + + public String getName(){ + return name; + } + + public int getStatus(){ + return RUNNING; + } + + public synchronized Vector getIdentities() { + Vector v = new Vector(); + for(int i=0; i + *

  • Host
  • + *
  • User
  • + *
  • Hostname
  • + *
  • Port
  • + *
  • PreferredAuthentications
  • + *
  • IdentityFile
  • + *
  • NumberOfPasswordPrompts
  • + *
  • ConnectTimeout
  • + *
  • HostKeyAlias
  • + *
  • UserKnownHostsFile
  • + *
  • KexAlgorithms
  • + *
  • HostKeyAlgorithms
  • + *
  • Ciphers
  • + *
  • Macs
  • + *
  • Compression
  • + *
  • CompressionLevel
  • + *
  • ForwardAgent
  • + *
  • RequestTTY
  • + *
  • ServerAliveInterval
  • + *
  • LocalForward
  • + *
  • RemoteForward
  • + *
  • ClearAllForwardings
  • + * + * + * @see ConfigRepository + */ +public class OpenSSHConfig implements ConfigRepository { + + /** + * Parses the given string, and returns an instance of ConfigRepository. + * + * @param conf string, which includes OpenSSH's config + * @return an instanceof OpenSSHConfig + */ + public static OpenSSHConfig parse(String conf) throws IOException { + InputStream in = new ByteArrayInputStream(Util.str2byte(conf)); + try { + return new OpenSSHConfig(in); + } + finally { + in.close(); + } + } + + /** + * Parses the given file, and returns an instance of ConfigRepository. + * + * @param file OpenSSH's config file + * @return an instanceof OpenSSHConfig + */ + public static OpenSSHConfig parseFile(String file) throws IOException { + byte[] conf = Util.fromFile(file); + InputStream in = new ByteArrayInputStream(conf); + try { + return new OpenSSHConfig(in); + } + finally { + in.close(); + } + } + + OpenSSHConfig(InputStream in) throws IOException { + _parse(in); + } + + private final Hashtable config = new Hashtable(); + private final Vector hosts = new Vector(); + + private void _parse(InputStream in) throws IOException { + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + + String host = ""; + Vector/**/ kv = new Vector(); + String l = null; + + while((l = br.readLine()) != null){ + l = l.trim(); + if(l.length() == 0 || l.startsWith("#")) + continue; + + String[] key_value = l.split("[= \t]", 2); + for(int i = 0; i < key_value.length; i++) + key_value[i] = key_value[i].trim(); + + if(key_value.length <= 1) + continue; + + if(key_value[0].equals("Host")){ + config.put(host, kv); + hosts.addElement(host); + host = key_value[1]; + kv = new Vector(); + } + else { + kv.addElement(key_value); + } + } + config.put(host, kv); + hosts.addElement(host); + } + + public Config getConfig(String host) { + return new MyConfig(host); + } + + private static final Hashtable keymap = new Hashtable(); + static { + keymap.put("kex", "KexAlgorithms"); + keymap.put("server_host_key", "HostKeyAlgorithms"); + keymap.put("cipher.c2s", "Ciphers"); + keymap.put("cipher.s2c", "Ciphers"); + keymap.put("mac.c2s", "Macs"); + keymap.put("mac.s2c", "Macs"); + keymap.put("compression.s2c", "Compression"); + keymap.put("compression.c2s", "Compression"); + keymap.put("compression_level", "CompressionLevel"); + keymap.put("MaxAuthTries", "NumberOfPasswordPrompts"); + } + + class MyConfig implements Config { + + private String host; + private Vector _configs = new Vector(); + + MyConfig(String host){ + this.host = host; + + _configs.addElement(config.get("")); + + byte[] _host = Util.str2byte(host); + if(hosts.size() > 1){ + for(int i = 1; i < hosts.size(); i++){ + String patterns[] = ((String)hosts.elementAt(i)).split("[ \t]"); + for(int j = 0; j < patterns.length; j++){ + boolean negate = false; + String foo = patterns[j].trim(); + if(foo.startsWith("!")){ + negate = true; + foo = foo.substring(1).trim(); + } + if(Util.glob(Util.str2byte(foo), _host)){ + if(!negate){ + _configs.addElement(config.get((String)hosts.elementAt(i))); + } + } + else if(negate){ + _configs.addElement(config.get((String)hosts.elementAt(i))); + } + } + } + } + } + + private String find(String key) { + if(keymap.get(key)!=null) { + key = (String)keymap.get(key); + } + String value = null; + for(int i = 0; i < _configs.size(); i++) { + Vector v = (Vector)_configs.elementAt(i); + for(int j = 0; j < v.size(); j++) { + String[] kv = (String[])v.elementAt(j); + if(kv[0].equals(key)) { + value = kv[1]; + break; + } + } + if(value != null) + break; + } + return value; + } + + private String[] multiFind(String key) { + Vector value = new Vector(); + for(int i = 0; i < _configs.size(); i++) { + Vector v = (Vector)_configs.elementAt(i); + for(int j = 0; j < v.size(); j++) { + String[] kv = (String[])v.elementAt(j); + if(kv[0].equals(key)) { + String foo = kv[1]; + if(foo != null) { + value.remove(foo); + value.addElement(foo); + } + } + } + } + String[] result = new String[value.size()]; + value.toArray(result); + return result; + } + + public String getHostname(){ return find("Hostname"); } + public String getUser(){ return find("User"); } + public int getPort(){ + String foo = find("Port"); + int port = -1; + try { + port = Integer.parseInt(foo); + } + catch(NumberFormatException e){ + // wrong format + } + return port; + } + public String getValue(String key){ + if(key.equals("compression.s2c") || + key.equals("compression.c2s")) { + String foo = find(key); + if(foo == null || foo.equals("no")) + return "none,zlib@openssh.com,zlib"; + return "zlib@openssh.com,zlib,none"; + } + return find(key); + } + public String[] getValues(String key){ return multiFind(key); } + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/Packet.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/Packet.java new file mode 100644 index 00000000..9c441577 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/Packet.java @@ -0,0 +1,115 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public class Packet{ + + private static Random random=null; + static void setRandom(Random foo){ random=foo;} + + Buffer buffer; + byte[] ba4=new byte[4]; + public Packet(Buffer buffer){ + this.buffer=buffer; + } + public void reset(){ + buffer.index=5; + } + void padding(int bsize){ + int len=buffer.index; + int pad=(-len)&(bsize-1); + if(pad>>24); + ba4[1]=(byte)(len>>>16); + ba4[2]=(byte)(len>>>8); + ba4[3]=(byte)(len); + System.arraycopy(ba4, 0, buffer.buffer, 0, 4); + buffer.buffer[4]=(byte)pad; + synchronized(random){ + random.fill(buffer.buffer, buffer.index, pad); + } + buffer.skip(pad); + //buffer.putPad(pad); +/* +for(int i=0; i0){ + socket.setSoTimeout(timeout); + } + socket.setTcpNoDelay(true); + + out.write(Util.str2byte("CONNECT "+host+":"+port+" HTTP/1.0\r\n")); + + if(user!=null && passwd!=null){ + byte[] code=Util.str2byte(user+":"+passwd); + code=Util.toBase64(code, 0, code.length); + out.write(Util.str2byte("Proxy-Authorization: Basic ")); + out.write(code); + out.write(Util.str2byte("\r\n")); + } + + out.write(Util.str2byte("\r\n")); + out.flush(); + + int foo=0; + + StringBuffer sb=new StringBuffer(); + while(foo>=0){ + foo=in.read(); if(foo!=13){sb.append((char)foo); continue;} + foo=in.read(); if(foo!=10){continue;} + break; + } + if(foo<0){ + throw new IOException(); + } + + String response=sb.toString(); + String reason="Unknow reason"; + int code=-1; + try{ + foo=response.indexOf(' '); + int bar=response.indexOf(' ', foo+1); + code=Integer.parseInt(response.substring(foo+1, bar)); + reason=response.substring(bar+1); + } + catch(Exception e){ + } + if(code!=200){ + throw new IOException("proxy error: "+reason); + } + + /* + while(foo>=0){ + foo=in.read(); if(foo!=13) continue; + foo=in.read(); if(foo!=10) continue; + foo=in.read(); if(foo!=13) continue; + foo=in.read(); if(foo!=10) continue; + break; + } + */ + + int count=0; + while(true){ + count=0; + while(foo>=0){ + foo=in.read(); if(foo!=13){count++; continue;} + foo=in.read(); if(foo!=10){continue;} + break; + } + if(foo<0){ + throw new IOException(); + } + if(count==0)break; + } + } + catch(RuntimeException e){ + throw e; + } + catch(Exception e){ + try{ if(socket!=null)socket.close(); } + catch(Exception eee){ + } + String message="ProxyHTTP: "+e.toString(); + if(e instanceof Throwable) + throw new JSchException(message, (Throwable)e); + throw new JSchException(message); + } + } + public InputStream getInputStream(){ return in; } + public OutputStream getOutputStream(){ return out; } + public Socket getSocket(){ return socket; } + public void close(){ + try{ + if(in!=null)in.close(); + if(out!=null)out.close(); + if(socket!=null)socket.close(); + } + catch(Exception e){ + } + in=null; + out=null; + socket=null; + } + public static int getDefaultPort(){ + return DEFAULTPORT; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/ProxySOCKS4.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/ProxySOCKS4.java new file mode 100644 index 00000000..cb506165 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/ProxySOCKS4.java @@ -0,0 +1,212 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + This file depends on following documents, + - SOCKS: A protocol for TCP proxy across firewalls, Ying-Da Lee + http://www.socks.nec.com/protocol/socks4.protocol + */ + +package com.jcraft.jsch; + +import java.io.*; +import java.net.*; + +public class ProxySOCKS4 implements Proxy{ + private static int DEFAULTPORT=1080; + private String proxy_host; + private int proxy_port; + private InputStream in; + private OutputStream out; + private Socket socket; + private String user; + private String passwd; + + public ProxySOCKS4(String proxy_host){ + int port=DEFAULTPORT; + String host=proxy_host; + if(proxy_host.indexOf(':')!=-1){ + try{ + host=proxy_host.substring(0, proxy_host.indexOf(':')); + port=Integer.parseInt(proxy_host.substring(proxy_host.indexOf(':')+1)); + } + catch(Exception e){ + } + } + this.proxy_host=host; + this.proxy_port=port; + } + public ProxySOCKS4(String proxy_host, int proxy_port){ + this.proxy_host=proxy_host; + this.proxy_port=proxy_port; + } + public void setUserPasswd(String user, String passwd){ + this.user=user; + this.passwd=passwd; + } + public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws JSchException{ + try{ + if(socket_factory==null){ + socket=Util.createSocket(proxy_host, proxy_port, timeout); + //socket=new Socket(proxy_host, proxy_port); + in=socket.getInputStream(); + out=socket.getOutputStream(); + } + else{ + socket=socket_factory.createSocket(proxy_host, proxy_port); + in=socket_factory.getInputStream(socket); + out=socket_factory.getOutputStream(socket); + } + if(timeout>0){ + socket.setSoTimeout(timeout); + } + socket.setTcpNoDelay(true); + + byte[] buf=new byte[1024]; + int index=0; + +/* + 1) CONNECT + + The client connects to the SOCKS server and sends a CONNECT request when + it wants to establish a connection to an application server. The client + includes in the request packet the IP address and the port number of the + destination host, and userid, in the following format. + + +----+----+----+----+----+----+----+----+----+----+....+----+ + | VN | CD | DSTPORT | DSTIP | USERID |NULL| + +----+----+----+----+----+----+----+----+----+----+....+----+ + # of bytes: 1 1 2 4 variable 1 + + VN is the SOCKS protocol version number and should be 4. CD is the + SOCKS command code and should be 1 for CONNECT request. NULL is a byte + of all zero bits. +*/ + + index=0; + buf[index++]=4; + buf[index++]=1; + + buf[index++]=(byte)(port>>>8); + buf[index++]=(byte)(port&0xff); + + try{ + InetAddress addr=InetAddress.getByName(host); + byte[] byteAddress = addr.getAddress(); + for (int i = 0; i < byteAddress.length; i++) { + buf[index++]=byteAddress[i]; + } + } + catch(UnknownHostException uhe){ + throw new JSchException("ProxySOCKS4: "+uhe.toString(), uhe); + } + + if(user!=null){ + System.arraycopy(Util.str2byte(user), 0, buf, index, user.length()); + index+=user.length(); + } + buf[index++]=0; + out.write(buf, 0, index); + +/* + The SOCKS server checks to see whether such a request should be granted + based on any combination of source IP address, destination IP address, + destination port number, the userid, and information it may obtain by + consulting IDENT, cf. RFC 1413. If the request is granted, the SOCKS + server makes a connection to the specified port of the destination host. + A reply packet is sent to the client when this connection is established, + or when the request is rejected or the operation fails. + + +----+----+----+----+----+----+----+----+ + | VN | CD | DSTPORT | DSTIP | + +----+----+----+----+----+----+----+----+ + # of bytes: 1 1 2 4 + + VN is the version of the reply code and should be 0. CD is the result + code with one of the following values: + + 90: request granted + 91: request rejected or failed + 92: request rejected becasue SOCKS server cannot connect to + identd on the client + 93: request rejected because the client program and identd + report different user-ids + + The remaining fields are ignored. +*/ + + int len=8; + int s=0; + while(s0){ + socket.setSoTimeout(timeout); + } + socket.setTcpNoDelay(true); + + byte[] buf=new byte[1024]; + int index=0; + +/* + +----+----------+----------+ + |VER | NMETHODS | METHODS | + +----+----------+----------+ + | 1 | 1 | 1 to 255 | + +----+----------+----------+ + + The VER field is set to X'05' for this version of the protocol. The + NMETHODS field contains the number of method identifier octets that + appear in the METHODS field. + + The values currently defined for METHOD are: + + o X'00' NO AUTHENTICATION REQUIRED + o X'01' GSSAPI + o X'02' USERNAME/PASSWORD + o X'03' to X'7F' IANA ASSIGNED + o X'80' to X'FE' RESERVED FOR PRIVATE METHODS + o X'FF' NO ACCEPTABLE METHODS +*/ + + buf[index++]=5; + + buf[index++]=2; + buf[index++]=0; // NO AUTHENTICATION REQUIRED + buf[index++]=2; // USERNAME/PASSWORD + + out.write(buf, 0, index); + +/* + The server selects from one of the methods given in METHODS, and + sends a METHOD selection message: + + +----+--------+ + |VER | METHOD | + +----+--------+ + | 1 | 1 | + +----+--------+ +*/ + //in.read(buf, 0, 2); + fill(in, buf, 2); + + boolean check=false; + switch((buf[1])&0xff){ + case 0: // NO AUTHENTICATION REQUIRED + check=true; + break; + case 2: // USERNAME/PASSWORD + if(user==null || passwd==null)break; + +/* + Once the SOCKS V5 server has started, and the client has selected the + Username/Password Authentication protocol, the Username/Password + subnegotiation begins. This begins with the client producing a + Username/Password request: + + +----+------+----------+------+----------+ + |VER | ULEN | UNAME | PLEN | PASSWD | + +----+------+----------+------+----------+ + | 1 | 1 | 1 to 255 | 1 | 1 to 255 | + +----+------+----------+------+----------+ + + The VER field contains the current version of the subnegotiation, + which is X'01'. The ULEN field contains the length of the UNAME field + that follows. The UNAME field contains the username as known to the + source operating system. The PLEN field contains the length of the + PASSWD field that follows. The PASSWD field contains the password + association with the given UNAME. +*/ + index=0; + buf[index++]=1; + buf[index++]=(byte)(user.length()); + System.arraycopy(Util.str2byte(user), 0, buf, index, user.length()); + index+=user.length(); + buf[index++]=(byte)(passwd.length()); + System.arraycopy(Util.str2byte(passwd), 0, buf, index, passwd.length()); + index+=passwd.length(); + + out.write(buf, 0, index); + +/* + The server verifies the supplied UNAME and PASSWD, and sends the + following response: + + +----+--------+ + |VER | STATUS | + +----+--------+ + | 1 | 1 | + +----+--------+ + + A STATUS field of X'00' indicates success. If the server returns a + `failure' (STATUS value other than X'00') status, it MUST close the + connection. +*/ + //in.read(buf, 0, 2); + fill(in, buf, 2); + if(buf[1]==0) + check=true; + break; + default: + } + + if(!check){ + try{ socket.close(); } + catch(Exception eee){ + } + throw new JSchException("fail in SOCKS5 proxy"); + } + +/* + The SOCKS request is formed as follows: + + +----+-----+-------+------+----------+----------+ + |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | + +----+-----+-------+------+----------+----------+ + | 1 | 1 | X'00' | 1 | Variable | 2 | + +----+-----+-------+------+----------+----------+ + + Where: + + o VER protocol version: X'05' + o CMD + o CONNECT X'01' + o BIND X'02' + o UDP ASSOCIATE X'03' + o RSV RESERVED + o ATYP address type of following address + o IP V4 address: X'01' + o DOMAINNAME: X'03' + o IP V6 address: X'04' + o DST.ADDR desired destination address + o DST.PORT desired destination port in network octet + order +*/ + + index=0; + buf[index++]=5; + buf[index++]=1; // CONNECT + buf[index++]=0; + + byte[] hostb=Util.str2byte(host); + int len=hostb.length; + buf[index++]=3; // DOMAINNAME + buf[index++]=(byte)(len); + System.arraycopy(hostb, 0, buf, index, len); + index+=len; + buf[index++]=(byte)(port>>>8); + buf[index++]=(byte)(port&0xff); + + out.write(buf, 0, index); + +/* + The SOCKS request information is sent by the client as soon as it has + established a connection to the SOCKS server, and completed the + authentication negotiations. The server evaluates the request, and + returns a reply formed as follows: + + +----+-----+-------+------+----------+----------+ + |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | + +----+-----+-------+------+----------+----------+ + | 1 | 1 | X'00' | 1 | Variable | 2 | + +----+-----+-------+------+----------+----------+ + + Where: + + o VER protocol version: X'05' + o REP Reply field: + o X'00' succeeded + o X'01' general SOCKS server failure + o X'02' connection not allowed by ruleset + o X'03' Network unreachable + o X'04' Host unreachable + o X'05' Connection refused + o X'06' TTL expired + o X'07' Command not supported + o X'08' Address type not supported + o X'09' to X'FF' unassigned + o RSV RESERVED + o ATYP address type of following address + o IP V4 address: X'01' + o DOMAINNAME: X'03' + o IP V6 address: X'04' + o BND.ADDR server bound address + o BND.PORT server bound port in network octet order +*/ + + //in.read(buf, 0, 4); + fill(in, buf, 4); + + if(buf[1]!=0){ + try{ socket.close(); } + catch(Exception eee){ + } + throw new JSchException("ProxySOCKS5: server returns "+buf[1]); + } + + switch(buf[3]&0xff){ + case 1: + //in.read(buf, 0, 6); + fill(in, buf, 6); + break; + case 3: + //in.read(buf, 0, 1); + fill(in, buf, 1); + //in.read(buf, 0, buf[0]+2); + fill(in, buf, (buf[0]&0xff)+2); + break; + case 4: + //in.read(buf, 0, 18); + fill(in, buf, 18); + break; + default: + } + } + catch(RuntimeException e){ + throw e; + } + catch(Exception e){ + try{ if(socket!=null)socket.close(); } + catch(Exception eee){ + } + String message="ProxySOCKS5: "+e.toString(); + if(e instanceof Throwable) + throw new JSchException(message, (Throwable)e); + throw new JSchException(message); + } + } + public InputStream getInputStream(){ return in; } + public OutputStream getOutputStream(){ return out; } + public Socket getSocket(){ return socket; } + public void close(){ + try{ + if(in!=null)in.close(); + if(out!=null)out.close(); + if(socket!=null)socket.close(); + } + catch(Exception e){ + } + in=null; + out=null; + socket=null; + } + public static int getDefaultPort(){ + return DEFAULTPORT; + } + private void fill(InputStream in, byte[] buf, int len) throws JSchException, IOException{ + int s=0; + while(s0){ + setReply(true); + } + } + boolean waitForReply(){ return reply; } + void setReply(boolean reply){ this.reply=reply; } + void write(Packet packet) throws Exception{ + if(reply){ + channel.reply=-1; + } + session.write(packet); + if(reply){ + long start=System.currentTimeMillis(); + long timeout=channel.connectTimeout; + while(channel.isConnected() && channel.reply==-1){ + try{Thread.sleep(10);} + catch(Exception ee){ + } + if(timeout>0L && + (System.currentTimeMillis()-start)>timeout){ + channel.reply=0; + throw new JSchException("channel request: timeout"); + } + } + + if(channel.reply==0){ + throw new JSchException("failed to send channel request"); + } + } + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestAgentForwarding.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestAgentForwarding.java new file mode 100644 index 00000000..66d328cd --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestAgentForwarding.java @@ -0,0 +1,53 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +class RequestAgentForwarding extends Request{ + public void request(Session session, Channel channel) throws Exception{ + super.request(session, channel); + + setReply(false); + + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + + // byte SSH_MSG_CHANNEL_REQUEST(98) + // uint32 recipient channel + // string request type // "auth-agent-req@openssh.com" + // boolean want reply // 0 + packet.reset(); + buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST); + buf.putInt(channel.getRecipient()); + buf.putString(Util.str2byte("auth-agent-req@openssh.com")); + buf.putByte((byte)(waitForReply() ? 1 : 0)); + write(packet); + session.agent_forwarding=true; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestEnv.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestEnv.java new file mode 100644 index 00000000..cccda4df --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestEnv.java @@ -0,0 +1,54 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +class RequestEnv extends Request{ + byte[] name=new byte[0]; + byte[] value=new byte[0]; + void setEnv(byte[] name, byte[] value){ + this.name=name; + this.value=value; + } + public void request(Session session, Channel channel) throws Exception{ + super.request(session, channel); + + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + + packet.reset(); + buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST); + buf.putInt(channel.getRecipient()); + buf.putString(Util.str2byte("env")); + buf.putByte((byte)(waitForReply() ? 1 : 0)); + buf.putString(name); + buf.putString(value); + write(packet); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestExec.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestExec.java new file mode 100644 index 00000000..318d99ad --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestExec.java @@ -0,0 +1,58 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +class RequestExec extends Request{ + private byte[] command=new byte[0]; + RequestExec(byte[] command){ + this.command=command; + } + public void request(Session session, Channel channel) throws Exception{ + super.request(session, channel); + + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + + // send + // byte SSH_MSG_CHANNEL_REQUEST(98) + // uint32 recipient channel + // string request type // "exec" + // boolean want reply // 0 + // string command + packet.reset(); + buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST); + buf.putInt(channel.getRecipient()); + buf.putString(Util.str2byte("exec")); + buf.putByte((byte)(waitForReply() ? 1 : 0)); + buf.checkFreeSize(4+command.length); + buf.putString(command); + write(packet); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestPtyReq.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestPtyReq.java new file mode 100644 index 00000000..86bf4f13 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestPtyReq.java @@ -0,0 +1,78 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +class RequestPtyReq extends Request{ + private String ttype="vt100"; + private int tcol=80; + private int trow=24; + private int twp=640; + private int thp=480; + + private byte[] terminal_mode=Util.empty; + + void setCode(String cookie){ + } + + void setTType(String ttype){ + this.ttype=ttype; + } + + void setTerminalMode(byte[] terminal_mode){ + this.terminal_mode=terminal_mode; + } + + void setTSize(int tcol, int trow, int twp, int thp){ + this.tcol=tcol; + this.trow=trow; + this.twp=twp; + this.thp=thp; + } + + public void request(Session session, Channel channel) throws Exception{ + super.request(session, channel); + + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + + packet.reset(); + buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST); + buf.putInt(channel.getRecipient()); + buf.putString(Util.str2byte("pty-req")); + buf.putByte((byte)(waitForReply() ? 1 : 0)); + buf.putString(Util.str2byte(ttype)); + buf.putInt(tcol); + buf.putInt(trow); + buf.putInt(twp); + buf.putInt(thp); + buf.putString(terminal_mode); + write(packet); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestSftp.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestSftp.java new file mode 100644 index 00000000..483c296b --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestSftp.java @@ -0,0 +1,49 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public class RequestSftp extends Request{ + RequestSftp(){ + setReply(true); + } + public void request(Session session, Channel channel) throws Exception{ + super.request(session, channel); + + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + packet.reset(); + buf.putByte((byte)Session.SSH_MSG_CHANNEL_REQUEST); + buf.putInt(channel.getRecipient()); + buf.putString(Util.str2byte("subsystem")); + buf.putByte((byte)(waitForReply() ? 1 : 0)); + buf.putString(Util.str2byte("sftp")); + write(packet); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestShell.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestShell.java new file mode 100644 index 00000000..e037ba9e --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestShell.java @@ -0,0 +1,51 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +class RequestShell extends Request{ + public void request(Session session, Channel channel) throws Exception{ + super.request(session, channel); + + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + + // send + // byte SSH_MSG_CHANNEL_REQUEST(98) + // uint32 recipient channel + // string request type // "shell" + // boolean want reply // 0 + packet.reset(); + buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST); + buf.putInt(channel.getRecipient()); + buf.putString(Util.str2byte("shell")); + buf.putByte((byte)(waitForReply() ? 1 : 0)); + write(packet); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestSignal.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestSignal.java new file mode 100644 index 00000000..a6926177 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestSignal.java @@ -0,0 +1,49 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +class RequestSignal extends Request{ + private String signal="KILL"; + public void setSignal(String foo){ signal=foo; } + public void request(Session session, Channel channel) throws Exception{ + super.request(session, channel); + + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + + packet.reset(); + buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST); + buf.putInt(channel.getRecipient()); + buf.putString(Util.str2byte("signal")); + buf.putByte((byte)(waitForReply() ? 1 : 0)); + buf.putString(Util.str2byte(signal)); + write(packet); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestSubsystem.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestSubsystem.java new file mode 100644 index 00000000..b6fee4f4 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestSubsystem.java @@ -0,0 +1,53 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2005-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public class RequestSubsystem extends Request{ + private String subsystem=null; + public void request(Session session, Channel channel, String subsystem, boolean want_reply) throws Exception{ + setReply(want_reply); + this.subsystem=subsystem; + this.request(session, channel); + } + public void request(Session session, Channel channel) throws Exception{ + super.request(session, channel); + + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + + packet.reset(); + buf.putByte((byte)Session.SSH_MSG_CHANNEL_REQUEST); + buf.putInt(channel.getRecipient()); + buf.putString(Util.str2byte("subsystem")); + buf.putByte((byte)(waitForReply() ? 1 : 0)); + buf.putString(Util.str2byte(subsystem)); + write(packet); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestWindowChange.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestWindowChange.java new file mode 100644 index 00000000..43600ac4 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestWindowChange.java @@ -0,0 +1,68 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +class RequestWindowChange extends Request{ + int width_columns=80; + int height_rows=24; + int width_pixels=640; + int height_pixels=480; + void setSize(int col, int row, int wp, int hp){ + this.width_columns=col; + this.height_rows=row; + this.width_pixels=wp; + this.height_pixels=hp; + } + public void request(Session session, Channel channel) throws Exception{ + super.request(session, channel); + + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + + //byte SSH_MSG_CHANNEL_REQUEST + //uint32 recipient_channel + //string "window-change" + //boolean FALSE + //uint32 terminal width, columns + //uint32 terminal height, rows + //uint32 terminal width, pixels + //uint32 terminal height, pixels + packet.reset(); + buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST); + buf.putInt(channel.getRecipient()); + buf.putString(Util.str2byte("window-change")); + buf.putByte((byte)(waitForReply() ? 1 : 0)); + buf.putInt(width_columns); + buf.putInt(height_rows); + buf.putInt(width_pixels); + buf.putInt(height_pixels); + write(packet); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestX11.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestX11.java new file mode 100644 index 00000000..3bdaca9f --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/RequestX11.java @@ -0,0 +1,63 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +class RequestX11 extends Request{ + public void setCookie(String cookie){ + ChannelX11.cookie=Util.str2byte(cookie); + } + public void request(Session session, Channel channel) throws Exception{ + super.request(session, channel); + + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + + // byte SSH_MSG_CHANNEL_REQUEST(98) + // uint32 recipient channel + // string request type // "x11-req" + // boolean want reply // 0 + // boolean single connection + // string x11 authentication protocol // "MIT-MAGIC-COOKIE-1". + // string x11 authentication cookie + // uint32 x11 screen number + packet.reset(); + buf.putByte((byte) Session.SSH_MSG_CHANNEL_REQUEST); + buf.putInt(channel.getRecipient()); + buf.putString(Util.str2byte("x11-req")); + buf.putByte((byte)(waitForReply() ? 1 : 0)); + buf.putByte((byte)0); + buf.putString(Util.str2byte("MIT-MAGIC-COOKIE-1")); + buf.putString(ChannelX11.getFakedCookie(session)); + buf.putInt(0); + write(packet); + + session.x11_forwarding=true; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/ServerSocketFactory.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/ServerSocketFactory.java new file mode 100644 index 00000000..682b4c4f --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/ServerSocketFactory.java @@ -0,0 +1,37 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.net.*; +import java.io.*; + +public interface ServerSocketFactory{ + public ServerSocket createServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException; +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/Session.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/Session.java new file mode 100644 index 00000000..8807f5f6 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/Session.java @@ -0,0 +1,2777 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.io.*; +import java.net.*; +import java.util.Vector; + +public class Session implements Runnable{ + + // http://ietf.org/internet-drafts/draft-ietf-secsh-assignednumbers-01.txt + static final int SSH_MSG_DISCONNECT= 1; + static final int SSH_MSG_IGNORE= 2; + static final int SSH_MSG_UNIMPLEMENTED= 3; + static final int SSH_MSG_DEBUG= 4; + static final int SSH_MSG_SERVICE_REQUEST= 5; + static final int SSH_MSG_SERVICE_ACCEPT= 6; + static final int SSH_MSG_KEXINIT= 20; + static final int SSH_MSG_NEWKEYS= 21; + static final int SSH_MSG_KEXDH_INIT= 30; + static final int SSH_MSG_KEXDH_REPLY= 31; + static final int SSH_MSG_KEX_DH_GEX_GROUP= 31; + static final int SSH_MSG_KEX_DH_GEX_INIT= 32; + static final int SSH_MSG_KEX_DH_GEX_REPLY= 33; + static final int SSH_MSG_KEX_DH_GEX_REQUEST= 34; + static final int SSH_MSG_GLOBAL_REQUEST= 80; + static final int SSH_MSG_REQUEST_SUCCESS= 81; + static final int SSH_MSG_REQUEST_FAILURE= 82; + static final int SSH_MSG_CHANNEL_OPEN= 90; + static final int SSH_MSG_CHANNEL_OPEN_CONFIRMATION= 91; + static final int SSH_MSG_CHANNEL_OPEN_FAILURE= 92; + static final int SSH_MSG_CHANNEL_WINDOW_ADJUST= 93; + static final int SSH_MSG_CHANNEL_DATA= 94; + static final int SSH_MSG_CHANNEL_EXTENDED_DATA= 95; + static final int SSH_MSG_CHANNEL_EOF= 96; + static final int SSH_MSG_CHANNEL_CLOSE= 97; + static final int SSH_MSG_CHANNEL_REQUEST= 98; + static final int SSH_MSG_CHANNEL_SUCCESS= 99; + static final int SSH_MSG_CHANNEL_FAILURE= 100; + + private static final int PACKET_MAX_SIZE = 256 * 1024; + + private byte[] V_S; // server version + private byte[] V_C=Util.str2byte("SSH-2.0-JSCH-"+JSch.VERSION); // client version + + private byte[] I_C; // the payload of the client's SSH_MSG_KEXINIT + private byte[] I_S; // the payload of the server's SSH_MSG_KEXINIT + private byte[] K_S; // the host key + + private byte[] session_id; + + private byte[] IVc2s; + private byte[] IVs2c; + private byte[] Ec2s; + private byte[] Es2c; + private byte[] MACc2s; + private byte[] MACs2c; + + private int seqi=0; + private int seqo=0; + + String[] guess=null; + private Cipher s2ccipher; + private Cipher c2scipher; + private MAC s2cmac; + private MAC c2smac; + //private byte[] mac_buf; + private byte[] s2cmac_result1; + private byte[] s2cmac_result2; + + private Compression deflater; + private Compression inflater; + + private IO io; + private Socket socket; + private int timeout=0; + + private volatile boolean isConnected=false; + + private boolean isAuthed=false; + + private Thread connectThread=null; + private Object lock=new Object(); + + boolean x11_forwarding=false; + boolean agent_forwarding=false; + + InputStream in=null; + OutputStream out=null; + + static Random random; + + Buffer buf; + Packet packet; + + SocketFactory socket_factory=null; + + static final int buffer_margin = 32 + // maximum padding length + 20 + // maximum mac length + 32; // margin for deflater; deflater may inflate data + + private java.util.Hashtable config=null; + + private Proxy proxy=null; + private UserInfo userinfo; + + private String hostKeyAlias=null; + private int serverAliveInterval=0; + private int serverAliveCountMax=1; + + private IdentityRepository identityRepository = null; + private HostKeyRepository hostkeyRepository = null; + + protected boolean daemon_thread=false; + + private long kex_start_time=0L; + + int max_auth_tries = 6; + int auth_failures = 0; + + String host="127.0.0.1"; + String org_host="127.0.0.1"; + int port=22; + + String username=null; + byte[] password=null; + + JSch jsch; + + Session(JSch jsch, String username, String host, int port) throws JSchException{ + super(); + this.jsch=jsch; + buf=new Buffer(); + packet=new Packet(buf); + this.username = username; + this.org_host = this.host = host; + this.port = port; + + applyConfig(); + + if(this.username==null) { + try { + this.username=(String)(System.getProperties().get("user.name")); + } + catch(SecurityException e){ + // ignore e + } + } + + if(this.username==null) { + throw new JSchException("username is not given."); + } + } + + public void connect() throws JSchException{ + connect(timeout); + } + + public void connect(int connectTimeout) throws JSchException{ + if(isConnected){ + throw new JSchException("session is already connected"); + } + + io=new IO(); + if(random==null){ + try{ + Class c=Class.forName(getConfig("random")); + random=(Random)(c.newInstance()); + } + catch(Exception e){ + throw new JSchException(e.toString(), e); + } + } + Packet.setRandom(random); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "Connecting to "+host+" port "+port); + } + + try { + int i, j; + + if(proxy==null){ + InputStream in; + OutputStream out; + if(socket_factory==null){ + socket=Util.createSocket(host, port, connectTimeout); + in=socket.getInputStream(); + out=socket.getOutputStream(); + } + else{ + socket=socket_factory.createSocket(host, port); + in=socket_factory.getInputStream(socket); + out=socket_factory.getOutputStream(socket); + } + //if(timeout>0){ socket.setSoTimeout(timeout); } + socket.setTcpNoDelay(true); + io.setInputStream(in); + io.setOutputStream(out); + } + else{ + synchronized(proxy){ + proxy.connect(socket_factory, host, port, connectTimeout); + io.setInputStream(proxy.getInputStream()); + io.setOutputStream(proxy.getOutputStream()); + socket=proxy.getSocket(); + } + } + + if(connectTimeout>0 && socket!=null){ + socket.setSoTimeout(connectTimeout); + } + + isConnected=true; + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "Connection established"); + } + + jsch.addSession(this); + + { + // Some Cisco devices will miss to read '\n' if it is sent separately. + byte[] foo=new byte[V_C.length+1]; + System.arraycopy(V_C, 0, foo, 0, V_C.length); + foo[foo.length-1]=(byte)'\n'; + io.put(foo, 0, foo.length); + } + + while(true){ + i=0; + j=0; + while(i0 && buf.buffer[i-1]==13){ // 0x0d + i--; + } + } + + if(i<=3 || + ((i!=buf.buffer.length) && + (buf.buffer[0]!='S'||buf.buffer[1]!='S'|| + buf.buffer[2]!='H'||buf.buffer[3]!='-'))){ + // It must not start with 'SSH-' + //System.err.println(new String(buf.buffer, 0, i); + continue; + } + + if(i==buf.buffer.length || + i<7 || // SSH-1.99 or SSH-2.0 + (buf.buffer[4]=='1' && buf.buffer[6]!='9') // SSH-1.5 + ){ + throw new JSchException("invalid server's version string"); + } + break; + } + + V_S=new byte[i]; System.arraycopy(buf.buffer, 0, V_S, 0, i); + //System.err.println("V_S: ("+i+") ["+new String(V_S)+"]"); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "Remote version string: "+Util.byte2str(V_S)); + JSch.getLogger().log(Logger.INFO, + "Local version string: "+Util.byte2str(V_C)); + } + + send_kexinit(); + + buf=read(buf); + if(buf.getCommand()!=SSH_MSG_KEXINIT){ + in_kex=false; + throw new JSchException("invalid protocol: "+buf.getCommand()); + } + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "SSH_MSG_KEXINIT received"); + } + + KeyExchange kex=receive_kexinit(buf); + + while(true){ + buf=read(buf); + if(kex.getState()==buf.getCommand()){ + kex_start_time=System.currentTimeMillis(); + boolean result=kex.next(buf); + if(!result){ + //System.err.println("verify: "+result); + in_kex=false; + throw new JSchException("verify: "+result); + } + } + else{ + in_kex=false; + throw new JSchException("invalid protocol(kex): "+buf.getCommand()); + } + if(kex.getState()==KeyExchange.STATE_END){ + break; + } + } + + try{ checkHost(host, port, kex); } + catch(JSchException ee){ + in_kex=false; + throw ee; + } + + send_newkeys(); + + // receive SSH_MSG_NEWKEYS(21) + buf=read(buf); + //System.err.println("read: 21 ? "+buf.getCommand()); + if(buf.getCommand()==SSH_MSG_NEWKEYS){ + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "SSH_MSG_NEWKEYS received"); + } + + receive_newkeys(buf, kex); + } + else{ + in_kex=false; + throw new JSchException("invalid protocol(newkyes): "+buf.getCommand()); + } + + try{ + String s = getConfig("MaxAuthTries"); + if(s!=null){ + max_auth_tries = Integer.parseInt(s); + } + } + catch(NumberFormatException e){ + throw new JSchException("MaxAuthTries: "+getConfig("MaxAuthTries"), e); + } + + boolean auth=false; + boolean auth_cancel=false; + + UserAuth ua=null; + try{ + Class c=Class.forName(getConfig("userauth.none")); + ua=(UserAuth)(c.newInstance()); + } + catch(Exception e){ + throw new JSchException(e.toString(), e); + } + + auth=ua.start(this); + + String cmethods=getConfig("PreferredAuthentications"); + + String[] cmethoda=Util.split(cmethods, ","); + + String smethods=null; + if(!auth){ + smethods=((UserAuthNone)ua).getMethods(); + if(smethods!=null){ + smethods=smethods.toLowerCase(); + } + else{ + // methods: publickey,password,keyboard-interactive + //smethods="publickey,password,keyboard-interactive"; + smethods=cmethods; + } + } + + String[] smethoda=Util.split(smethods, ","); + + int methodi=0; + + loop: + while(true){ + + while(!auth && + cmethoda!=null && methodi= max_auth_tries){ + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "Login trials exceeds "+max_auth_tries); + } + } + if(auth_cancel) + throw new JSchException("Auth cancel"); + throw new JSchException("Auth fail"); + } + + if(socket!=null && (connectTimeout>0 || timeout>0)){ + socket.setSoTimeout(timeout); + } + + isAuthed=true; + + synchronized(lock){ + if(isConnected){ + connectThread=new Thread(this); + connectThread.setName("Connect thread "+host+" session"); + if(daemon_thread){ + connectThread.setDaemon(daemon_thread); + } + connectThread.start(); + + requestPortForwarding(); + } + else{ + // The session has been already down and + // we don't have to start new thread. + } + } + } + catch(Exception e) { + in_kex=false; + if(isConnected){ + try{ + packet.reset(); + buf.putByte((byte)SSH_MSG_DISCONNECT); + buf.putInt(3); + buf.putString(Util.str2byte(e.toString())); + buf.putString(Util.str2byte("en")); + write(packet); + disconnect(); + } + catch(Exception ee){ + } + } + isConnected=false; + //e.printStackTrace(); + if(e instanceof RuntimeException) throw (RuntimeException)e; + if(e instanceof JSchException) throw (JSchException)e; + throw new JSchException("Session.connect: "+e); + } + finally{ + Util.bzero(this.password); + this.password=null; + } + } + + private KeyExchange receive_kexinit(Buffer buf) throws Exception { + int j=buf.getInt(); + if(j!=buf.getLength()){ // packet was compressed and + buf.getByte(); // j is the size of deflated packet. + I_S=new byte[buf.index-5]; + } + else{ + I_S=new byte[j-1-buf.getByte()]; + } + System.arraycopy(buf.buffer, buf.s, I_S, 0, I_S.length); + + if(!in_kex){ // We are in rekeying activated by the remote! + send_kexinit(); + } + + guess=KeyExchange.guess(I_S, I_C); + if(guess==null){ + throw new JSchException("Algorithm negotiation fail"); + } + + if(!isAuthed && + (guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS].equals("none") || + (guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC].equals("none")))){ + throw new JSchException("NONE Cipher should not be chosen before authentification is successed."); + } + + KeyExchange kex=null; + try{ + Class c=Class.forName(getConfig(guess[KeyExchange.PROPOSAL_KEX_ALGS])); + kex=(KeyExchange)(c.newInstance()); + } + catch(Exception e){ + throw new JSchException(e.toString(), e); + } + + kex.init(this, V_S, V_C, I_S, I_C); + return kex; + } + + private boolean in_kex=false; + public void rekey() throws Exception { + send_kexinit(); + } + private void send_kexinit() throws Exception { + if(in_kex) + return; + + String cipherc2s=getConfig("cipher.c2s"); + String ciphers2c=getConfig("cipher.s2c"); + + String[] not_available_ciphers=checkCiphers(getConfig("CheckCiphers")); + if(not_available_ciphers!=null && not_available_ciphers.length>0){ + cipherc2s=Util.diffString(cipherc2s, not_available_ciphers); + ciphers2c=Util.diffString(ciphers2c, not_available_ciphers); + if(cipherc2s==null || ciphers2c==null){ + throw new JSchException("There are not any available ciphers."); + } + } + + String kex=getConfig("kex"); + String[] not_available_kexes=checkKexes(getConfig("CheckKexes")); + if(not_available_kexes!=null && not_available_kexes.length>0){ + kex=Util.diffString(kex, not_available_kexes); + if(kex==null){ + throw new JSchException("There are not any available kexes."); + } + } + + in_kex=true; + kex_start_time=System.currentTimeMillis(); + + // byte SSH_MSG_KEXINIT(20) + // byte[16] cookie (random bytes) + // string kex_algorithms + // string server_host_key_algorithms + // string encryption_algorithms_client_to_server + // string encryption_algorithms_server_to_client + // string mac_algorithms_client_to_server + // string mac_algorithms_server_to_client + // string compression_algorithms_client_to_server + // string compression_algorithms_server_to_client + // string languages_client_to_server + // string languages_server_to_client + Buffer buf = new Buffer(); // send_kexinit may be invoked + Packet packet = new Packet(buf); // by user thread. + packet.reset(); + buf.putByte((byte) SSH_MSG_KEXINIT); + synchronized(random){ + random.fill(buf.buffer, buf.index, 16); buf.skip(16); + } + buf.putString(Util.str2byte(kex)); + buf.putString(Util.str2byte(getConfig("server_host_key"))); + buf.putString(Util.str2byte(cipherc2s)); + buf.putString(Util.str2byte(ciphers2c)); + buf.putString(Util.str2byte(getConfig("mac.c2s"))); + buf.putString(Util.str2byte(getConfig("mac.s2c"))); + buf.putString(Util.str2byte(getConfig("compression.c2s"))); + buf.putString(Util.str2byte(getConfig("compression.s2c"))); + buf.putString(Util.str2byte(getConfig("lang.c2s"))); + buf.putString(Util.str2byte(getConfig("lang.s2c"))); + buf.putByte((byte)0); + buf.putInt(0); + + buf.setOffSet(5); + I_C=new byte[buf.getLength()]; + buf.getByte(I_C); + + write(packet); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "SSH_MSG_KEXINIT sent"); + } + } + + private void send_newkeys() throws Exception { + // send SSH_MSG_NEWKEYS(21) + packet.reset(); + buf.putByte((byte)SSH_MSG_NEWKEYS); + write(packet); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "SSH_MSG_NEWKEYS sent"); + } + } + + private void checkHost(String chost, int port, KeyExchange kex) throws JSchException { + String shkc=getConfig("StrictHostKeyChecking"); + + if(hostKeyAlias!=null){ + chost=hostKeyAlias; + } + + //System.err.println("shkc: "+shkc); + + byte[] K_S=kex.getHostKey(); + String key_type=kex.getKeyType(); + String key_fprint=kex.getFingerPrint(); + + if(hostKeyAlias==null && port!=22){ + chost=("["+chost+"]:"+port); + } + + HostKeyRepository hkr=getHostKeyRepository(); + + String hkh=getConfig("HashKnownHosts"); + if(hkh.equals("yes") && (hkr instanceof KnownHosts)){ + hostkey=((KnownHosts)hkr).createHashedHostKey(chost, K_S); + } + else{ + hostkey=new HostKey(chost, K_S); + } + + int i=0; + synchronized(hkr){ + i=hkr.check(chost, K_S); + } + + boolean insert=false; + if((shkc.equals("ask") || shkc.equals("yes")) && + i==HostKeyRepository.CHANGED){ + String file=null; + synchronized(hkr){ + file=hkr.getKnownHostsRepositoryID(); + } + if(file==null){file="known_hosts";} + + boolean b=false; + + if(userinfo!=null){ + String message= +"WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n"+ +"IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!\n"+ +"Someone could be eavesdropping on you right now (man-in-the-middle attack)!\n"+ +"It is also possible that the "+key_type+" host key has just been changed.\n"+ +"The fingerprint for the "+key_type+" key sent by the remote host is\n"+ +key_fprint+".\n"+ +"Please contact your system administrator.\n"+ +"Add correct host key in "+file+" to get rid of this message."; + + if(shkc.equals("ask")){ + b=userinfo.promptYesNo(message+ + "\nDo you want to delete the old key and insert the new key?"); + } + else{ // shkc.equals("yes") + userinfo.showMessage(message); + } + } + + if(!b){ + throw new JSchException("HostKey has been changed: "+chost); + } + + synchronized(hkr){ + hkr.remove(chost, + (key_type.equals("DSA") ? "ssh-dss" : "ssh-rsa"), + null); + insert=true; + } + } + + if((shkc.equals("ask") || shkc.equals("yes")) && + (i!=HostKeyRepository.OK) && !insert){ + if(shkc.equals("yes")){ + throw new JSchException("reject HostKey: "+host); + } + //System.err.println("finger-print: "+key_fprint); + if(userinfo!=null){ + boolean foo=userinfo.promptYesNo( +"The authenticity of host '"+host+"' can't be established.\n"+ +key_type+" key fingerprint is "+key_fprint+".\n"+ +"Are you sure you want to continue connecting?" + ); + if(!foo){ + throw new JSchException("reject HostKey: "+host); + } + insert=true; + } + else{ + if(i==HostKeyRepository.NOT_INCLUDED) + throw new JSchException("UnknownHostKey: "+host+". "+key_type+" key fingerprint is "+key_fprint); + else + throw new JSchException("HostKey has been changed: "+host); + } + } + + if(shkc.equals("no") && + HostKeyRepository.NOT_INCLUDED==i){ + insert=true; + } + + if(i==HostKeyRepository.OK){ + HostKey[] keys = + hkr.getHostKey(chost, + (key_type.equals("DSA") ? "ssh-dss" : "ssh-rsa")); + String _key= Util.byte2str(Util.toBase64(K_S, 0, K_S.length)); + for(int j=0; j< keys.length; j++){ + if(keys[i].getKey().equals(_key) && + keys[j].getMarker().equals("@revoked")){ + if(userinfo!=null){ + userinfo.showMessage( +"The "+ key_type +" host key for "+ host +" is marked as revoked.\n"+ +"This could mean that a stolen key is being used to "+ +"impersonate this host."); + } + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "Host '"+host+"' has provided revoked key."); + } + throw new JSchException("revoked HostKey: "+host); + } + } + } + + if(i==HostKeyRepository.OK && + JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "Host '"+host+"' is known and mathces the "+key_type+" host key"); + } + + if(insert && + JSch.getLogger().isEnabled(Logger.WARN)){ + JSch.getLogger().log(Logger.WARN, + "Permanently added '"+host+"' ("+key_type+") to the list of known hosts."); + } + + if(insert){ + synchronized(hkr){ + hkr.add(hostkey, userinfo); + } + } + } + +//public void start(){ (new Thread(this)).start(); } + + public Channel openChannel(String type) throws JSchException{ + if(!isConnected){ + throw new JSchException("session is down"); + } + try{ + Channel channel=Channel.getChannel(type); + addChannel(channel); + channel.init(); + if(channel instanceof ChannelSession){ + applyConfigChannel((ChannelSession)channel); + } + return channel; + } + catch(Exception e){ + //e.printStackTrace(); + } + return null; + } + + // encode will bin invoked in write with synchronization. + public void encode(Packet packet) throws Exception{ +//System.err.println("encode: "+packet.buffer.getCommand()); +//System.err.println(" "+packet.buffer.index); +//if(packet.buffer.getCommand()==96){ +//Thread.dumpStack(); +//} + if(deflater!=null){ + compress_len[0]=packet.buffer.index; + packet.buffer.buffer=deflater.compress(packet.buffer.buffer, + 5, compress_len); + packet.buffer.index=compress_len[0]; + } + if(c2scipher!=null){ + //packet.padding(c2scipher.getIVSize()); + packet.padding(c2scipher_size); + int pad=packet.buffer.buffer[4]; + synchronized(random){ + random.fill(packet.buffer.buffer, packet.buffer.index-pad, pad); + } + } + else{ + packet.padding(8); + } + + if(c2smac!=null){ + c2smac.update(seqo); + c2smac.update(packet.buffer.buffer, 0, packet.buffer.index); + c2smac.doFinal(packet.buffer.buffer, packet.buffer.index); + } + if(c2scipher!=null){ + byte[] buf=packet.buffer.buffer; + c2scipher.update(buf, 0, packet.buffer.index, buf, 0); + } + if(c2smac!=null){ + packet.buffer.skip(c2smac.getBlockSize()); + } + } + + int[] uncompress_len=new int[1]; + int[] compress_len=new int[1]; + + private int s2ccipher_size=8; + private int c2scipher_size=8; + public Buffer read(Buffer buf) throws Exception{ + int j=0; + while(true){ + buf.reset(); + io.getByte(buf.buffer, buf.index, s2ccipher_size); + buf.index+=s2ccipher_size; + if(s2ccipher!=null){ + s2ccipher.update(buf.buffer, 0, s2ccipher_size, buf.buffer, 0); + } + j=((buf.buffer[0]<<24)&0xff000000)| + ((buf.buffer[1]<<16)&0x00ff0000)| + ((buf.buffer[2]<< 8)&0x0000ff00)| + ((buf.buffer[3] )&0x000000ff); + // RFC 4253 6.1. Maximum Packet Length + if(j<5 || j>PACKET_MAX_SIZE){ + start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE); + } + int need = j+4-s2ccipher_size; + //if(need<0){ + // throw new IOException("invalid data"); + //} + if((buf.index+need)>buf.buffer.length){ + byte[] foo=new byte[buf.index+need]; + System.arraycopy(buf.buffer, 0, foo, 0, buf.index); + buf.buffer=foo; + } + + if((need%s2ccipher_size)!=0){ + String message="Bad packet length "+need; + if(JSch.getLogger().isEnabled(Logger.FATAL)){ + JSch.getLogger().log(Logger.FATAL, message); + } + start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE-s2ccipher_size); + } + + if(need>0){ + io.getByte(buf.buffer, buf.index, need); buf.index+=(need); + if(s2ccipher!=null){ + s2ccipher.update(buf.buffer, s2ccipher_size, need, buf.buffer, s2ccipher_size); + } + } + + if(s2cmac!=null){ + s2cmac.update(seqi); + s2cmac.update(buf.buffer, 0, buf.index); + + s2cmac.doFinal(s2cmac_result1, 0); + io.getByte(s2cmac_result2, 0, s2cmac_result2.length); + if(!java.util.Arrays.equals(s2cmac_result1, s2cmac_result2)){ + if(need > PACKET_MAX_SIZE){ + throw new IOException("MAC Error"); + } + start_discard(buf, s2ccipher, s2cmac, j, PACKET_MAX_SIZE-need); + continue; + } + } + + seqi++; + + if(inflater!=null){ + //inflater.uncompress(buf); + int pad=buf.buffer[4]; + uncompress_len[0]=buf.index-5-pad; + byte[] foo=inflater.uncompress(buf.buffer, 5, uncompress_len); + if(foo!=null){ + buf.buffer=foo; + buf.index=5+uncompress_len[0]; + } + else{ + System.err.println("fail in inflater"); + break; + } + } + + int type=buf.getCommand()&0xff; + //System.err.println("read: "+type); + if(type==SSH_MSG_DISCONNECT){ + buf.rewind(); + buf.getInt();buf.getShort(); + int reason_code=buf.getInt(); + byte[] description=buf.getString(); + byte[] language_tag=buf.getString(); + throw new JSchException("SSH_MSG_DISCONNECT: "+ + reason_code+ + " "+Util.byte2str(description)+ + " "+Util.byte2str(language_tag)); + //break; + } + else if(type==SSH_MSG_IGNORE){ + } + else if(type==SSH_MSG_UNIMPLEMENTED){ + buf.rewind(); + buf.getInt();buf.getShort(); + int reason_id=buf.getInt(); + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "Received SSH_MSG_UNIMPLEMENTED for "+reason_id); + } + } + else if(type==SSH_MSG_DEBUG){ + buf.rewind(); + buf.getInt();buf.getShort(); +/* + byte always_display=(byte)buf.getByte(); + byte[] message=buf.getString(); + byte[] language_tag=buf.getString(); + System.err.println("SSH_MSG_DEBUG:"+ + " "+Util.byte2str(message)+ + " "+Util.byte2str(language_tag)); +*/ + } + else if(type==SSH_MSG_CHANNEL_WINDOW_ADJUST){ + buf.rewind(); + buf.getInt();buf.getShort(); + Channel c=Channel.getChannel(buf.getInt(), this); + if(c==null){ + } + else{ + c.addRemoteWindowSize(buf.getInt()); + } + } + else if(type==UserAuth.SSH_MSG_USERAUTH_SUCCESS){ + isAuthed=true; + if(inflater==null && deflater==null){ + String method; + method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS]; + initDeflater(method); + method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC]; + initInflater(method); + } + break; + } + else{ + break; + } + } + buf.rewind(); + return buf; + } + + private void start_discard(Buffer buf, Cipher cipher, MAC mac, + int packet_length, int discard) throws JSchException, IOException{ + MAC discard_mac = null; + + if(!cipher.isCBC()){ + throw new JSchException("Packet corrupt"); + } + + if(packet_length!=PACKET_MAX_SIZE && mac != null){ + discard_mac = mac; + } + + discard -= buf.index; + + while(discard>0){ + buf.reset(); + int len = discard>buf.buffer.length ? buf.buffer.length : discard; + io.getByte(buf.buffer, 0, len); + if(discard_mac!=null){ + discard_mac.update(buf.buffer, 0, len); + } + discard -= len; + } + + if(discard_mac!=null){ + discard_mac.doFinal(buf.buffer, 0); + } + + throw new JSchException("Packet corrupt"); + } + + byte[] getSessionId(){ + return session_id; + } + + private void receive_newkeys(Buffer buf, KeyExchange kex) throws Exception { + updateKeys(kex); + in_kex=false; + } + private void updateKeys(KeyExchange kex) throws Exception{ + byte[] K=kex.getK(); + byte[] H=kex.getH(); + HASH hash=kex.getHash(); + + if(session_id==null){ + session_id=new byte[H.length]; + System.arraycopy(H, 0, session_id, 0, H.length); + } + + /* + Initial IV client to server: HASH (K || H || "A" || session_id) + Initial IV server to client: HASH (K || H || "B" || session_id) + Encryption key client to server: HASH (K || H || "C" || session_id) + Encryption key server to client: HASH (K || H || "D" || session_id) + Integrity key client to server: HASH (K || H || "E" || session_id) + Integrity key server to client: HASH (K || H || "F" || session_id) + */ + + buf.reset(); + buf.putMPInt(K); + buf.putByte(H); + buf.putByte((byte)0x41); + buf.putByte(session_id); + hash.update(buf.buffer, 0, buf.index); + IVc2s=hash.digest(); + + int j=buf.index-session_id.length-1; + + buf.buffer[j]++; + hash.update(buf.buffer, 0, buf.index); + IVs2c=hash.digest(); + + buf.buffer[j]++; + hash.update(buf.buffer, 0, buf.index); + Ec2s=hash.digest(); + + buf.buffer[j]++; + hash.update(buf.buffer, 0, buf.index); + Es2c=hash.digest(); + + buf.buffer[j]++; + hash.update(buf.buffer, 0, buf.index); + MACc2s=hash.digest(); + + buf.buffer[j]++; + hash.update(buf.buffer, 0, buf.index); + MACs2c=hash.digest(); + + try{ + Class c; + String method; + + method=guess[KeyExchange.PROPOSAL_ENC_ALGS_STOC]; + c=Class.forName(getConfig(method)); + s2ccipher=(Cipher)(c.newInstance()); + while(s2ccipher.getBlockSize()>Es2c.length){ + buf.reset(); + buf.putMPInt(K); + buf.putByte(H); + buf.putByte(Es2c); + hash.update(buf.buffer, 0, buf.index); + byte[] foo=hash.digest(); + byte[] bar=new byte[Es2c.length+foo.length]; + System.arraycopy(Es2c, 0, bar, 0, Es2c.length); + System.arraycopy(foo, 0, bar, Es2c.length, foo.length); + Es2c=bar; + } + s2ccipher.init(Cipher.DECRYPT_MODE, Es2c, IVs2c); + s2ccipher_size=s2ccipher.getIVSize(); + + method=guess[KeyExchange.PROPOSAL_MAC_ALGS_STOC]; + c=Class.forName(getConfig(method)); + s2cmac=(MAC)(c.newInstance()); + MACs2c = expandKey(buf, K, H, MACs2c, hash, s2cmac.getBlockSize()); + s2cmac.init(MACs2c); + //mac_buf=new byte[s2cmac.getBlockSize()]; + s2cmac_result1=new byte[s2cmac.getBlockSize()]; + s2cmac_result2=new byte[s2cmac.getBlockSize()]; + + method=guess[KeyExchange.PROPOSAL_ENC_ALGS_CTOS]; + c=Class.forName(getConfig(method)); + c2scipher=(Cipher)(c.newInstance()); + while(c2scipher.getBlockSize()>Ec2s.length){ + buf.reset(); + buf.putMPInt(K); + buf.putByte(H); + buf.putByte(Ec2s); + hash.update(buf.buffer, 0, buf.index); + byte[] foo=hash.digest(); + byte[] bar=new byte[Ec2s.length+foo.length]; + System.arraycopy(Ec2s, 0, bar, 0, Ec2s.length); + System.arraycopy(foo, 0, bar, Ec2s.length, foo.length); + Ec2s=bar; + } + c2scipher.init(Cipher.ENCRYPT_MODE, Ec2s, IVc2s); + c2scipher_size=c2scipher.getIVSize(); + + method=guess[KeyExchange.PROPOSAL_MAC_ALGS_CTOS]; + c=Class.forName(getConfig(method)); + c2smac=(MAC)(c.newInstance()); + MACc2s = expandKey(buf, K, H, MACc2s, hash, c2smac.getBlockSize()); + c2smac.init(MACc2s); + + method=guess[KeyExchange.PROPOSAL_COMP_ALGS_CTOS]; + initDeflater(method); + + method=guess[KeyExchange.PROPOSAL_COMP_ALGS_STOC]; + initInflater(method); + } + catch(Exception e){ + if(e instanceof JSchException) + throw e; + throw new JSchException(e.toString(), e); + //System.err.println("updatekeys: "+e); + } + } + + + /* + * RFC 4253 7.2. Output from Key Exchange + * If the key length needed is longer than the output of the HASH, the + * key is extended by computing HASH of the concatenation of K and H and + * the entire key so far, and appending the resulting bytes (as many as + * HASH generates) to the key. This process is repeated until enough + * key material is available; the key is taken from the beginning of + * this value. In other words: + * K1 = HASH(K || H || X || session_id) (X is e.g., "A") + * K2 = HASH(K || H || K1) + * K3 = HASH(K || H || K1 || K2) + * ... + * key = K1 || K2 || K3 || ... + */ + private byte[] expandKey(Buffer buf, byte[] K, byte[] H, byte[] key, + HASH hash, int required_length) throws Exception { + byte[] result = key; + int size = hash.getBlockSize(); + while(result.length < required_length){ + buf.reset(); + buf.putMPInt(K); + buf.putByte(H); + buf.putByte(result); + hash.update(buf.buffer, 0, buf.index); + byte[] tmp = new byte[result.length+size]; + System.arraycopy(result, 0, tmp, 0, result.length); + System.arraycopy(hash.digest(), 0, tmp, result.length, size); + Util.bzero(result); + result = tmp; + } + return result; + } + + /*public*/ /*synchronized*/ void write(Packet packet, Channel c, int length) throws Exception{ + long t = getTimeout(); + while(true){ + if(in_kex){ + if(t>0L && (System.currentTimeMillis()-kex_start_time)>t){ + throw new JSchException("timeout in wating for rekeying process."); + } + try{Thread.sleep(10);} + catch(java.lang.InterruptedException e){}; + continue; + } + synchronized(c){ + + if(c.rwsize=length){ + c.rwsize-=length; + break; + } + + } + if(c.close || !c.isConnected()){ + throw new IOException("channel is broken"); + } + + boolean sendit=false; + int s=0; + byte command=0; + int recipient=-1; + synchronized(c){ + if(c.rwsize>0){ + long len=c.rwsize; + if(len>length){ + len=length; + } + if(len!=length){ + s=packet.shift((int)len, + (c2scipher!=null ? c2scipher_size : 8), + (c2smac!=null ? c2smac.getBlockSize() : 0)); + } + command=packet.buffer.getCommand(); + recipient=c.getRecipient(); + length-=len; + c.rwsize-=len; + sendit=true; + } + } + if(sendit){ + _write(packet); + if(length==0){ + return; + } + packet.unshift(command, recipient, s, length); + } + + synchronized(c){ + if(in_kex){ + continue; + } + if(c.rwsize>=length){ + c.rwsize-=length; + break; + } + + //try{ + //System.out.println("1wait: "+c.rwsize); + // c.notifyme++; + // c.wait(100); + //} + //catch(java.lang.InterruptedException e){ + //} + //finally{ + // c.notifyme--; + //} + } + } + _write(packet); + } + + public void write(Packet packet) throws Exception{ + // System.err.println("in_kex="+in_kex+" "+(packet.buffer.getCommand())); + long t = getTimeout(); + while(in_kex){ + if(t>0L && (System.currentTimeMillis()-kex_start_time)>t){ + throw new JSchException("timeout in wating for rekeying process."); + } + byte command=packet.buffer.getCommand(); + //System.err.println("command: "+command); + if(command==SSH_MSG_KEXINIT || + command==SSH_MSG_NEWKEYS || + command==SSH_MSG_KEXDH_INIT || + command==SSH_MSG_KEXDH_REPLY || + command==SSH_MSG_KEX_DH_GEX_GROUP || + command==SSH_MSG_KEX_DH_GEX_INIT || + command==SSH_MSG_KEX_DH_GEX_REPLY || + command==SSH_MSG_KEX_DH_GEX_REQUEST || + command==SSH_MSG_DISCONNECT){ + break; + } + try{Thread.sleep(10);} + catch(java.lang.InterruptedException e){}; + } + _write(packet); + } + + private void _write(Packet packet) throws Exception{ + synchronized(lock){ + encode(packet); + if(io!=null){ + io.put(packet); + seqo++; + } + } + } + + Runnable thread; + public void run(){ + thread=this; + + byte[] foo; + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + int i=0; + Channel channel; + int[] start=new int[1]; + int[] length=new int[1]; + KeyExchange kex=null; + + int stimeout=0; + try{ + while(isConnected && + thread!=null){ + try{ + buf=read(buf); + stimeout=0; + } + catch(InterruptedIOException/*SocketTimeoutException*/ ee){ + if(!in_kex && stimeoutlport is 0, the tcp port will be allocated. + * @param lport local port for local port forwarding + * @param host host address for local port forwarding + * @param rport remote port number for local port forwarding + * @return an allocated local TCP port number + * @see #setPortForwardingL(String bind_address, int lport, String host, int rport, ServerSocketFactory ssf, int connectTimeout) + */ + public int setPortForwardingL(int lport, String host, int rport) throws JSchException{ + return setPortForwardingL("127.0.0.1", lport, host, rport); + } + + /** + * Registers the local port forwarding. If bind_address is an empty string + * or '*', the port should be available from all interfaces. + * If bind_address is "localhost" or + * null, the listening port will be bound for local use only. + * If lport is 0, the tcp port will be allocated. + * @param bind_address bind address for local port forwarding + * @param lport local port for local port forwarding + * @param host host address for local port forwarding + * @param rport remote port number for local port forwarding + * @return an allocated local TCP port number + * @see #setPortForwardingL(String bind_address, int lport, String host, int rport, ServerSocketFactory ssf, int connectTimeout) + */ + public int setPortForwardingL(String bind_address, int lport, String host, int rport) throws JSchException{ + return setPortForwardingL(bind_address, lport, host, rport, null); + } + + /** + * Registers the local port forwarding. + * If bind_address is an empty string or "*", + * the port should be available from all interfaces. + * If bind_address is "localhost" or + * null, the listening port will be bound for local use only. + * If lport is 0, the tcp port will be allocated. + * @param bind_address bind address for local port forwarding + * @param lport local port for local port forwarding + * @param host host address for local port forwarding + * @param rport remote port number for local port forwarding + * @param ssf socket factory + * @return an allocated local TCP port number + * @see #setPortForwardingL(String bind_address, int lport, String host, int rport, ServerSocketFactory ssf, int connectTimeout) + */ + public int setPortForwardingL(String bind_address, int lport, String host, int rport, ServerSocketFactory ssf) throws JSchException{ + return setPortForwardingL(bind_address, lport, host, rport, ssf, 0); + } + + /** + * Registers the local port forwarding. + * If bind_address is an empty string + * or "*", the port should be available from all interfaces. + * If bind_address is "localhost" or + * null, the listening port will be bound for local use only. + * If lport is 0, the tcp port will be allocated. + * @param bind_address bind address for local port forwarding + * @param lport local port for local port forwarding + * @param host host address for local port forwarding + * @param rport remote port number for local port forwarding + * @param ssf socket factory + * @param connectTimeout timeout for establishing port connection + * @return an allocated local TCP port number + */ + public int setPortForwardingL(String bind_address, int lport, String host, int rport, ServerSocketFactory ssf, int connectTimeout) throws JSchException{ + PortWatcher pw=PortWatcher.addPort(this, bind_address, lport, host, rport, ssf); + pw.setConnectTimeout(connectTimeout); + Thread tmp=new Thread(pw); + tmp.setName("PortWatcher Thread for "+host); + if(daemon_thread){ + tmp.setDaemon(daemon_thread); + } + tmp.start(); + return pw.lport; + } + + /** + * Cancels the local port forwarding assigned + * at local TCP port lport on loopback interface. + * + * @param lport local TCP port + */ + public void delPortForwardingL(int lport) throws JSchException{ + delPortForwardingL("127.0.0.1", lport); + } + + /** + * Cancels the local port forwarding assigned + * at local TCP port lport on bind_address interface. + * + * @param bind_address bind_address of network interfaces + * @param lport local TCP port + */ + public void delPortForwardingL(String bind_address, int lport) throws JSchException{ + PortWatcher.delPort(this, bind_address, lport); + } + + /** + * Lists the registered local port forwarding. + * + * @return a list of "lport:host:hostport" + */ + public String[] getPortForwardingL() throws JSchException{ + return PortWatcher.getPortForwarding(this); + } + + /** + * Registers the remote port forwarding for the loopback interface + * of the remote. + * + * @param rport remote port + * @param host host address + * @param lport local port + * @see #setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf) + */ + public void setPortForwardingR(int rport, String host, int lport) throws JSchException{ + setPortForwardingR(null, rport, host, lport, (SocketFactory)null); + } + + /** + * Registers the remote port forwarding. + * If bind_address is an empty string or "*", + * the port should be available from all interfaces. + * If bind_address is "localhost" or is not given, + * the listening port will be bound for local use only. + * Note that if GatewayPorts is "no" on the + * remote, "localhost" is always used as a bind_address. + * + * @param bind_address bind address + * @param rport remote port + * @param host host address + * @param lport local port + * @see #setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf) + */ + public void setPortForwardingR(String bind_address, int rport, String host, int lport) throws JSchException{ + setPortForwardingR(bind_address, rport, host, lport, (SocketFactory)null); + } + + /** + * Registers the remote port forwarding for the loopback interface + * of the remote. + * + * @param rport remote port + * @param host host address + * @param lport local port + * @param sf socket factory + * @see #setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf) + */ + public void setPortForwardingR(int rport, String host, int lport, SocketFactory sf) throws JSchException{ + setPortForwardingR(null, rport, host, lport, sf); + } + + // TODO: This method should return the integer value as the assigned port. + /** + * Registers the remote port forwarding. + * If bind_address is an empty string or "*", + * the port should be available from all interfaces. + * If bind_address is "localhost" or is not given, + * the listening port will be bound for local use only. + * Note that if GatewayPorts is "no" on the + * remote, "localhost" is always used as a bind_address. + * If rport is 0, the TCP port will be allocated on the remote. + * + * @param bind_address bind address + * @param rport remote port + * @param host host address + * @param lport local port + * @param sf socket factory + */ + public void setPortForwardingR(String bind_address, int rport, String host, int lport, SocketFactory sf) throws JSchException{ + int allocated=_setPortForwardingR(bind_address, rport); + ChannelForwardedTCPIP.addPort(this, bind_address, + rport, allocated, host, lport, sf); + } + + /** + * Registers the remote port forwarding for the loopback interface + * of the remote. + * The TCP connection to rport on the remote will be + * forwarded to an instance of the class daemon. + * The class specified by daemon must implement + * ForwardedTCPIPDaemon. + * + * @param rport remote port + * @param daemon class name, which implements "ForwardedTCPIPDaemon" + * @see #setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg) + */ + public void setPortForwardingR(int rport, String daemon) throws JSchException{ + setPortForwardingR(null, rport, daemon, null); + } + + /** + * Registers the remote port forwarding for the loopback interface + * of the remote. + * The TCP connection to rport on the remote will be + * forwarded to an instance of the class daemon with + * the argument arg. + * The class specified by daemon must implement ForwardedTCPIPDaemon. + * + * @param rport remote port + * @param daemon class name, which implements "ForwardedTCPIPDaemon" + * @param arg arguments for "daemon" + * @see #setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg) + */ + public void setPortForwardingR(int rport, String daemon, Object[] arg) throws JSchException{ + setPortForwardingR(null, rport, daemon, arg); + } + + /** + * Registers the remote port forwarding. + * If bind_address is an empty string + * or "*", the port should be available from all interfaces. + * If bind_address is "localhost" or is not given, + * the listening port will be bound for local use only. + * Note that if GatewayPorts is "no" on the + * remote, "localhost" is always used as a bind_address. + * The TCP connection to rport on the remote will be + * forwarded to an instance of the class daemon with the + * argument arg. + * The class specified by daemon must implement ForwardedTCPIPDaemon. + * + * @param bind_address bind address + * @param rport remote port + * @param daemon class name, which implements "ForwardedTCPIPDaemon" + * @param arg arguments for "daemon" + * @see #setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg) + */ + public void setPortForwardingR(String bind_address, int rport, String daemon, Object[] arg) throws JSchException{ + int allocated = _setPortForwardingR(bind_address, rport); + ChannelForwardedTCPIP.addPort(this, bind_address, + rport, allocated, daemon, arg); + } + + /** + * Lists the registered remote port forwarding. + * + * @return a list of "rport:host:hostport" + */ + public String[] getPortForwardingR() throws JSchException{ + return ChannelForwardedTCPIP.getPortForwarding(this); + } + + private class Forwarding { + String bind_address = null; + int port = -1; + String host = null; + int hostport = -1; + } + + /** + * The given argument may be "[bind_address:]port:host:hostport" or + * "[bind_address:]port host:hostport", which is from LocalForward command of + * ~/.ssh/config . + */ + private Forwarding parseForwarding(String conf) throws JSchException { + String[] tmp = conf.split(" "); + if(tmp.length>1){ // "[bind_address:]port host:hostport" + Vector foo = new Vector(); + for(int i=0; ibind_address is an empty string or "*", + * the port should be available from all interfaces. + * If bind_address is "localhost" or is not given, + * the listening port will be bound for local use only. + * + * @param conf configuration of local port forwarding + * @return an assigned port number + * @see #setPortForwardingL(String bind_address, int lport, String host, int rport) + */ + public int setPortForwardingL(String conf) throws JSchException { + Forwarding f = parseForwarding(conf); + return setPortForwardingL(f.bind_address, f.port, f.host, f.hostport); + } + + /** + * Registers the remote port forwarding. The argument should be + * in the format like "[bind_address:]port:host:hostport". If the + * bind_address is not given, the default is to only bind to loopback + * addresses. If the bind_address is "*" or an empty string, + * then the forwarding is requested to listen on all interfaces. + * Note that if GatewayPorts is "no" on the remote, + * "localhost" is always used for bind_address. + * If the specified remote is "0", + * the TCP port will be allocated on the remote. + * + * @param conf configuration of remote port forwarding + * @return an allocated TCP port on the remote. + * @see #setPortForwardingR(String bind_address, int rport, String host, int rport) + */ + public int setPortForwardingR(String conf) throws JSchException { + Forwarding f = parseForwarding(conf); + int allocated = _setPortForwardingR(f.bind_address, f.port); + ChannelForwardedTCPIP.addPort(this, f.bind_address, + f.port, allocated, f.host, f.hostport, null); + return allocated; + } + + /** + * Instantiates an instance of stream-forwarder to host:port. + * Set I/O stream to the given channel, and then invoke Channel#connect() method. + * + * @param host remote host, which the given stream will be plugged to. + * @param port remote port, which the given stream will be plugged to. + */ + public Channel getStreamForwarder(String host, int port) throws JSchException { + ChannelDirectTCPIP channel = new ChannelDirectTCPIP(); + channel.init(); + this.addChannel(channel); + channel.setHost(host); + channel.setPort(port); + return channel; + } + + private class GlobalRequestReply{ + private Thread thread=null; + private int reply=-1; + private int port=0; + void setThread(Thread thread){ + this.thread=thread; + this.reply=-1; + } + Thread getThread(){ return thread; } + void setReply(int reply){ this.reply=reply; } + int getReply(){ return this.reply; } + int getPort(){ return this.port; } + void setPort(int port){ this.port=port; } + } + private GlobalRequestReply grr=new GlobalRequestReply(); + private int _setPortForwardingR(String bind_address, int rport) throws JSchException{ + synchronized(grr){ + Buffer buf=new Buffer(100); // ?? + Packet packet=new Packet(buf); + + String address_to_bind=ChannelForwardedTCPIP.normalize(bind_address); + + grr.setThread(Thread.currentThread()); + grr.setPort(rport); + + try{ + // byte SSH_MSG_GLOBAL_REQUEST 80 + // string "tcpip-forward" + // boolean want_reply + // string address_to_bind + // uint32 port number to bind + packet.reset(); + buf.putByte((byte) SSH_MSG_GLOBAL_REQUEST); + buf.putString(Util.str2byte("tcpip-forward")); + buf.putByte((byte)1); + buf.putString(Util.str2byte(address_to_bind)); + buf.putInt(rport); + write(packet); + } + catch(Exception e){ + grr.setThread(null); + if(e instanceof Throwable) + throw new JSchException(e.toString(), (Throwable)e); + throw new JSchException(e.toString()); + } + + int count = 0; + int reply = grr.getReply(); + while(count < 10 && reply == -1){ + try{ Thread.sleep(1000); } + catch(Exception e){ + } + count++; + reply = grr.getReply(); + } + grr.setThread(null); + if(reply != 1){ + throw new JSchException("remote port forwarding failed for listen port "+rport); + } + rport=grr.getPort(); + } + return rport; + } + + /** + * Cancels the remote port forwarding assigned at remote TCP port rport. + * + * @param rport remote TCP port + */ + public void delPortForwardingR(int rport) throws JSchException{ + this.delPortForwardingR(null, rport); + } + + /** + * Cancels the remote port forwarding assigned at + * remote TCP port rport bound on the interface at + * bind_address. + * + * @param bind_address bind address of the interface on the remote + * @param rport remote TCP port + */ + public void delPortForwardingR(String bind_address, int rport) throws JSchException{ + ChannelForwardedTCPIP.delPort(this, bind_address, rport); + } + + private void initDeflater(String method) throws JSchException{ + if(method.equals("none")){ + deflater=null; + return; + } + String foo=getConfig(method); + if(foo!=null){ + if(method.equals("zlib") || + (isAuthed && method.equals("zlib@openssh.com"))){ + try{ + Class c=Class.forName(foo); + deflater=(Compression)(c.newInstance()); + int level=6; + try{ level=Integer.parseInt(getConfig("compression_level"));} + catch(Exception ee){ } + deflater.init(Compression.DEFLATER, level); + } + catch(NoClassDefFoundError ee){ + throw new JSchException(ee.toString(), ee); + } + catch(Exception ee){ + throw new JSchException(ee.toString(), ee); + //System.err.println(foo+" isn't accessible."); + } + } + } + } + private void initInflater(String method) throws JSchException{ + if(method.equals("none")){ + inflater=null; + return; + } + String foo=getConfig(method); + if(foo!=null){ + if(method.equals("zlib") || + (isAuthed && method.equals("zlib@openssh.com"))){ + try{ + Class c=Class.forName(foo); + inflater=(Compression)(c.newInstance()); + inflater.init(Compression.INFLATER, 0); + } + catch(Exception ee){ + throw new JSchException(ee.toString(), ee); + //System.err.println(foo+" isn't accessible."); + } + } + } + } + + void addChannel(Channel channel){ + channel.setSession(this); + } + + public void setProxy(Proxy proxy){ this.proxy=proxy; } + public void setHost(String host){ this.host=host; } + public void setPort(int port){ this.port=port; } + void setUserName(String username){ this.username=username; } + public void setUserInfo(UserInfo userinfo){ this.userinfo=userinfo; } + public UserInfo getUserInfo(){ return userinfo; } + public void setInputStream(InputStream in){ this.in=in; } + public void setOutputStream(OutputStream out){ this.out=out; } + public void setX11Host(String host){ ChannelX11.setHost(host); } + public void setX11Port(int port){ ChannelX11.setPort(port); } + public void setX11Cookie(String cookie){ ChannelX11.setCookie(cookie); } + public void setPassword(String password){ + if(password!=null) + this.password=Util.str2byte(password); + } + public void setPassword(byte[] password){ + if(password!=null){ + this.password=new byte[password.length]; + System.arraycopy(password, 0, this.password, 0, password.length); + } + } + + public void setConfig(java.util.Properties newconf){ + setConfig((java.util.Hashtable)newconf); + } + + public void setConfig(java.util.Hashtable newconf){ + synchronized(lock){ + if(config==null) + config=new java.util.Hashtable(); + for(java.util.Enumeration e=newconf.keys() ; e.hasMoreElements() ;) { + String key=(String)(e.nextElement()); + config.put(key, (String)(newconf.get(key))); + } + } + } + + public void setConfig(String key, String value){ + synchronized(lock){ + if(config==null){ + config=new java.util.Hashtable(); + } + config.put(key, value); + } + } + + public String getConfig(String key){ + Object foo=null; + if(config!=null){ + foo=config.get(key); + if(foo instanceof String) return (String)foo; + } + foo=jsch.getConfig(key); + if(foo instanceof String) return (String)foo; + return null; + } + + public void setSocketFactory(SocketFactory sfactory){ + socket_factory=sfactory; + } + public boolean isConnected(){ return isConnected; } + public int getTimeout(){ return timeout; } + public void setTimeout(int timeout) throws JSchException { + if(socket==null){ + if(timeout<0){ + throw new JSchException("invalid timeout value"); + } + this.timeout=timeout; + return; + } + try{ + socket.setSoTimeout(timeout); + this.timeout=timeout; + } + catch(Exception e){ + if(e instanceof Throwable) + throw new JSchException(e.toString(), (Throwable)e); + throw new JSchException(e.toString()); + } + } + public String getServerVersion(){ + return Util.byte2str(V_S); + } + public String getClientVersion(){ + return Util.byte2str(V_C); + } + public void setClientVersion(String cv){ + V_C=Util.str2byte(cv); + } + + public void sendIgnore() throws Exception{ + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + packet.reset(); + buf.putByte((byte)SSH_MSG_IGNORE); + write(packet); + } + + private static final byte[] keepalivemsg=Util.str2byte("keepalive@jcraft.com"); + public void sendKeepAliveMsg() throws Exception{ + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + packet.reset(); + buf.putByte((byte)SSH_MSG_GLOBAL_REQUEST); + buf.putString(keepalivemsg); + buf.putByte((byte)1); + write(packet); + } + + private static final byte[] nomoresessions=Util.str2byte("no-more-sessions@openssh.com"); + public void noMoreSessionChannels() throws Exception{ + Buffer buf=new Buffer(); + Packet packet=new Packet(buf); + packet.reset(); + buf.putByte((byte)SSH_MSG_GLOBAL_REQUEST); + buf.putString(nomoresessions); + buf.putByte((byte)0); + write(packet); + } + + private HostKey hostkey=null; + public HostKey getHostKey(){ return hostkey; } + public String getHost(){return host;} + public String getUserName(){return username;} + public int getPort(){return port;} + public void setHostKeyAlias(String hostKeyAlias){ + this.hostKeyAlias=hostKeyAlias; + } + public String getHostKeyAlias(){ + return hostKeyAlias; + } + + /** + * Sets the interval to send a keep-alive message. If zero is + * specified, any keep-alive message must not be sent. The default interval + * is zero. + * + * @param interval the specified interval, in milliseconds. + * @see #getServerAliveInterval() + */ + public void setServerAliveInterval(int interval) throws JSchException { + setTimeout(interval); + this.serverAliveInterval=interval; + } + + /** + * Returns setting for the interval to send a keep-alive message. + * + * @see #setServerAliveInterval(int) + */ + public int getServerAliveInterval(){ + return this.serverAliveInterval; + } + + /** + * Sets the number of keep-alive messages which may be sent without + * receiving any messages back from the server. If this threshold is + * reached while keep-alive messages are being sent, the connection will + * be disconnected. The default value is one. + * + * @param count the specified count + * @see #getServerAliveCountMax() + */ + public void setServerAliveCountMax(int count){ + this.serverAliveCountMax=count; + } + + /** + * Returns setting for the threshold to send keep-alive messages. + * + * @see #setServerAliveCountMax(int) + */ + public int getServerAliveCountMax(){ + return this.serverAliveCountMax; + } + + public void setDaemonThread(boolean enable){ + this.daemon_thread=enable; + } + + private String[] checkCiphers(String ciphers){ + if(ciphers==null || ciphers.length()==0) + return null; + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + JSch.getLogger().log(Logger.INFO, + "CheckCiphers: "+ciphers); + } + + Vector result=new Vector(); + String[] _ciphers=Util.split(ciphers, ","); + for(int i=0; i<_ciphers.length; i++){ + if(!checkCipher(getConfig(_ciphers[i]))){ + result.addElement(_ciphers[i]); + } + } + if(result.size()==0) + return null; + String[] foo=new String[result.size()]; + System.arraycopy(result.toArray(), 0, foo, 0, result.size()); + + if(JSch.getLogger().isEnabled(Logger.INFO)){ + for(int i=0; inull. + * + * @param identityRepository + * @see #getIdentityRepository() + */ + public void setIdentityRepository(IdentityRepository identityRepository){ + this.identityRepository = identityRepository; + } + + /** + * Gets the identityRepository. + * If this.identityRepository is null, + * JSch#getIdentityRepository() will be invoked. + * + * @see JSch#getIdentityRepository() + */ + IdentityRepository getIdentityRepository(){ + if(identityRepository == null) + return jsch.getIdentityRepository(); + return identityRepository; + } + + /** + * Sets the hostkeyRepository, which will be referred + * in the host key checking. + * + * @param hostkeyRepository + * @see #getHostKeyRepository() + */ + public void setHostKeyRepository(HostKeyRepository hostkeyRepository){ + this.hostkeyRepository = hostkeyRepository; + } + + /** + * Gets the hostkeyRepository. + * If this.hostkeyRepository is null, + * JSch#getHostKeyRepository() will be invoked. + * + * @see JSch#getHostKeyRepository() + */ + public HostKeyRepository getHostKeyRepository(){ + if(hostkeyRepository == null) + return jsch.getHostKeyRepository(); + return hostkeyRepository; + } + + /* + // setProxyCommand("ssh -l user2 host2 -o 'ProxyCommand ssh user1@host1 nc host2 22' nc %h %p") + public void setProxyCommand(String command){ + setProxy(new ProxyCommand(command)); + } + + class ProxyCommand implements Proxy { + String command; + Process p = null; + InputStream in = null; + OutputStream out = null; + ProxyCommand(String command){ + this.command = command; + } + public void connect(SocketFactory socket_factory, String host, int port, int timeout) throws Exception { + String _command = command.replace("%h", host); + _command = _command.replace("%p", new Integer(port).toString()); + p = Runtime.getRuntime().exec(_command); + in = p.getInputStream(); + out = p.getOutputStream(); + } + public Socket getSocket() { return null; } + public InputStream getInputStream() { return in; } + public OutputStream getOutputStream() { return out; } + public void close() { + try{ + if(p!=null){ + p.getErrorStream().close(); + p.getOutputStream().close(); + p.getInputStream().close(); + p.destroy(); + p=null; + } + } + catch(IOException e){ + } + } + } + */ + + private void applyConfig() throws JSchException { + ConfigRepository configRepository = jsch.getConfigRepository(); + if(configRepository == null){ + return; + } + + ConfigRepository.Config config = + configRepository.getConfig(org_host); + + String value = null; + + value = config.getUser(); + if(value != null) + username = value; + + value = config.getHostname(); + if(value != null) + host = value; + + int port = config.getPort(); + if(port != -1) + this.port = port; + + checkConfig(config, "kex"); + checkConfig(config, "server_host_key"); + + checkConfig(config, "cipher.c2s"); + checkConfig(config, "cipher.s2c"); + checkConfig(config, "mac.c2s"); + checkConfig(config, "mac.s2c"); + checkConfig(config, "compression.c2s"); + checkConfig(config, "compression.s2c"); + checkConfig(config, "compression_level"); + + checkConfig(config, "StrictHostKeyChecking"); + checkConfig(config, "HashKnownHosts"); + checkConfig(config, "PreferredAuthentications"); + checkConfig(config, "MaxAuthTries"); + checkConfig(config, "ClearAllForwardings"); + + value = config.getValue("HostKeyAlias"); + if(value != null) + this.setHostKeyAlias(value); + + value = config.getValue("UserKnownHostsFile"); + if(value != null) { + KnownHosts kh = new KnownHosts(jsch); + kh.setKnownHosts(value); + this.setHostKeyRepository(kh); + } + + String[] values = config.getValues("IdentityFile"); + if(values != null) { + String[] global = + configRepository.getConfig("").getValues("IdentityFile"); + if(global != null){ + for(int i = 0; i < global.length; i++){ + jsch.addIdentity(global[i]); + } + } + else { + global = new String[0]; + } + if(values.length - global.length > 0){ + IdentityRepository.Wrapper ir = + new IdentityRepository.Wrapper(jsch.getIdentityRepository(), true); + for(int i = 0; i < values.length; i++){ + String ifile = values[i]; + for(int j = 0; j < global.length; j++){ + if(!ifile.equals(global[j])) + continue; + ifile = null; + break; + } + if(ifile == null) + continue; + Identity identity = + IdentityFile.newInstance(ifile, null, jsch); + ir.add(identity); + } + this.setIdentityRepository(ir); + } + } + + value = config.getValue("ServerAliveInterval"); + if(value != null) { + try { + this.setServerAliveInterval(Integer.parseInt(value)); + } + catch(NumberFormatException e){ + } + } + + value = config.getValue("ConnectTimeout"); + if(value != null) { + try { + setTimeout(Integer.parseInt(value)); + } + catch(NumberFormatException e){ + } + } + + value = config.getValue("MaxAuthTries"); + if(value != null) { + setConfig("MaxAuthTries", value); + } + + value = config.getValue("ClearAllForwardings"); + if(value != null) { + setConfig("ClearAllForwardings", value); + } + + } + + private void applyConfigChannel(ChannelSession channel) throws JSchException { + ConfigRepository configRepository = jsch.getConfigRepository(); + if(configRepository == null){ + return; + } + + ConfigRepository.Config config = + configRepository.getConfig(org_host); + + String value = null; + + value = config.getValue("ForwardAgent"); + if(value != null){ + channel.setAgentForwarding(value.equals("yes")); + } + + value = config.getValue("RequestTTY"); + if(value != null){ + channel.setPty(value.equals("yes")); + } + } + + private void requestPortForwarding() throws JSchException { + + if(getConfig("ClearAllForwardings").equals("yes")) + return; + + ConfigRepository configRepository = jsch.getConfigRepository(); + if(configRepository == null){ + return; + } + + ConfigRepository.Config config = + configRepository.getConfig(org_host); + + String[] values = config.getValues("LocalForward"); + if(values != null){ + for(int i = 0; i < values.length; i++) { + setPortForwardingL(values[i]); + } + } + + values = config.getValues("RemoteForward"); + if(values != null){ + for(int i = 0; i < values.length; i++) { + setPortForwardingR(values[i]); + } + } + } + + private void checkConfig(ConfigRepository.Config config, String key){ + String value = config.getValue(key); + if(value != null) + this.setConfig(key, value); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/SftpATTRS.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/SftpATTRS.java new file mode 100644 index 00000000..b3a86ba0 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/SftpATTRS.java @@ -0,0 +1,294 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/* + uint32 flags + uint64 size present only if flag SSH_FILEXFER_ATTR_SIZE + uint32 uid present only if flag SSH_FILEXFER_ATTR_UIDGID + uint32 gid present only if flag SSH_FILEXFER_ATTR_UIDGID + uint32 permissions present only if flag SSH_FILEXFER_ATTR_PERMISSIONS + uint32 atime present only if flag SSH_FILEXFER_ACMODTIME + uint32 mtime present only if flag SSH_FILEXFER_ACMODTIME + uint32 extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED + string extended_type + string extended_data + ... more extended data (extended_type - extended_data pairs), + so that number of pairs equals extended_count +*/ +public class SftpATTRS { + + static final int S_ISUID = 04000; // set user ID on execution + static final int S_ISGID = 02000; // set group ID on execution + static final int S_ISVTX = 01000; // sticky bit ****** NOT DOCUMENTED ***** + + static final int S_IRUSR = 00400; // read by owner + static final int S_IWUSR = 00200; // write by owner + static final int S_IXUSR = 00100; // execute/search by owner + static final int S_IREAD = 00400; // read by owner + static final int S_IWRITE= 00200; // write by owner + static final int S_IEXEC = 00100; // execute/search by owner + + static final int S_IRGRP = 00040; // read by group + static final int S_IWGRP = 00020; // write by group + static final int S_IXGRP = 00010; // execute/search by group + + static final int S_IROTH = 00004; // read by others + static final int S_IWOTH = 00002; // write by others + static final int S_IXOTH = 00001; // execute/search by others + + private static final int pmask = 0xFFF; + + public String getPermissionsString() { + StringBuffer buf = new StringBuffer(10); + + if(isDir()) buf.append('d'); + else if(isLink()) buf.append('l'); + else buf.append('-'); + + if((permissions & S_IRUSR)!=0) buf.append('r'); + else buf.append('-'); + + if((permissions & S_IWUSR)!=0) buf.append('w'); + else buf.append('-'); + + if((permissions & S_ISUID)!=0) buf.append('s'); + else if ((permissions & S_IXUSR)!=0) buf.append('x'); + else buf.append('-'); + + if((permissions & S_IRGRP)!=0) buf.append('r'); + else buf.append('-'); + + if((permissions & S_IWGRP)!=0) buf.append('w'); + else buf.append('-'); + + if((permissions & S_ISGID)!=0) buf.append('s'); + else if((permissions & S_IXGRP)!=0) buf.append('x'); + else buf.append('-'); + + if((permissions & S_IROTH) != 0) buf.append('r'); + else buf.append('-'); + + if((permissions & S_IWOTH) != 0) buf.append('w'); + else buf.append('-'); + + if((permissions & S_IXOTH) != 0) buf.append('x'); + else buf.append('-'); + return (buf.toString()); + } + + public String getAtimeString(){ + SimpleDateFormat locale=new SimpleDateFormat(); + return (locale.format(new Date(atime))); + } + + public String getMtimeString(){ + Date date= new Date(((long)mtime)*1000); + return (date.toString()); + } + + public static final int SSH_FILEXFER_ATTR_SIZE= 0x00000001; + public static final int SSH_FILEXFER_ATTR_UIDGID= 0x00000002; + public static final int SSH_FILEXFER_ATTR_PERMISSIONS= 0x00000004; + public static final int SSH_FILEXFER_ATTR_ACMODTIME= 0x00000008; + public static final int SSH_FILEXFER_ATTR_EXTENDED= 0x80000000; + + static final int S_IFMT=0xf000; + static final int S_IFIFO=0x1000; + static final int S_IFCHR=0x2000; + static final int S_IFDIR=0x4000; + static final int S_IFBLK=0x6000; + static final int S_IFREG=0x8000; + static final int S_IFLNK=0xa000; + static final int S_IFSOCK=0xc000; + + int flags=0; + long size; + int uid; + int gid; + int permissions; + int atime; + int mtime; + String[] extended=null; + + private SftpATTRS(){ + } + + static SftpATTRS getATTR(Buffer buf){ + SftpATTRS attr=new SftpATTRS(); + attr.flags=buf.getInt(); + if((attr.flags&SSH_FILEXFER_ATTR_SIZE)!=0){ attr.size=buf.getLong(); } + if((attr.flags&SSH_FILEXFER_ATTR_UIDGID)!=0){ + attr.uid=buf.getInt(); attr.gid=buf.getInt(); + } + if((attr.flags&SSH_FILEXFER_ATTR_PERMISSIONS)!=0){ + attr.permissions=buf.getInt(); + } + if((attr.flags&SSH_FILEXFER_ATTR_ACMODTIME)!=0){ + attr.atime=buf.getInt(); + } + if((attr.flags&SSH_FILEXFER_ATTR_ACMODTIME)!=0){ + attr.mtime=buf.getInt(); + } + if((attr.flags&SSH_FILEXFER_ATTR_EXTENDED)!=0){ + int count=buf.getInt(); + if(count>0){ + attr.extended=new String[count*2]; + for(int i=0; i0){ + for(int i=0; i0){ + for(int i=0; i= session.max_auth_tries){ + return false; + } + + // send + // byte SSH_MSG_USERAUTH_REQUEST(50) + // string user name (ISO-10646 UTF-8, as defined in [RFC-2279]) + // string service name (US-ASCII) "ssh-userauth" ? "ssh-connection" + // string "keyboard-interactive" (US-ASCII) + // string language tag (as defined in [RFC-3066]) + // string submethods (ISO-10646 UTF-8) + packet.reset(); + buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST); + buf.putString(_username); + buf.putString(Util.str2byte("ssh-connection")); + //buf.putString("ssh-userauth".getBytes()); + buf.putString(Util.str2byte("keyboard-interactive")); + buf.putString(Util.empty); + buf.putString(Util.empty); + session.write(packet); + + boolean firsttime=true; + loop: + while(true){ + buf=session.read(buf); + int command=buf.getCommand()&0xff; + + if(command==SSH_MSG_USERAUTH_SUCCESS){ + return true; + } + if(command==SSH_MSG_USERAUTH_BANNER){ + buf.getInt(); buf.getByte(); buf.getByte(); + byte[] _message=buf.getString(); + byte[] lang=buf.getString(); + String message=Util.byte2str(_message); + if(userinfo!=null){ + userinfo.showMessage(message); + } + continue loop; + } + if(command==SSH_MSG_USERAUTH_FAILURE){ + buf.getInt(); buf.getByte(); buf.getByte(); + byte[] foo=buf.getString(); + int partial_success=buf.getByte(); +// System.err.println(new String(foo)+ +// " partial_success:"+(partial_success!=0)); + + if(partial_success!=0){ + throw new JSchPartialAuthException(Util.byte2str(foo)); + } + + if(firsttime){ + return false; + //throw new JSchException("USERAUTH KI is not supported"); + //cancel=true; // ?? + } + session.auth_failures++; + break; + } + if(command==SSH_MSG_USERAUTH_INFO_REQUEST){ + firsttime=false; + buf.getInt(); buf.getByte(); buf.getByte(); + String name=Util.byte2str(buf.getString()); + String instruction=Util.byte2str(buf.getString()); + String languate_tag=Util.byte2str(buf.getString()); + int num=buf.getInt(); + String[] prompt=new String[num]; + boolean[] echo=new boolean[num]; + for(int i=0; i= 0){ + response=new byte[1][]; + response[0]=password; + password=null; + } + else if(num>0 + ||(name.length()>0 || instruction.length()>0) + ){ + if(userinfo!=null){ + UIKeyboardInteractive kbi=(UIKeyboardInteractive)userinfo; + String[] _response=kbi.promptKeyboardInteractive(dest, + name, + instruction, + prompt, + echo); + if(_response!=null){ + response=new byte[_response.length][]; + for(int i=0; i<_response.length; i++){ + response[i]=Util.str2byte(_response[i]); + } + } + } + } + + // byte SSH_MSG_USERAUTH_INFO_RESPONSE(61) + // int num-responses + // string response[1] (ISO-10646 UTF-8) + // ... + // string response[num-responses] (ISO-10646 UTF-8) + packet.reset(); + buf.putByte((byte)SSH_MSG_USERAUTH_INFO_RESPONSE); + if(num>0 && + (response==null || // cancel + num!=response.length)){ + + if(response==null){ + // working around the bug in OpenSSH ;-< + buf.putInt(num); + for(int i=0; i= session.max_auth_tries){ + return false; + } + + if(password==null){ + if(userinfo==null){ + //throw new JSchException("USERAUTH fail"); + return false; + } + if(!userinfo.promptPassword("Password for "+dest)){ + throw new JSchAuthCancelException("password"); + //break; + } + + String _password=userinfo.getPassword(); + if(_password==null){ + throw new JSchAuthCancelException("password"); + //break; + } + password=Util.str2byte(_password); + } + + byte[] _username=null; + _username=Util.str2byte(username); + + // send + // byte SSH_MSG_USERAUTH_REQUEST(50) + // string user name + // string service name ("ssh-connection") + // string "password" + // boolen FALSE + // string plaintext password (ISO-10646 UTF-8) + packet.reset(); + buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST); + buf.putString(_username); + buf.putString(Util.str2byte("ssh-connection")); + buf.putString(Util.str2byte("password")); + buf.putByte((byte)0); + buf.putString(password); + session.write(packet); + + loop: + while(true){ + buf=session.read(buf); + int command=buf.getCommand()&0xff; + + if(command==SSH_MSG_USERAUTH_SUCCESS){ + return true; + } + if(command==SSH_MSG_USERAUTH_BANNER){ + buf.getInt(); buf.getByte(); buf.getByte(); + byte[] _message=buf.getString(); + byte[] lang=buf.getString(); + String message=Util.byte2str(_message); + if(userinfo!=null){ + userinfo.showMessage(message); + } + continue loop; + } + if(command==SSH_MSG_USERAUTH_PASSWD_CHANGEREQ){ + buf.getInt(); buf.getByte(); buf.getByte(); + byte[] instruction=buf.getString(); + byte[] tag=buf.getString(); + if(userinfo==null || + !(userinfo instanceof UIKeyboardInteractive)){ + if(userinfo!=null){ + userinfo.showMessage("Password must be changed."); + } + return false; + } + + UIKeyboardInteractive kbi=(UIKeyboardInteractive)userinfo; + String[] response; + String name="Password Change Required"; + String[] prompt={"New Password: "}; + boolean[] echo={false}; + response=kbi.promptKeyboardInteractive(dest, + name, + Util.byte2str(instruction), + prompt, + echo); + if(response==null){ + throw new JSchAuthCancelException("password"); + } + + byte[] newpassword=Util.str2byte(response[0]); + + // send + // byte SSH_MSG_USERAUTH_REQUEST(50) + // string user name + // string service name ("ssh-connection") + // string "password" + // boolen TRUE + // string plaintext old password (ISO-10646 UTF-8) + // string plaintext new password (ISO-10646 UTF-8) + packet.reset(); + buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST); + buf.putString(_username); + buf.putString(Util.str2byte("ssh-connection")); + buf.putString(Util.str2byte("password")); + buf.putByte((byte)1); + buf.putString(password); + buf.putString(newpassword); + Util.bzero(newpassword); + response=null; + session.write(packet); + continue loop; + } + if(command==SSH_MSG_USERAUTH_FAILURE){ + buf.getInt(); buf.getByte(); buf.getByte(); + byte[] foo=buf.getString(); + int partial_success=buf.getByte(); + //System.err.println(new String(foo)+ + // " partial_success:"+(partial_success!=0)); + if(partial_success!=0){ + throw new JSchPartialAuthException(Util.byte2str(foo)); + } + session.auth_failures++; + break; + } + else{ + //System.err.println("USERAUTH fail ("+buf.getCommand()+")"); +// throw new JSchException("USERAUTH fail ("+buf.getCommand()+")"); + return false; + } + } + + if(password!=null){ + Util.bzero(password); + password=null; + } + + } + + } + finally{ + if(password!=null){ + Util.bzero(password); + password=null; + } + } + + //throw new JSchException("USERAUTH fail"); + //return false; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/UserAuthPublicKey.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/UserAuthPublicKey.java new file mode 100644 index 00000000..a4d38be5 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/UserAuthPublicKey.java @@ -0,0 +1,231 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +import java.util.Vector; + +class UserAuthPublicKey extends UserAuth{ + + public boolean start(Session session) throws Exception{ + super.start(session); + + Vector identities=session.getIdentityRepository().getIdentities(); + + byte[] passphrase=null; + byte[] _username=null; + + int command; + + synchronized(identities){ + if(identities.size()<=0){ + return false; + } + + _username=Util.str2byte(username); + + for(int i=0; i= session.max_auth_tries){ + return false; + } + + Identity identity=(Identity)(identities.elementAt(i)); + byte[] pubkeyblob=identity.getPublicKeyBlob(); + + if(pubkeyblob!=null){ + // send + // byte SSH_MSG_USERAUTH_REQUEST(50) + // string user name + // string service name ("ssh-connection") + // string "publickey" + // boolen FALSE + // string plaintext password (ISO-10646 UTF-8) + packet.reset(); + buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST); + buf.putString(_username); + buf.putString(Util.str2byte("ssh-connection")); + buf.putString(Util.str2byte("publickey")); + buf.putByte((byte)0); + buf.putString(Util.str2byte(identity.getAlgName())); + buf.putString(pubkeyblob); + session.write(packet); + + loop1: + while(true){ + buf=session.read(buf); + command=buf.getCommand()&0xff; + + if(command==SSH_MSG_USERAUTH_PK_OK){ + break; + } + else if(command==SSH_MSG_USERAUTH_FAILURE){ + break; + } + else if(command==SSH_MSG_USERAUTH_BANNER){ + buf.getInt(); buf.getByte(); buf.getByte(); + byte[] _message=buf.getString(); + byte[] lang=buf.getString(); + String message=Util.byte2str(_message); + if(userinfo!=null){ + userinfo.showMessage(message); + } + continue loop1; + } + else{ + //System.err.println("USERAUTH fail ("+command+")"); + //throw new JSchException("USERAUTH fail ("+command+")"); + break; + } + } + + if(command!=SSH_MSG_USERAUTH_PK_OK){ + continue; + } + } + +//System.err.println("UserAuthPublicKey: identity.isEncrypted()="+identity.isEncrypted()); + + int count=5; + while(true){ + if((identity.isEncrypted() && passphrase==null)){ + if(userinfo==null) throw new JSchException("USERAUTH fail"); + if(identity.isEncrypted() && + !userinfo.promptPassphrase("Passphrase for "+identity.getName())){ + throw new JSchAuthCancelException("publickey"); + //throw new JSchException("USERAUTH cancel"); + //break; + } + String _passphrase=userinfo.getPassphrase(); + if(_passphrase!=null){ + passphrase=Util.str2byte(_passphrase); + } + } + + if(!identity.isEncrypted() || passphrase!=null){ + if(identity.setPassphrase(passphrase)){ + if(passphrase!=null && + (session.getIdentityRepository() instanceof IdentityRepository.Wrapper)){ + ((IdentityRepository.Wrapper)session.getIdentityRepository()).check(); + } + break; + } + } + Util.bzero(passphrase); + passphrase=null; + count--; + if(count==0)break; + } + + Util.bzero(passphrase); + passphrase=null; +//System.err.println("UserAuthPublicKey: identity.isEncrypted()="+identity.isEncrypted()); + + if(identity.isEncrypted()) continue; + if(pubkeyblob==null) pubkeyblob=identity.getPublicKeyBlob(); + +//System.err.println("UserAuthPublicKey: pubkeyblob="+pubkeyblob); + + if(pubkeyblob==null) continue; + + // send + // byte SSH_MSG_USERAUTH_REQUEST(50) + // string user name + // string service name ("ssh-connection") + // string "publickey" + // boolen TRUE + // string plaintext password (ISO-10646 UTF-8) + packet.reset(); + buf.putByte((byte)SSH_MSG_USERAUTH_REQUEST); + buf.putString(_username); + buf.putString(Util.str2byte("ssh-connection")); + buf.putString(Util.str2byte("publickey")); + buf.putByte((byte)1); + buf.putString(Util.str2byte(identity.getAlgName())); + buf.putString(pubkeyblob); + +// byte[] tmp=new byte[buf.index-5]; +// System.arraycopy(buf.buffer, 5, tmp, 0, tmp.length); +// buf.putString(signature); + + byte[] sid=session.getSessionId(); + int sidlen=sid.length; + byte[] tmp=new byte[4+sidlen+buf.index-5]; + tmp[0]=(byte)(sidlen>>>24); + tmp[1]=(byte)(sidlen>>>16); + tmp[2]=(byte)(sidlen>>>8); + tmp[3]=(byte)(sidlen); + System.arraycopy(sid, 0, tmp, 4, sidlen); + System.arraycopy(buf.buffer, 5, tmp, 4+sidlen, buf.index-5); + byte[] signature=identity.getSignature(tmp); + if(signature==null){ // for example, too long key length. + break; + } + buf.putString(signature); + session.write(packet); + + loop2: + while(true){ + buf=session.read(buf); + command=buf.getCommand()&0xff; + + if(command==SSH_MSG_USERAUTH_SUCCESS){ + return true; + } + else if(command==SSH_MSG_USERAUTH_BANNER){ + buf.getInt(); buf.getByte(); buf.getByte(); + byte[] _message=buf.getString(); + byte[] lang=buf.getString(); + String message=Util.byte2str(_message); + if(userinfo!=null){ + userinfo.showMessage(message); + } + continue loop2; + } + else if(command==SSH_MSG_USERAUTH_FAILURE){ + buf.getInt(); buf.getByte(); buf.getByte(); + byte[] foo=buf.getString(); + int partial_success=buf.getByte(); + //System.err.println(new String(foo)+ + // " partial_success:"+(partial_success!=0)); + if(partial_success!=0){ + throw new JSchPartialAuthException(Util.byte2str(foo)); + } + session.auth_failures++; + break; + } + //System.err.println("USERAUTH fail ("+command+")"); + //throw new JSchException("USERAUTH fail ("+command+")"); + break; + } + } + } + return false; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/UserInfo.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/UserInfo.java new file mode 100644 index 00000000..22552ede --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/UserInfo.java @@ -0,0 +1,39 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; + +public interface UserInfo{ + String getPassphrase(); + String getPassword(); + boolean promptPassword(String message); + boolean promptPassphrase(String message); + boolean promptYesNo(String message); + void showMessage(String message); +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/Util.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/Util.java new file mode 100644 index 00000000..6a5354b0 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/Util.java @@ -0,0 +1,510 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch; +import java.net.Socket; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +class Util{ + + private static final byte[] b64 =Util.str2byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="); + private static byte val(byte foo){ + if(foo == '=') return 0; + for(int j=0; j>>4)); + if(buf[i+2]==(byte)'='){ j++; break;} + foo[j+1]=(byte)(((val(buf[i+1])&0x0f)<<4)|((val(buf[i+2])&0x3c)>>>2)); + if(buf[i+3]==(byte)'='){ j+=2; break;} + foo[j+2]=(byte)(((val(buf[i+2])&0x03)<<6)|(val(buf[i+3])&0x3f)); + j+=3; + } + byte[] bar=new byte[j]; + System.arraycopy(foo, 0, bar, 0, j); + return bar; + } + static byte[] toBase64(byte[] buf, int start, int length){ + + byte[] tmp=new byte[length*2]; + int i,j,k; + + int foo=(length/3)*3+start; + i=0; + for(j=start; j>>2)&0x3f; + tmp[i++]=b64[k]; + k=(buf[j]&0x03)<<4|(buf[j+1]>>>4)&0x0f; + tmp[i++]=b64[k]; + k=(buf[j+1]&0x0f)<<2|(buf[j+2]>>>6)&0x03; + tmp[i++]=b64[k]; + k=buf[j+2]&0x3f; + tmp[i++]=b64[k]; + } + + foo=(start+length)-foo; + if(foo==1){ + k=(buf[j]>>>2)&0x3f; + tmp[i++]=b64[k]; + k=((buf[j]&0x03)<<4)&0x3f; + tmp[i++]=b64[k]; + tmp[i++]=(byte)'='; + tmp[i++]=(byte)'='; + } + else if(foo==2){ + k=(buf[j]>>>2)&0x3f; + tmp[i++]=b64[k]; + k=(buf[j]&0x03)<<4|(buf[j+1]>>>4)&0x0f; + tmp[i++]=b64[k]; + k=((buf[j+1]&0x0f)<<2)&0x3f; + tmp[i++]=b64[k]; + tmp[i++]=(byte)'='; + } + byte[] bar=new byte[i]; + System.arraycopy(tmp, 0, bar, 0, i); + return bar; + +// return sun.misc.BASE64Encoder().encode(buf); + } + + static String[] split(String foo, String split){ + if(foo==null) + return null; + byte[] buf=Util.str2byte(foo); + java.util.Vector bar=new java.util.Vector(); + int start=0; + int index; + while(true){ + index=foo.indexOf(split, start); + if(index>=0){ + bar.addElement(Util.byte2str(buf, start, index-start)); + start=index+1; + continue; + } + bar.addElement(Util.byte2str(buf, start, buf.length-start)); + break; + } + String[] result=new String[bar.size()]; + for(int i=0; i0 && name[0]=='.'){ + if(pattern.length>0 && pattern[0]=='.'){ + if(pattern.length==2 && pattern[1]=='*') return true; + return glob(pattern, pattern_index+1, name, name_index+1); + } + return false; + } + return glob(pattern, pattern_index, name, name_index); + } + static private boolean glob(byte[] pattern, int pattern_index, + byte[] name, int name_index){ + //System.err.println("glob: "+new String(pattern)+", "+pattern_index+" "+new String(name)+", "+name_index); + + int patternlen=pattern.length; + if(patternlen==0) + return false; + + int namelen=name.length; + int i=pattern_index; + int j=name_index; + + while(i>>4)&0xf]); + sb.append(chars[(bar)&0xf]); + if(i+1>>8); + bar[j++]=(byte)foo[i]; + } + } + return bar; + } + */ + static void bzero(byte[] foo){ + if(foo==null) + return; + for(int i=0; iivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + + try{ + SecretKeySpec keyspec=new SecretKeySpec(key, "AES"); + cipher=javax.crypto.Cipher.getInstance("AES/CBC/"+pad); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + keyspec, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } + + public boolean isCBC(){return true; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES128CTR.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES128CTR.java new file mode 100644 index 00000000..470a896b --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES128CTR.java @@ -0,0 +1,73 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2008-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.spec.*; + +public class AES128CTR implements Cipher{ + private static final int ivsize=16; + private static final int bsize=16; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + byte[] tmp; + if(iv.length>ivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + + try{ + SecretKeySpec keyspec=new SecretKeySpec(key, "AES"); + cipher=javax.crypto.Cipher.getInstance("AES/CTR/"+pad); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + keyspec, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } + + public boolean isCBC(){return false; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES192CBC.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES192CBC.java new file mode 100644 index 00000000..615d4943 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES192CBC.java @@ -0,0 +1,71 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2005-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.spec.*; + +public class AES192CBC implements Cipher{ + private static final int ivsize=16; + private static final int bsize=24; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + byte[] tmp; + if(iv.length>ivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + SecretKeySpec keyspec=new SecretKeySpec(key, "AES"); + cipher=javax.crypto.Cipher.getInstance("AES/CBC/"+pad); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + keyspec, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } + public boolean isCBC(){return true; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES192CTR.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES192CTR.java new file mode 100644 index 00000000..74090bf9 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES192CTR.java @@ -0,0 +1,71 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2008-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.spec.*; + +public class AES192CTR implements Cipher{ + private static final int ivsize=16; + private static final int bsize=24; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + byte[] tmp; + if(iv.length>ivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + SecretKeySpec keyspec=new SecretKeySpec(key, "AES"); + cipher=javax.crypto.Cipher.getInstance("AES/CTR/"+pad); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + keyspec, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } + public boolean isCBC(){return false; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES256CBC.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES256CBC.java new file mode 100644 index 00000000..9018a204 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES256CBC.java @@ -0,0 +1,71 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2005-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.spec.*; + +public class AES256CBC implements Cipher{ + private static final int ivsize=16; + private static final int bsize=32; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + byte[] tmp; + if(iv.length>ivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + SecretKeySpec keyspec=new SecretKeySpec(key, "AES"); + cipher=javax.crypto.Cipher.getInstance("AES/CBC/"+pad); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + keyspec, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } + public boolean isCBC(){return true; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES256CTR.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES256CTR.java new file mode 100644 index 00000000..b7472e96 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/AES256CTR.java @@ -0,0 +1,71 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2008-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.spec.*; + +public class AES256CTR implements Cipher{ + private static final int ivsize=16; + private static final int bsize=32; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + byte[] tmp; + if(iv.length>ivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + SecretKeySpec keyspec=new SecretKeySpec(key, "AES"); + cipher=javax.crypto.Cipher.getInstance("AES/CTR/"+pad); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + keyspec, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } + public boolean isCBC(){return false; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/ARCFOUR.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/ARCFOUR.java new file mode 100644 index 00000000..9f6537c3 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/ARCFOUR.java @@ -0,0 +1,68 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2008-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.*; +import javax.crypto.spec.*; + +public class ARCFOUR implements Cipher{ + private static final int ivsize=8; + private static final int bsize=16; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + byte[] tmp; + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + + try{ + cipher=javax.crypto.Cipher.getInstance("RC4"); + SecretKeySpec _key = new SecretKeySpec(key, "RC4"); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + _key); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } + public boolean isCBC(){return false; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/ARCFOUR128.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/ARCFOUR128.java new file mode 100644 index 00000000..d8b46137 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/ARCFOUR128.java @@ -0,0 +1,71 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2008-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.*; +import javax.crypto.spec.*; + +public class ARCFOUR128 implements Cipher{ + private static final int ivsize=8; + private static final int bsize=16; + private static final int skip=1536; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + byte[] tmp; + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + cipher=javax.crypto.Cipher.getInstance("RC4"); + SecretKeySpec _key = new SecretKeySpec(key, "RC4"); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + _key); + byte[] foo=new byte[1]; + for(int i=0; ibsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + cipher=javax.crypto.Cipher.getInstance("RC4"); + SecretKeySpec _key = new SecretKeySpec(key, "RC4"); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + _key); + byte[] foo=new byte[1]; + for(int i=0; iivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + try{ + SecretKeySpec skeySpec = new SecretKeySpec(key, "Blowfish"); + cipher=javax.crypto.Cipher.getInstance("Blowfish/CBC/"+pad); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + skeySpec, new IvParameterSpec(iv)); + } + catch(Exception e){ + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } + public boolean isCBC(){return true; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/DH.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/DH.java new file mode 100644 index 00000000..da03c1de --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/DH.java @@ -0,0 +1,91 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import java.math.BigInteger; +import java.security.*; +import javax.crypto.*; +import javax.crypto.spec.*; + +public class DH implements com.jcraft.jsch.DH{ + BigInteger p; + BigInteger g; + BigInteger e; // my public key + byte[] e_array; + BigInteger f; // your public key + BigInteger K; // shared secret key + byte[] K_array; + + private KeyPairGenerator myKpairGen; + private KeyAgreement myKeyAgree; + public void init() throws Exception{ + myKpairGen=KeyPairGenerator.getInstance("DH"); +// myKpairGen=KeyPairGenerator.getInstance("DiffieHellman"); + myKeyAgree=KeyAgreement.getInstance("DH"); +// myKeyAgree=KeyAgreement.getInstance("DiffieHellman"); + } + public byte[] getE() throws Exception{ + if(e==null){ + DHParameterSpec dhSkipParamSpec=new DHParameterSpec(p, g); + myKpairGen.initialize(dhSkipParamSpec); + KeyPair myKpair=myKpairGen.generateKeyPair(); + myKeyAgree.init(myKpair.getPrivate()); +// BigInteger x=((javax.crypto.interfaces.DHPrivateKey)(myKpair.getPrivate())).getX(); + byte[] myPubKeyEnc=myKpair.getPublic().getEncoded(); + e=((javax.crypto.interfaces.DHPublicKey)(myKpair.getPublic())).getY(); + e_array=e.toByteArray(); + } + return e_array; + } + public byte[] getK() throws Exception{ + if(K==null){ + KeyFactory myKeyFac=KeyFactory.getInstance("DH"); + DHPublicKeySpec keySpec=new DHPublicKeySpec(f, p, g); + PublicKey yourPubKey=myKeyFac.generatePublic(keySpec); + myKeyAgree.doPhase(yourPubKey, true); + byte[] mySharedSecret=myKeyAgree.generateSecret(); + K=new BigInteger(mySharedSecret); + K_array=K.toByteArray(); + +//System.err.println("K.signum(): "+K.signum()+ +// " "+Integer.toHexString(mySharedSecret[0]&0xff)+ +// " "+Integer.toHexString(K_array[0]&0xff)); + + K_array=mySharedSecret; + } + return K_array; + } + public void setP(byte[] p){ setP(new BigInteger(p)); } + public void setG(byte[] g){ setG(new BigInteger(g)); } + public void setF(byte[] f){ setF(new BigInteger(f)); } + void setP(BigInteger p){this.p=p;} + void setG(BigInteger g){this.g=g;} + void setF(BigInteger f){this.f=f;} +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMAC.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMAC.java new file mode 100644 index 00000000..27439b2b --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMAC.java @@ -0,0 +1,82 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2012-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.MAC; +import javax.crypto.*; +import javax.crypto.spec.*; + +abstract class HMAC implements MAC { + protected String name; + protected int bsize; + protected String algorithm; + private Mac mac; + + public int getBlockSize() { + return bsize; + }; + + public void init(byte[] key) throws Exception { + if(key.length>bsize){ + byte[] tmp = new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, bsize); + key = tmp; + } + SecretKeySpec skey = new SecretKeySpec(key, algorithm); + mac = Mac.getInstance(algorithm); + mac.init(skey); + } + + private final byte[] tmp = new byte[4]; + public void update(int i){ + tmp[0] = (byte)(i>>>24); + tmp[1] = (byte)(i>>>16); + tmp[2] = (byte)(i>>>8); + tmp[3] = (byte)i; + update(tmp, 0, 4); + } + + public void update(byte foo[], int s, int l){ + mac.update(foo, s, l); + } + + public void doFinal(byte[] buf, int offset){ + try{ + mac.doFinal(buf, offset); + } + catch(ShortBufferException e){ + System.err.println(e); + } + } + + public String getName(){ + return name; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACMD5.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACMD5.java new file mode 100644 index 00000000..d4e1b697 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACMD5.java @@ -0,0 +1,42 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.MAC; +import javax.crypto.*; +import javax.crypto.spec.*; + +public class HMACMD5 extends HMAC { + public HMACMD5(){ + name = "hmac-md5"; + bsize = 16; + algorithm = "HmacMD5"; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACMD596.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACMD596.java new file mode 100644 index 00000000..4f7262ae --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACMD596.java @@ -0,0 +1,46 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +public class HMACMD596 extends HMACMD5 { + public HMACMD596(){ + name="hmac-md5-96"; + } + + public int getBlockSize(){ + return 12; + }; + + private final byte[] _buf16 = new byte[16]; + public void doFinal(byte[] buf, int offset){ + super.doFinal(_buf16, 0); + System.arraycopy(_buf16, 0, buf, offset, 12); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA1.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA1.java new file mode 100644 index 00000000..805cebe5 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA1.java @@ -0,0 +1,38 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +public class HMACSHA1 extends HMAC { + public HMACSHA1(){ + name = "hmac-sha1"; + bsize = 20; + algorithm = "HmacSHA1"; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA196.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA196.java new file mode 100644 index 00000000..b897c314 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA196.java @@ -0,0 +1,47 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +public class HMACSHA196 extends HMACSHA1 { + + public HMACSHA196(){ + name = "hmac-sha1-96"; + } + + public int getBlockSize(){ + return 12; + }; + + private final byte[] _buf20 = new byte[20]; + public void doFinal(byte[] buf, int offset){ + super.doFinal(_buf20, 0); + System.arraycopy(_buf20, 0, buf, offset, 12); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA256.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA256.java new file mode 100644 index 00000000..a2d86137 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA256.java @@ -0,0 +1,38 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2012-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +public class HMACSHA256 extends HMAC { + public HMACSHA256(){ + name = "hmac-sha2-256"; + bsize = 32; + algorithm = "HmacSHA256"; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA512.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA512.java new file mode 100644 index 00000000..0876ad18 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/HMACSHA512.java @@ -0,0 +1,38 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2012-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +public class HMACSHA512 extends HMAC { + public HMACSHA512(){ + name = "hmac-sha2-512"; + bsize = 64; + algorithm = "HmacSHA512"; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/KeyPairGenDSA.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/KeyPairGenDSA.java new file mode 100644 index 00000000..67ad54eb --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/KeyPairGenDSA.java @@ -0,0 +1,62 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import java.security.*; +import java.security.interfaces.*; + +public class KeyPairGenDSA implements com.jcraft.jsch.KeyPairGenDSA{ + byte[] x; // private + byte[] y; // public + byte[] p; + byte[] q; + byte[] g; + + public void init(int key_size) throws Exception{ + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA"); + keyGen.initialize(key_size, new SecureRandom()); + KeyPair pair = keyGen.generateKeyPair(); + PublicKey pubKey=pair.getPublic(); + PrivateKey prvKey=pair.getPrivate(); + + x=((DSAPrivateKey)prvKey).getX().toByteArray(); + y=((DSAPublicKey)pubKey).getY().toByteArray(); + + DSAParams params=((DSAKey)prvKey).getParams(); + p=params.getP().toByteArray(); + q=params.getQ().toByteArray(); + g=params.getG().toByteArray(); + } + public byte[] getX(){return x;} + public byte[] getY(){return y;} + public byte[] getP(){return p;} + public byte[] getQ(){return q;} + public byte[] getG(){return g;} +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/KeyPairGenRSA.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/KeyPairGenRSA.java new file mode 100644 index 00000000..543f0f79 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/KeyPairGenRSA.java @@ -0,0 +1,72 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import java.security.*; +import java.security.interfaces.*; + +public class KeyPairGenRSA implements com.jcraft.jsch.KeyPairGenRSA{ + byte[] d; // private + byte[] e; // public + byte[] n; + + byte[] c; // coefficient + byte[] ep; // exponent p + byte[] eq; // exponent q + byte[] p; // prime p + byte[] q; // prime q + + public void init(int key_size) throws Exception{ + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(key_size, new SecureRandom()); + KeyPair pair = keyGen.generateKeyPair(); + + PublicKey pubKey=pair.getPublic(); + PrivateKey prvKey=pair.getPrivate(); + + d=((RSAPrivateKey)prvKey).getPrivateExponent().toByteArray(); + e=((RSAPublicKey)pubKey).getPublicExponent().toByteArray(); + n=((RSAPrivateKey)prvKey).getModulus().toByteArray(); + + c=((RSAPrivateCrtKey)prvKey).getCrtCoefficient().toByteArray(); + ep=((RSAPrivateCrtKey)prvKey).getPrimeExponentP().toByteArray(); + eq=((RSAPrivateCrtKey)prvKey).getPrimeExponentQ().toByteArray(); + p=((RSAPrivateCrtKey)prvKey).getPrimeP().toByteArray(); + q=((RSAPrivateCrtKey)prvKey).getPrimeQ().toByteArray(); + } + public byte[] getD(){return d;} + public byte[] getE(){return e;} + public byte[] getN(){return n;} + public byte[] getC(){return c;} + public byte[] getEP(){return ep;} + public byte[] getEQ(){return eq;} + public byte[] getP(){return p;} + public byte[] getQ(){return q;} +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/MD5.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/MD5.java new file mode 100644 index 00000000..538ae340 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/MD5.java @@ -0,0 +1,51 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.HASH; + +import java.security.*; + +public class MD5 implements HASH{ + MessageDigest md; + public int getBlockSize(){return 16;} + public void init() throws Exception{ + try{ md=MessageDigest.getInstance("MD5"); } + catch(Exception e){ + System.err.println(e); + } + } + public void update(byte[] foo, int start, int len) throws Exception{ + md.update(foo, start, len); + } + public byte[] digest() throws Exception{ + return md.digest(); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/Random.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/Random.java new file mode 100644 index 00000000..8668a01a --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/Random.java @@ -0,0 +1,81 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import java.security.SecureRandom; + +public class Random implements com.jcraft.jsch.Random{ + private byte[] tmp=new byte[16]; + private SecureRandom random=null; + public Random(){ + + // We hope that 'new SecureRandom()' will use NativePRNG algorithm + // on Sun's Java5 for GNU/Linux and Solaris. + // It seems NativePRNG refers to /dev/urandom and it must not be blocked, + // but NativePRNG is slower than SHA1PRNG ;-< + // TIPS: By adding option '-Djava.security.egd=file:/dev/./urandom' + // SHA1PRNG will be used instead of NativePRNG. + // On MacOSX, 'new SecureRandom()' will use NativePRNG algorithm and + // it is also slower than SHA1PRNG. + // On Windows, 'new SecureRandom()' will use SHA1PRNG algorithm. + random=new SecureRandom(); + + /* + try{ + random=SecureRandom.getInstance("SHA1PRNG"); + return; + } + catch(java.security.NoSuchAlgorithmException e){ + // System.err.println(e); + } + + // The following code is for IBM's JCE + try{ + random=SecureRandom.getInstance("IBMSecureRandom"); + return; + } + catch(java.security.NoSuchAlgorithmException ee){ + //System.err.println(ee); + } + */ + } + public void fill(byte[] foo, int start, int len){ + /* + // This case will not become true in our usage. + if(start==0 && foo.length==len){ + random.nextBytes(foo); + return; + } + */ + if(len>tmp.length){ tmp=new byte[len]; } + random.nextBytes(tmp); + System.arraycopy(tmp, 0, foo, start, len); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/SHA1.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/SHA1.java new file mode 100644 index 00000000..08fce4b0 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/SHA1.java @@ -0,0 +1,51 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.HASH; + +import java.security.*; + +public class SHA1 implements HASH{ + MessageDigest md; + public int getBlockSize(){return 20;} + public void init() throws Exception{ + try{ md=MessageDigest.getInstance("SHA-1"); } + catch(Exception e){ + System.err.println(e); + } + } + public void update(byte[] foo, int start, int len) throws Exception{ + md.update(foo, start, len); + } + public byte[] digest() throws Exception{ + return md.digest(); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/SHA256.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/SHA256.java new file mode 100644 index 00000000..28266b06 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/SHA256.java @@ -0,0 +1,51 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.HASH; + +import java.security.*; + +public class SHA256 implements HASH { + MessageDigest md; + public int getBlockSize(){return 32;} + public void init() throws Exception { + try{ md=MessageDigest.getInstance("SHA-256"); } + catch(Exception e){ + System.err.println(e); + } + } + public void update(byte[] foo, int start, int len) throws Exception { + md.update(foo, start, len); + } + public byte[] digest() throws Exception { + return md.digest(); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/SignatureDSA.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/SignatureDSA.java new file mode 100644 index 00000000..262dfc5e --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/SignatureDSA.java @@ -0,0 +1,147 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import java.math.BigInteger; +import java.security.*; +import java.security.spec.*; + +public class SignatureDSA implements com.jcraft.jsch.SignatureDSA{ + + java.security.Signature signature; + KeyFactory keyFactory; + + public void init() throws Exception{ + signature=java.security.Signature.getInstance("SHA1withDSA"); + keyFactory=KeyFactory.getInstance("DSA"); + } + public void setPubKey(byte[] y, byte[] p, byte[] q, byte[] g) throws Exception{ + DSAPublicKeySpec dsaPubKeySpec = + new DSAPublicKeySpec(new BigInteger(y), + new BigInteger(p), + new BigInteger(q), + new BigInteger(g)); + PublicKey pubKey=keyFactory.generatePublic(dsaPubKeySpec); + signature.initVerify(pubKey); + } + public void setPrvKey(byte[] x, byte[] p, byte[] q, byte[] g) throws Exception{ + DSAPrivateKeySpec dsaPrivKeySpec = + new DSAPrivateKeySpec(new BigInteger(x), + new BigInteger(p), + new BigInteger(q), + new BigInteger(g)); + PrivateKey prvKey = keyFactory.generatePrivate(dsaPrivKeySpec); + signature.initSign(prvKey); + } + public byte[] sign() throws Exception{ + byte[] sig=signature.sign(); +/* +System.err.print("sign["+sig.length+"] "); +for(int i=0; iivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + + try{ + cipher=javax.crypto.Cipher.getInstance("DESede/CBC/"+pad); +/* + // The following code does not work on IBM's JDK 1.4.1 + SecretKeySpec skeySpec = new SecretKeySpec(key, "DESede"); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + skeySpec, new IvParameterSpec(iv)); +*/ + DESedeKeySpec keyspec=new DESedeKeySpec(key); + SecretKeyFactory keyfactory=SecretKeyFactory.getInstance("DESede"); + SecretKey _key=keyfactory.generateSecret(keyspec); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + _key, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } + public boolean isCBC(){return true; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/TripleDESCTR.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/TripleDESCTR.java new file mode 100644 index 00000000..899f03bd --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jce/TripleDESCTR.java @@ -0,0 +1,84 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2008-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jce; + +import com.jcraft.jsch.Cipher; +import javax.crypto.*; +import javax.crypto.spec.*; + +public class TripleDESCTR implements Cipher{ + private static final int ivsize=8; + private static final int bsize=24; + private javax.crypto.Cipher cipher; + public int getIVSize(){return ivsize;} + public int getBlockSize(){return bsize;} + public void init(int mode, byte[] key, byte[] iv) throws Exception{ + String pad="NoPadding"; + //if(padding) pad="PKCS5Padding"; + byte[] tmp; + if(iv.length>ivsize){ + tmp=new byte[ivsize]; + System.arraycopy(iv, 0, tmp, 0, tmp.length); + iv=tmp; + } + if(key.length>bsize){ + tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, tmp.length); + key=tmp; + } + + try{ + cipher=javax.crypto.Cipher.getInstance("DESede/CTR/"+pad); +/* + // The following code does not work on IBM's JDK 1.4.1 + SecretKeySpec skeySpec = new SecretKeySpec(key, "DESede"); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + skeySpec, new IvParameterSpec(iv)); +*/ + DESedeKeySpec keyspec=new DESedeKeySpec(key); + SecretKeyFactory keyfactory=SecretKeyFactory.getInstance("DESede"); + SecretKey _key=keyfactory.generateSecret(keyspec); + cipher.init((mode==ENCRYPT_MODE? + javax.crypto.Cipher.ENCRYPT_MODE: + javax.crypto.Cipher.DECRYPT_MODE), + _key, new IvParameterSpec(iv)); + } + catch(Exception e){ + cipher=null; + throw e; + } + } + public void update(byte[] foo, int s1, int len, byte[] bar, int s2) throws Exception{ + cipher.update(foo, s1, len, bar, s2); + } + public boolean isCBC(){return false; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/Compression.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/Compression.java new file mode 100644 index 00000000..dddcaed4 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/Compression.java @@ -0,0 +1,140 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2002-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jcraft; +import com.jcraft.jzlib.*; +import com.jcraft.jsch.*; + +public class Compression implements com.jcraft.jsch.Compression { + static private final int BUF_SIZE=4096; + private final int buffer_margin=32+20; // AES256 + HMACSHA1 + private int type; + private ZStream stream; + private byte[] tmpbuf=new byte[BUF_SIZE]; + + public Compression(){ + stream=new ZStream(); + } + + public void init(int type, int level){ + if(type==DEFLATER){ + stream.deflateInit(level); + this.type=DEFLATER; + } + else if(type==INFLATER){ + stream.inflateInit(); + inflated_buf=new byte[BUF_SIZE]; + this.type=INFLATER; + } + } + + private byte[] inflated_buf; + + public byte[] compress(byte[] buf, int start, int[] len){ + stream.next_in=buf; + stream.next_in_index=start; + stream.avail_in=len[0]-start; + int status; + int outputlen=start; + byte[] outputbuf=buf; + int tmp=0; + + do{ + stream.next_out=tmpbuf; + stream.next_out_index=0; + stream.avail_out=BUF_SIZE; + status=stream.deflate(JZlib.Z_PARTIAL_FLUSH); + switch(status){ + case JZlib.Z_OK: + tmp=BUF_SIZE-stream.avail_out; + if(outputbuf.lengthbuffer.length-start){ + byte[] foo=new byte[inflated_end+start]; + System.arraycopy(buffer, 0, foo, 0, start); + System.arraycopy(inflated_buf, 0, foo, start, inflated_end); + buffer=foo; + } + else{ + System.arraycopy(inflated_buf, 0, buffer, start, inflated_end); + } + length[0]=inflated_end; + return buffer; + default: + System.err.println("uncompress: inflate returnd "+status); + return null; + } + } + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMAC.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMAC.java new file mode 100644 index 00000000..9aedc27f --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMAC.java @@ -0,0 +1,107 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jcraft; + +import java.security.*; + +class HMAC{ + + /* + * Refer to RFC2104. + * + * H(K XOR opad, H(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected + */ + private static final int B=64; + private byte[] k_ipad=null; + private byte[] k_opad=null; + + private MessageDigest md=null; + + private int bsize=0; + + protected void setH(MessageDigest md){ + this.md=md; + bsize=md.getDigestLength(); + } + + public int getBlockSize(){return bsize;}; + public void init(byte[] key) throws Exception{ + if(key.length>bsize){ + byte[] tmp=new byte[bsize]; + System.arraycopy(key, 0, tmp, 0, bsize); + key=tmp; + } + + /* if key is longer than B bytes reset it to key=MD5(key) */ + if(key.length>B){ + md.update(key, 0, key.length); + key=md.digest(); + } + + k_ipad=new byte[B]; + System.arraycopy(key, 0, k_ipad, 0, key.length); + k_opad=new byte[B]; + System.arraycopy(key, 0, k_opad, 0, key.length); + + /* XOR key with ipad and opad values */ + for(int i=0; i>>24); + tmp[1]=(byte)(i>>>16); + tmp[2]=(byte)(i>>>8); + tmp[3]=(byte)i; + update(tmp, 0, 4); + } + + public void update(byte foo[], int s, int l){ + md.update(foo, s, l); + } + + public void doFinal(byte[] buf, int offset){ + byte[] result=md.digest(); + md.update(k_opad, 0, B); + md.update(result, 0, bsize); + try{md.digest(buf, offset, bsize);}catch(Exception e){} + md.update(k_ipad, 0, B); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACMD5.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACMD5.java new file mode 100644 index 00000000..90960113 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACMD5.java @@ -0,0 +1,51 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jcraft; + +import com.jcraft.jsch.MAC; +import java.security.*; + +public class HMACMD5 extends HMAC implements MAC{ + private static final String name="hmac-md5"; + + public HMACMD5(){ + super(); + MessageDigest md=null; + try{ md=MessageDigest.getInstance("MD5"); } + catch(Exception e){ + System.err.println(e); + } + setH(md); + } + + public String getName(){ + return name; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACMD596.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACMD596.java new file mode 100644 index 00000000..95c6f60d --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACMD596.java @@ -0,0 +1,50 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jcraft; + +import com.jcraft.jsch.MAC; + +public class HMACMD596 extends HMACMD5{ + + private static final String name="hmac-md5-96"; + private static final int BSIZE=12; + + public int getBlockSize(){return BSIZE;}; + + private final byte[] _buf16=new byte[16]; + public void doFinal(byte[] buf, int offset){ + super.doFinal(_buf16, 0); + System.arraycopy(_buf16, 0, buf, offset, BSIZE); + } + + public String getName(){ + return name; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACSHA1.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACSHA1.java new file mode 100644 index 00000000..ea9eccf1 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACSHA1.java @@ -0,0 +1,51 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jcraft; + +import com.jcraft.jsch.MAC; +import java.security.*; + +public class HMACSHA1 extends HMAC implements MAC{ + private static final String name="hmac-sha1"; + + public HMACSHA1(){ + super(); + MessageDigest md=null; + try{ md=MessageDigest.getInstance("SHA-1"); } + catch(Exception e){ + System.err.println(e); + } + setH(md); + } + + public String getName(){ + return name; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACSHA196.java b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACSHA196.java new file mode 100644 index 00000000..86a81b5b --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jsch/jcraft/HMACSHA196.java @@ -0,0 +1,50 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2006-2012 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.jcraft.jsch.jcraft; + +import com.jcraft.jsch.MAC; + +public class HMACSHA196 extends HMACSHA1{ + + private static final String name="hmac-sha1-96"; + private static final int BSIZE=12; + + public int getBlockSize(){return BSIZE;}; + + private final byte[] _buf16=new byte[20]; + public void doFinal(byte[] buf, int offset){ + super.doFinal(_buf16, 0); + System.arraycopy(_buf16, 0, buf, offset, BSIZE); + } + + public String getName(){ + return name; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/Adler32.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Adler32.java new file mode 100644 index 00000000..a789a5a1 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Adler32.java @@ -0,0 +1,139 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final public class Adler32 implements Checksum { + + // largest prime smaller than 65536 + static final private int BASE=65521; + // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 + static final private int NMAX=5552; + + private long s1=1L; + private long s2=0L; + + public void reset(long init){ + s1=init&0xffff; + s2=(init>>16)&0xffff; + } + + public void reset(){ + s1=1L; + s2=0L; + } + + public long getValue(){ + return ((s2<<16)|s1); + } + + public void update(byte[] buf, int index, int len){ + + if(len==1){ + s1+=buf[index++]&0xff; s2+=s1; + s1%=BASE; + s2%=BASE; + return; + } + + int len1 = len/NMAX; + int len2 = len%NMAX; + while(len1-->0) { + int k=NMAX; + len-=k; + while(k-->0){ + s1+=buf[index++]&0xff; s2+=s1; + } + s1%=BASE; + s2%=BASE; + } + + int k=len2; + len-=k; + while(k-->0){ + s1+=buf[index++]&0xff; s2+=s1; + } + s1%=BASE; + s2%=BASE; + } + + public Adler32 copy(){ + Adler32 foo = new Adler32(); + foo.s1 = this.s1; + foo.s2 = this.s2; + return foo; + } + + // The following logic has come from zlib.1.2. + static long combine(long adler1, long adler2, long len2){ + long BASEL = (long)BASE; + long sum1; + long sum2; + long rem; // unsigned int + + rem = len2 % BASEL; + sum1 = adler1 & 0xffffL; + sum2 = rem * sum1; + sum2 %= BASEL; // MOD(sum2); + sum1 += (adler2 & 0xffffL) + BASEL - 1; + sum2 += ((adler1 >> 16) & 0xffffL) + ((adler2 >> 16) & 0xffffL) + BASEL - rem; + if (sum1 >= BASEL) sum1 -= BASEL; + if (sum1 >= BASEL) sum1 -= BASEL; + if (sum2 >= (BASEL << 1)) sum2 -= (BASEL << 1); + if (sum2 >= BASEL) sum2 -= BASEL; + return sum1 | (sum2 << 16); + } + +/* + private java.util.zip.Adler32 adler=new java.util.zip.Adler32(); + public void update(byte[] buf, int index, int len){ + if(buf==null) {adler.reset();} + else{adler.update(buf, index, len);} + } + public void reset(){ + adler.reset(); + } + public void reset(long init){ + if(init==1L){ + adler.reset(); + } + else{ + System.err.println("unsupported operation"); + } + } + public long getValue(){ + return adler.getValue(); + } +*/ +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/CRC32.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/CRC32.java new file mode 100644 index 00000000..30457968 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/CRC32.java @@ -0,0 +1,179 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final public class CRC32 implements Checksum { + + /* + * The following logic has come from RFC1952. + */ + private int v = 0; + private static int[] crc_table = null; + static { + crc_table = new int[256]; + for (int n = 0; n < 256; n++) { + int c = n; + for (int k = 8; --k >= 0; ) { + if ((c & 1) != 0) + c = 0xedb88320 ^ (c >>> 1); + else + c = c >>> 1; + } + crc_table[n] = c; + } + } + + public void update (byte[] buf, int index, int len) { + int c = ~v; + while (--len >= 0) + c = crc_table[(c^buf[index++])&0xff]^(c >>> 8); + v = ~c; + } + + public void reset(){ + v = 0; + } + + public void reset(long vv){ + v = (int)(vv&0xffffffffL); + } + + public long getValue(){ + return (long)(v&0xffffffffL); + } + + // The following logic has come from zlib.1.2. + private static final int GF2_DIM = 32; + static long combine(long crc1, long crc2, long len2){ + long row; + long[] even = new long[GF2_DIM]; + long[] odd = new long[GF2_DIM]; + + // degenerate case (also disallow negative lengths) + if (len2 <= 0) + return crc1; + + // put operator for one zero bit in odd + odd[0] = 0xedb88320L; // CRC-32 polynomial + row = 1; + for (int n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + // put operator for two zero bits in even + gf2_matrix_square(even, odd); + + // put operator for four zero bits in odd + gf2_matrix_square(odd, even); + + // apply len2 zeros to crc1 (first square will put the operator for one + // zero byte, eight zero bits, in even) + do { + // apply zeros operator for this bit of len2 + gf2_matrix_square(even, odd); + if ((len2 & 1)!=0) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + // if no more bits set, then done + if (len2 == 0) + break; + + // another iteration of the loop with odd and even swapped + gf2_matrix_square(odd, even); + if ((len2 & 1)!=0) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + // if no more bits set, then done + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; + } + + private static long gf2_matrix_times(long[] mat, long vec){ + long sum = 0; + int index = 0; + while (vec!=0) { + if ((vec & 1)!=0) + sum ^= mat[index]; + vec >>= 1; + index++; + } + return sum; + } + + static final void gf2_matrix_square(long[] square, long[] mat) { + for (int n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); + } + + /* + private java.util.zip.CRC32 crc32 = new java.util.zip.CRC32(); + + public void update(byte[] buf, int index, int len){ + if(buf==null) {crc32.reset();} + else{crc32.update(buf, index, len);} + } + public void reset(){ + crc32.reset(); + } + public void reset(long init){ + if(init==0L){ + crc32.reset(); + } + else{ + System.err.println("unsupported operation"); + } + } + public long getValue(){ + return crc32.getValue(); + } +*/ + public CRC32 copy(){ + CRC32 foo = new CRC32(); + foo.v = this.v; + return foo; + } + + public static int[] getCRC32Table(){ + int[] tmp = new int[crc_table.length]; + System.arraycopy(crc_table, 0, tmp, 0, tmp.length); + return tmp; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/Checksum.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Checksum.java new file mode 100644 index 00000000..1139093c --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Checksum.java @@ -0,0 +1,43 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +interface Checksum { + void update(byte[] buf, int index, int len); + void reset(); + void reset(long init); + long getValue(); + Checksum copy(); +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/Deflate.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Deflate.java new file mode 100644 index 00000000..47ad4423 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Deflate.java @@ -0,0 +1,1754 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +public +final class Deflate implements Cloneable { + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_DEFAULT_COMPRESSION=-1; + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_MEM_LEVEL=8; + + static class Config{ + int good_length; // reduce lazy search above this match length + int max_lazy; // do not perform lazy search above this match length + int nice_length; // quit search above this match length + int max_chain; + int func; + Config(int good_length, int max_lazy, + int nice_length, int max_chain, int func){ + this.good_length=good_length; + this.max_lazy=max_lazy; + this.nice_length=nice_length; + this.max_chain=max_chain; + this.func=func; + } + } + + static final private int STORED=0; + static final private int FAST=1; + static final private int SLOW=2; + static final private Config[] config_table; + static{ + config_table=new Config[10]; + // good lazy nice chain + config_table[0]=new Config(0, 0, 0, 0, STORED); + config_table[1]=new Config(4, 4, 8, 4, FAST); + config_table[2]=new Config(4, 5, 16, 8, FAST); + config_table[3]=new Config(4, 6, 32, 32, FAST); + + config_table[4]=new Config(4, 4, 16, 16, SLOW); + config_table[5]=new Config(8, 16, 32, 32, SLOW); + config_table[6]=new Config(8, 16, 128, 128, SLOW); + config_table[7]=new Config(8, 32, 128, 256, SLOW); + config_table[8]=new Config(32, 128, 258, 1024, SLOW); + config_table[9]=new Config(32, 258, 258, 4096, SLOW); + } + + static final private String[] z_errmsg = { + "need dictionary", // Z_NEED_DICT 2 + "stream end", // Z_STREAM_END 1 + "", // Z_OK 0 + "file error", // Z_ERRNO (-1) + "stream error", // Z_STREAM_ERROR (-2) + "data error", // Z_DATA_ERROR (-3) + "insufficient memory", // Z_MEM_ERROR (-4) + "buffer error", // Z_BUF_ERROR (-5) + "incompatible version",// Z_VERSION_ERROR (-6) + "" + }; + + // block not completed, need more input or more output + static final private int NeedMore=0; + + // block flush performed + static final private int BlockDone=1; + + // finish started, need only more output at next deflate + static final private int FinishStarted=2; + + // finish done, accept no more input or output + static final private int FinishDone=3; + + // preset dictionary flag in zlib header + static final private int PRESET_DICT=0x20; + + static final private int Z_FILTERED=1; + static final private int Z_HUFFMAN_ONLY=2; + static final private int Z_DEFAULT_STRATEGY=0; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + static final private int INIT_STATE=42; + static final private int BUSY_STATE=113; + static final private int FINISH_STATE=666; + + // The deflate compression method + static final private int Z_DEFLATED=8; + + static final private int STORED_BLOCK=0; + static final private int STATIC_TREES=1; + static final private int DYN_TREES=2; + + // The three kinds of block type + static final private int Z_BINARY=0; + static final private int Z_ASCII=1; + static final private int Z_UNKNOWN=2; + + static final private int Buf_size=8*2; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + static final private int REP_3_6=16; + + // repeat a zero length 3-10 times (3 bits of repeat count) + static final private int REPZ_3_10=17; + + // repeat a zero length 11-138 times (7 bits of repeat count) + static final private int REPZ_11_138=18; + + static final private int MIN_MATCH=3; + static final private int MAX_MATCH=258; + static final private int MIN_LOOKAHEAD=(MAX_MATCH+MIN_MATCH+1); + + static final private int MAX_BITS=15; + static final private int D_CODES=30; + static final private int BL_CODES=19; + static final private int LENGTH_CODES=29; + static final private int LITERALS=256; + static final private int L_CODES=(LITERALS+1+LENGTH_CODES); + static final private int HEAP_SIZE=(2*L_CODES+1); + + static final private int END_BLOCK=256; + + ZStream strm; // pointer back to this zlib stream + int status; // as the name implies + byte[] pending_buf; // output still pending + int pending_buf_size; // size of pending_buf + int pending_out; // next pending byte to output to the stream + int pending; // nb of bytes in the pending buffer + int wrap = 1; + byte data_type; // UNKNOWN, BINARY or ASCII + byte method; // STORED (for zip only) or DEFLATED + int last_flush; // value of flush param for previous deflate call + + int w_size; // LZ77 window size (32K by default) + int w_bits; // log2(w_size) (8..16) + int w_mask; // w_size - 1 + + byte[] window; + // Sliding window. Input bytes are read into the second half of the window, + // and move to the first half later to keep a dictionary of at least wSize + // bytes. With this organization, matches are limited to a distance of + // wSize-MAX_MATCH bytes, but this ensures that IO is always + // performed with a length multiple of the block size. Also, it limits + // the window size to 64K, which is quite useful on MSDOS. + // To do: use the user input buffer as sliding window. + + int window_size; + // Actual size of window: 2*wSize, except when the user input buffer + // is directly used as sliding window. + + short[] prev; + // Link to older string with same hash index. To limit the size of this + // array to 64K, this link is maintained only for the last 32K strings. + // An index in this array is thus a window index modulo 32K. + + short[] head; // Heads of the hash chains or NIL. + + int ins_h; // hash index of string to be inserted + int hash_size; // number of elements in hash table + int hash_bits; // log2(hash_size) + int hash_mask; // hash_size-1 + + // Number of bits by which ins_h must be shifted at each input + // step. It must be such that after MIN_MATCH steps, the oldest + // byte no longer takes part in the hash key, that is: + // hash_shift * MIN_MATCH >= hash_bits + int hash_shift; + + // Window position at the beginning of the current output block. Gets + // negative when the window is moved backwards. + + int block_start; + + int match_length; // length of best match + int prev_match; // previous match + int match_available; // set if previous match exists + int strstart; // start of string to insert + int match_start; // start of matching string + int lookahead; // number of valid bytes ahead in window + + // Length of the best match at previous step. Matches not greater than this + // are discarded. This is used in the lazy match evaluation. + int prev_length; + + // To speed up deflation, hash chains are never searched beyond this + // length. A higher limit improves compression ratio but degrades the speed. + int max_chain_length; + + // Attempt to find a better match only when the current match is strictly + // smaller than this value. This mechanism is used only for compression + // levels >= 4. + int max_lazy_match; + + // Insert new strings in the hash table only if the match length is not + // greater than this length. This saves time but degrades compression. + // max_insert_length is used only for compression levels <= 3. + + int level; // compression level (1..9) + int strategy; // favor or force Huffman coding + + // Use a faster search when the previous match is longer than this + int good_match; + + // Stop searching when current match exceeds this + int nice_match; + + short[] dyn_ltree; // literal and length tree + short[] dyn_dtree; // distance tree + short[] bl_tree; // Huffman tree for bit lengths + + Tree l_desc=new Tree(); // desc for literal tree + Tree d_desc=new Tree(); // desc for distance tree + Tree bl_desc=new Tree(); // desc for bit length tree + + // number of codes at each bit length for an optimal tree + short[] bl_count=new short[MAX_BITS+1]; + // working area to be used in Tree#gen_codes() + short[] next_code=new short[MAX_BITS+1]; + + // heap used to build the Huffman trees + int[] heap=new int[2*L_CODES+1]; + + int heap_len; // number of elements in the heap + int heap_max; // element of largest frequency + // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + // The same heap array is used to build all trees. + + // Depth of each subtree used as tie breaker for trees of equal frequency + byte[] depth=new byte[2*L_CODES+1]; + + int l_buf; // index for literals or lengths */ + + // Size of match buffer for literals/lengths. There are 4 reasons for + // limiting lit_bufsize to 64K: + // - frequencies can be kept in 16 bit counters + // - if compression is not successful for the first block, all input + // data is still in the window so we can still emit a stored block even + // when input comes from standard input. (This can also be done for + // all blocks if lit_bufsize is not greater than 32K.) + // - if compression is not successful for a file smaller than 64K, we can + // even emit a stored file instead of a stored block (saving 5 bytes). + // This is applicable only for zip (not gzip or zlib). + // - creating new Huffman trees less frequently may not provide fast + // adaptation to changes in the input data statistics. (Take for + // example a binary file with poorly compressible code followed by + // a highly compressible string table.) Smaller buffer sizes give + // fast adaptation but have of course the overhead of transmitting + // trees more frequently. + // - I can't count above 4 + int lit_bufsize; + + int last_lit; // running index in l_buf + + // Buffer for distances. To simplify the code, d_buf and l_buf have + // the same number of elements. To use different lengths, an extra flag + // array would be necessary. + + int d_buf; // index of pendig_buf + + int opt_len; // bit length of current block with optimal trees + int static_len; // bit length of current block with static trees + int matches; // number of string matches in current block + int last_eob_len; // bit length of EOB code for last block + + // Output buffer. bits are inserted starting at the bottom (least + // significant bits). + short bi_buf; + + // Number of valid bits in bi_buf. All bits above the last valid bit + // are always zero. + int bi_valid; + + GZIPHeader gheader = null; + + Deflate(ZStream strm){ + this.strm=strm; + dyn_ltree=new short[HEAP_SIZE*2]; + dyn_dtree=new short[(2*D_CODES+1)*2]; // distance tree + bl_tree=new short[(2*BL_CODES+1)*2]; // Huffman tree for bit lengths + } + + void lm_init() { + window_size=2*w_size; + + head[hash_size-1]=0; + for(int i=0; i= 3; max_blindex--) { + if (bl_tree[Tree.bl_order[max_blindex]*2+1] != 0) break; + } + // Update opt_len to include the bit length tree and counts + opt_len += 3*(max_blindex+1) + 5+5+4; + + return max_blindex; + } + + + // Send the header for a block using dynamic Huffman trees: the counts, the + // lengths of the bit length codes, the literal tree and the distance tree. + // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + void send_all_trees(int lcodes, int dcodes, int blcodes){ + int rank; // index in bl_order + + send_bits(lcodes-257, 5); // not +255 as stated in appnote.txt + send_bits(dcodes-1, 5); + send_bits(blcodes-4, 4); // not -3 as stated in appnote.txt + for (rank = 0; rank < blcodes; rank++) { + send_bits(bl_tree[Tree.bl_order[rank]*2+1], 3); + } + send_tree(dyn_ltree, lcodes-1); // literal tree + send_tree(dyn_dtree, dcodes-1); // distance tree + } + + // Send a literal or distance tree in compressed form, using the codes in + // bl_tree. + void send_tree (short[] tree,// the tree to be sent + int max_code // and its largest code of non zero frequency + ){ + int n; // iterates over all tree elements + int prevlen = -1; // last emitted length + int curlen; // length of current code + int nextlen = tree[0*2+1]; // length of next code + int count = 0; // repeat count of the current code + int max_count = 7; // max repeat count + int min_count = 4; // min repeat count + + if (nextlen == 0){ max_count = 138; min_count = 3; } + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[(n+1)*2+1]; + if(++count < max_count && curlen == nextlen) { + continue; + } + else if(count < min_count) { + do { send_code(curlen, bl_tree); } while (--count != 0); + } + else if(curlen != 0){ + if(curlen != prevlen){ + send_code(curlen, bl_tree); count--; + } + send_code(REP_3_6, bl_tree); + send_bits(count-3, 2); + } + else if(count <= 10){ + send_code(REPZ_3_10, bl_tree); + send_bits(count-3, 3); + } + else{ + send_code(REPZ_11_138, bl_tree); + send_bits(count-11, 7); + } + count = 0; prevlen = curlen; + if(nextlen == 0){ + max_count = 138; min_count = 3; + } + else if(curlen == nextlen){ + max_count = 6; min_count = 3; + } + else{ + max_count = 7; min_count = 4; + } + } + } + + // Output a byte on the stream. + // IN assertion: there is enough room in pending_buf. + final void put_byte(byte[] p, int start, int len){ + System.arraycopy(p, start, pending_buf, pending, len); + pending+=len; + } + + final void put_byte(byte c){ + pending_buf[pending++]=c; + } + final void put_short(int w) { + put_byte((byte)(w/*&0xff*/)); + put_byte((byte)(w>>>8)); + } + final void putShortMSB(int b){ + put_byte((byte)(b>>8)); + put_byte((byte)(b/*&0xff*/)); + } + + final void send_code(int c, short[] tree){ + int c2=c*2; + send_bits((tree[c2]&0xffff), (tree[c2+1]&0xffff)); + } + + void send_bits(int value, int length){ + int len = length; + if (bi_valid > (int)Buf_size - len) { + int val = value; +// bi_buf |= (val << bi_valid); + bi_buf |= ((val << bi_valid)&0xffff); + put_short(bi_buf); + bi_buf = (short)(val >>> (Buf_size - bi_valid)); + bi_valid += len - Buf_size; + } else { +// bi_buf |= (value) << bi_valid; + bi_buf |= (((value) << bi_valid)&0xffff); + bi_valid += len; + } + } + + // Send one empty static block to give enough lookahead for inflate. + // This takes 10 bits, of which 7 may remain in the bit buffer. + // The current inflate code requires 9 bits of lookahead. If the + // last two codes for the previous block (real code plus EOB) were coded + // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + // the last real code. In this case we send two empty static blocks instead + // of one. (There are no problems if the previous block is stored or fixed.) + // To simplify the code, we assume the worst case of last real code encoded + // on one bit only. + void _tr_align(){ + send_bits(STATIC_TREES<<1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + + bi_flush(); + + // Of the 10 bits for the empty block, we have already sent + // (10 - bi_valid) bits. The lookahead for the last real code (before + // the EOB of the previous block) was thus at least one plus the length + // of the EOB plus what we have just sent of the empty static block. + if (1 + last_eob_len + 10 - bi_valid < 9) { + send_bits(STATIC_TREES<<1, 3); + send_code(END_BLOCK, StaticTree.static_ltree); + bi_flush(); + } + last_eob_len = 7; + } + + + // Save the match info and tally the frequency counts. Return true if + // the current block must be flushed. + boolean _tr_tally (int dist, // distance of matched string + int lc // match length-MIN_MATCH or unmatched char (if dist==0) + ){ + + pending_buf[d_buf+last_lit*2] = (byte)(dist>>>8); + pending_buf[d_buf+last_lit*2+1] = (byte)dist; + + pending_buf[l_buf+last_lit] = (byte)lc; last_lit++; + + if (dist == 0) { + // lc is the unmatched char + dyn_ltree[lc*2]++; + } + else { + matches++; + // Here, lc is the match length - MIN_MATCH + dist--; // dist = match distance - 1 + dyn_ltree[(Tree._length_code[lc]+LITERALS+1)*2]++; + dyn_dtree[Tree.d_code(dist)*2]++; + } + + if ((last_lit & 0x1fff) == 0 && level > 2) { + // Compute an upper bound for the compressed length + int out_length = last_lit*8; + int in_length = strstart - block_start; + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (int)dyn_dtree[dcode*2] * + (5L+Tree.extra_dbits[dcode]); + } + out_length >>>= 3; + if ((matches < (last_lit/2)) && out_length < in_length/2) return true; + } + + return (last_lit == lit_bufsize-1); + // We avoid equality with lit_bufsize because of wraparound at 64K + // on 16 bit machines and because stored blocks are restricted to + // 64K-1 bytes. + } + + // Send the block data compressed using the given Huffman trees + void compress_block(short[] ltree, short[] dtree){ + int dist; // distance of matched string + int lc; // match length or unmatched char (if dist == 0) + int lx = 0; // running index in l_buf + int code; // the code to send + int extra; // number of extra bits to send + + if (last_lit != 0){ + do{ + dist=((pending_buf[d_buf+lx*2]<<8)&0xff00)| + (pending_buf[d_buf+lx*2+1]&0xff); + lc=(pending_buf[l_buf+lx])&0xff; lx++; + + if(dist == 0){ + send_code(lc, ltree); // send a literal byte + } + else{ + // Here, lc is the match length - MIN_MATCH + code = Tree._length_code[lc]; + + send_code(code+LITERALS+1, ltree); // send the length code + extra = Tree.extra_lbits[code]; + if(extra != 0){ + lc -= Tree.base_length[code]; + send_bits(lc, extra); // send the extra length bits + } + dist--; // dist is now the match distance - 1 + code = Tree.d_code(dist); + + send_code(code, dtree); // send the distance code + extra = Tree.extra_dbits[code]; + if (extra != 0) { + dist -= Tree.base_dist[code]; + send_bits(dist, extra); // send the extra distance bits + } + } // literal or match pair ? + + // Check that the overlay between pending_buf and d_buf+l_buf is ok: + } + while (lx < last_lit); + } + + send_code(END_BLOCK, ltree); + last_eob_len = ltree[END_BLOCK*2+1]; + } + + // Set the data type to ASCII or BINARY, using a crude approximation: + // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + // IN assertion: the fields freq of dyn_ltree are set and the total of all + // frequencies does not exceed 64K (to fit in an int on 16 bit machines). + void set_data_type(){ + int n = 0; + int ascii_freq = 0; + int bin_freq = 0; + while(n<7){ bin_freq += dyn_ltree[n*2]; n++;} + while(n<128){ ascii_freq += dyn_ltree[n*2]; n++;} + while(n (ascii_freq >>> 2) ? Z_BINARY : Z_ASCII); + } + + // Flush the bit buffer, keeping at most 7 bits in it. + void bi_flush(){ + if (bi_valid == 16) { + put_short(bi_buf); + bi_buf=0; + bi_valid=0; + } + else if (bi_valid >= 8) { + put_byte((byte)bi_buf); + bi_buf>>>=8; + bi_valid-=8; + } + } + + // Flush the bit buffer and align the output on a byte boundary + void bi_windup(){ + if (bi_valid > 8) { + put_short(bi_buf); + } else if (bi_valid > 0) { + put_byte((byte)bi_buf); + } + bi_buf = 0; + bi_valid = 0; + } + + // Copy a stored block, storing first the length and its + // one's complement if requested. + void copy_block(int buf, // the input data + int len, // its length + boolean header // true if block header must be written + ){ + int index=0; + bi_windup(); // align on byte boundary + last_eob_len = 8; // enough lookahead for inflate + + if (header) { + put_short((short)len); + put_short((short)~len); + } + + // while(len--!=0) { + // put_byte(window[buf+index]); + // index++; + // } + put_byte(window, buf, len); + } + + void flush_block_only(boolean eof){ + _tr_flush_block(block_start>=0 ? block_start : -1, + strstart-block_start, + eof); + block_start=strstart; + strm.flush_pending(); + } + + // Copy without compression as much as possible from the input stream, return + // the current block state. + // This function does not insert new strings in the dictionary since + // uncompressible data is probably not useful. This function is used + // only for the level=0 compression option. + // NOTE: this function should be optimized to avoid extra copying from + // window to pending_buf. + int deflate_stored(int flush){ + // Stored blocks are limited to 0xffff bytes, pending_buf is limited + // to pending_buf_size, and each stored block has a 5 byte header: + + int max_block_size = 0xffff; + int max_start; + + if(max_block_size > pending_buf_size - 5) { + max_block_size = pending_buf_size - 5; + } + + // Copy as much as possible from input to output: + while(true){ + // Fill the window as much as possible: + if(lookahead<=1){ + fill_window(); + if(lookahead==0 && flush==Z_NO_FLUSH) return NeedMore; + if(lookahead==0) break; // flush the current block + } + + strstart+=lookahead; + lookahead=0; + + // Emit a stored block if pending_buf will be full: + max_start=block_start+max_block_size; + if(strstart==0|| strstart>=max_start) { + // strstart == 0 is possible when wraparound on 16-bit machine + lookahead = (int)(strstart-max_start); + strstart = (int)max_start; + + flush_block_only(false); + if(strm.avail_out==0) return NeedMore; + + } + + // Flush if we may have to slide, otherwise block_start may become + // negative and the data will be gone: + if(strstart-block_start >= w_size-MIN_LOOKAHEAD) { + flush_block_only(false); + if(strm.avail_out==0) return NeedMore; + } + } + + flush_block_only(flush == Z_FINISH); + if(strm.avail_out==0) + return (flush == Z_FINISH) ? FinishStarted : NeedMore; + + return flush == Z_FINISH ? FinishDone : BlockDone; + } + + // Send a stored block + void _tr_stored_block(int buf, // input block + int stored_len, // length of input block + boolean eof // true if this is the last block for a file + ){ + send_bits((STORED_BLOCK<<1)+(eof?1:0), 3); // send block type + copy_block(buf, stored_len, true); // with header + } + + // Determine the best encoding for the current block: dynamic trees, static + // trees or store, and output the encoded block to the zip file. + void _tr_flush_block(int buf, // input block, or NULL if too old + int stored_len, // length of input block + boolean eof // true if this is the last block for a file + ) { + int opt_lenb, static_lenb;// opt_len and static_len in bytes + int max_blindex = 0; // index of last bit length code of non zero freq + + // Build the Huffman trees unless a stored block is forced + if(level > 0) { + // Check if the file is ascii or binary + if(data_type == Z_UNKNOWN) set_data_type(); + + // Construct the literal and distance trees + l_desc.build_tree(this); + + d_desc.build_tree(this); + + // At this point, opt_len and static_len are the total bit lengths of + // the compressed block data, excluding the tree representations. + + // Build the bit length tree for the above two trees, and get the index + // in bl_order of the last bit length code to send. + max_blindex=build_bl_tree(); + + // Determine the best encoding. Compute first the block length in bytes + opt_lenb=(opt_len+3+7)>>>3; + static_lenb=(static_len+3+7)>>>3; + + if(static_lenb<=opt_lenb) opt_lenb=static_lenb; + } + else { + opt_lenb=static_lenb=stored_len+5; // force a stored block + } + + if(stored_len+4<=opt_lenb && buf != -1){ + // 4: two words for the lengths + // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + // Otherwise we can't have processed more than WSIZE input bytes since + // the last block flush, because compression would have been + // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + // transform a block into a stored block. + _tr_stored_block(buf, stored_len, eof); + } + else if(static_lenb == opt_lenb){ + send_bits((STATIC_TREES<<1)+(eof?1:0), 3); + compress_block(StaticTree.static_ltree, StaticTree.static_dtree); + } + else{ + send_bits((DYN_TREES<<1)+(eof?1:0), 3); + send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1); + compress_block(dyn_ltree, dyn_dtree); + } + + // The above check is made mod 2^32, for files larger than 512 MB + // and uLong implemented on 32 bits. + + init_block(); + + if(eof){ + bi_windup(); + } + } + + // Fill the window when the lookahead becomes insufficient. + // Updates strstart and lookahead. + // + // IN assertion: lookahead < MIN_LOOKAHEAD + // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + // At least one byte has been read, or avail_in == 0; reads are + // performed for at least two bytes (required for the zip translate_eol + // option -- not supported here). + void fill_window(){ + int n, m; + int p; + int more; // Amount of free space at the end of the window. + + do{ + more = (window_size-lookahead-strstart); + + // Deal with !@#$% 64K limit: + if(more==0 && strstart==0 && lookahead==0){ + more = w_size; + } + else if(more==-1) { + // Very unlikely, but possible on 16 bit machine if strstart == 0 + // and lookahead == 1 (input done one byte at time) + more--; + + // If the window is almost full and there is insufficient lookahead, + // move the upper half to the lower one to make room in the upper half. + } + else if(strstart >= w_size+ w_size-MIN_LOOKAHEAD) { + System.arraycopy(window, w_size, window, 0, w_size); + match_start-=w_size; + strstart-=w_size; // we now have strstart >= MAX_DIST + block_start-=w_size; + + // Slide the hash table (could be avoided with 32 bit values + // at the expense of memory usage). We slide even when level == 0 + // to keep the hash table consistent if we switch back to level > 0 + // later. (Using level 0 permanently is not an optimal usage of + // zlib, so we don't care about this pathological case.) + + n = hash_size; + p=n; + do { + m = (head[--p]&0xffff); + head[p]=(m>=w_size ? (short)(m-w_size) : 0); + } + while (--n != 0); + + n = w_size; + p = n; + do { + m = (prev[--p]&0xffff); + prev[p] = (m >= w_size ? (short)(m-w_size) : 0); + // If n is not on any hash chain, prev[n] is garbage but + // its value will never be used. + } + while (--n!=0); + more += w_size; + } + + if (strm.avail_in == 0) return; + + // If there was no sliding: + // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + // more == window_size - lookahead - strstart + // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + // => more >= window_size - 2*WSIZE + 2 + // In the BIG_MEM or MMAP case (not yet supported), + // window_size == input_size + MIN_LOOKAHEAD && + // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + // Otherwise, window_size == 2*WSIZE so more >= 2. + // If there was sliding, more >= WSIZE. So in all cases, more >= 2. + + n = strm.read_buf(window, strstart + lookahead, more); + lookahead += n; + + // Initialize the hash value now that we have some input: + if(lookahead >= MIN_MATCH) { + ins_h = window[strstart]&0xff; + ins_h=(((ins_h)<= MIN_MATCH){ + ins_h=(((ins_h)<=MIN_MATCH){ + // check_match(strstart, match_start, match_length); + + bflush=_tr_tally(strstart-match_start, match_length-MIN_MATCH); + + lookahead -= match_length; + + // Insert new strings in the hash table only if the match length + // is not too large. This saves time but degrades compression. + if(match_length <= max_lazy_match && + lookahead >= MIN_MATCH) { + match_length--; // string at strstart already in hash table + do{ + strstart++; + + ins_h=((ins_h<= MIN_MATCH) { + ins_h=(((ins_h)< 4096))) { + + // If prev_match is also MIN_MATCH, match_start is garbage + // but we will ignore the current match anyway. + match_length = MIN_MATCH-1; + } + } + + // If there was a match at the previous step and the current + // match is not better, output the previous match: + if(prev_length >= MIN_MATCH && match_length <= prev_length) { + int max_insert = strstart + lookahead - MIN_MATCH; + // Do not insert strings in hash table beyond this. + + // check_match(strstart-1, prev_match, prev_length); + + bflush=_tr_tally(strstart-1-prev_match, prev_length - MIN_MATCH); + + // Insert in hash table all strings up to the end of the match. + // strstart-1 and strstart are already inserted. If there is not + // enough lookahead, the last two strings are not inserted in + // the hash table. + lookahead -= prev_length-1; + prev_length -= 2; + do{ + if(++strstart <= max_insert) { + ins_h=(((ins_h)<(w_size-MIN_LOOKAHEAD) ? + strstart-(w_size-MIN_LOOKAHEAD) : 0; + int nice_match=this.nice_match; + + // Stop when cur_match becomes <= limit. To simplify the code, + // we prevent matches with the string of window index 0. + + int wmask = w_mask; + + int strend = strstart + MAX_MATCH; + byte scan_end1 = window[scan+best_len-1]; + byte scan_end = window[scan+best_len]; + + // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + // It is easy to get rid of this optimization if necessary. + + // Do not waste too much time if we already have a good match: + if (prev_length >= good_match) { + chain_length >>= 2; + } + + // Do not look for matches beyond the end of the input. This is necessary + // to make deflate deterministic. + if (nice_match > lookahead) nice_match = lookahead; + + do { + match = cur_match; + + // Skip to next match if the match length cannot increase + // or if the match length is less than 2: + if (window[match+best_len] != scan_end || + window[match+best_len-1] != scan_end1 || + window[match] != window[scan] || + window[++match] != window[scan+1]) continue; + + // The check at best_len-1 can be removed because it will be made + // again later. (This heuristic is not always a win.) + // It is not necessary to compare scan[2] and match[2] since they + // are always equal when the other bytes match, given that + // the hash keys are equal and that HASH_BITS >= 8. + scan += 2; match++; + + // We check for insufficient lookahead only every 8th comparison; + // the 256th check will be made at strstart+258. + do { + } while (window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + window[++scan] == window[++match] && + scan < strend); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + + if(len>best_len) { + match_start = cur_match; + best_len = len; + if (len >= nice_match) break; + scan_end1 = window[scan+best_len-1]; + scan_end = window[scan+best_len]; + } + + } while ((cur_match = (prev[cur_match & wmask]&0xffff)) > limit + && --chain_length != 0); + + if (best_len <= lookahead) return best_len; + return lookahead; + } + + int deflateInit(int level, int bits, int memlevel){ + return deflateInit(level, Z_DEFLATED, bits, memlevel, + Z_DEFAULT_STRATEGY); + } + + int deflateInit(int level, int bits){ + return deflateInit(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY); + } + int deflateInit(int level){ + return deflateInit(level, MAX_WBITS); + } + private int deflateInit(int level, int method, int windowBits, + int memLevel, int strategy){ + int wrap = 1; + // byte[] my_version=ZLIB_VERSION; + + // + // if (version == null || version[0] != my_version[0] + // || stream_size != sizeof(z_stream)) { + // return Z_VERSION_ERROR; + // } + + strm.msg = null; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; + + if (windowBits < 0) { // undocumented feature: suppress zlib header + wrap = 0; + windowBits = -windowBits; + } + else if(windowBits > 15){ + wrap = 2; + windowBits -= 16; + strm.adler=new CRC32(); + } + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || + method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + strm.dstate = (Deflate)this; + + this.wrap = wrap; + w_bits = windowBits; + w_size = 1 << w_bits; + w_mask = w_size - 1; + + hash_bits = memLevel + 7; + hash_size = 1 << hash_bits; + hash_mask = hash_size - 1; + hash_shift = ((hash_bits+MIN_MATCH-1)/MIN_MATCH); + + window = new byte[w_size*2]; + prev = new short[w_size]; + head = new short[hash_size]; + + lit_bufsize = 1 << (memLevel + 6); // 16K elements by default + + // We overlay pending_buf and d_buf+l_buf. This works since the average + // output size for (length,distance) codes is <= 24 bits. + pending_buf = new byte[lit_bufsize*4]; + pending_buf_size = lit_bufsize*4; + + d_buf = lit_bufsize/2; + l_buf = (1+2)*lit_bufsize; + + this.level = level; + + this.strategy = strategy; + this.method = (byte)method; + + return deflateReset(); + } + + int deflateReset(){ + strm.total_in = strm.total_out = 0; + strm.msg = null; // + strm.data_type = Z_UNKNOWN; + + pending = 0; + pending_out = 0; + + if(wrap < 0){ + wrap = -wrap; + } + status = (wrap==0) ? BUSY_STATE : INIT_STATE; + strm.adler.reset(); + + last_flush = Z_NO_FLUSH; + + tr_init(); + lm_init(); + return Z_OK; + } + + int deflateEnd(){ + if(status!=INIT_STATE && status!=BUSY_STATE && status!=FINISH_STATE){ + return Z_STREAM_ERROR; + } + // Deallocate in reverse order of allocations: + pending_buf=null; + head=null; + prev=null; + window=null; + // free + // dstate=null; + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; + } + + int deflateParams(int _level, int _strategy){ + int err=Z_OK; + + if(_level == Z_DEFAULT_COMPRESSION){ + _level = 6; + } + if(_level < 0 || _level > 9 || + _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + + if(config_table[level].func!=config_table[_level].func && + strm.total_in != 0) { + // Flush the last buffer: + err = strm.deflate(Z_PARTIAL_FLUSH); + } + + if(level != _level) { + level = _level; + max_lazy_match = config_table[level].max_lazy; + good_match = config_table[level].good_length; + nice_match = config_table[level].nice_length; + max_chain_length = config_table[level].max_chain; + } + strategy = _strategy; + return err; + } + + int deflateSetDictionary (byte[] dictionary, int dictLength){ + int length = dictLength; + int index=0; + + if(dictionary == null || status != INIT_STATE) + return Z_STREAM_ERROR; + + strm.adler.update(dictionary, 0, dictLength); + + if(length < MIN_MATCH) return Z_OK; + if(length > w_size-MIN_LOOKAHEAD){ + length = w_size-MIN_LOOKAHEAD; + index=dictLength-length; // use the tail of the dictionary + } + System.arraycopy(dictionary, index, window, 0, length); + strstart = length; + block_start = length; + + // Insert all strings in the hash table (except for the last two bytes). + // s->lookahead stays null, so s->ins_h will be recomputed at the next + // call of fill_window. + + ins_h = window[0]&0xff; + ins_h=(((ins_h)<Z_FINISH || flush<0){ + return Z_STREAM_ERROR; + } + + if(strm.next_out == null || + (strm.next_in == null && strm.avail_in != 0) || + (status == FINISH_STATE && flush != Z_FINISH)) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_STREAM_ERROR)]; + return Z_STREAM_ERROR; + } + if(strm.avail_out == 0){ + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + old_flush = last_flush; + last_flush = flush; + + // Write the zlib header + if(status == INIT_STATE) { + if(wrap == 2){ + getGZIPHeader().put(this); + status=BUSY_STATE; + strm.adler.reset(); + } + else{ + int header = (Z_DEFLATED+((w_bits-8)<<4))<<8; + int level_flags=((level-1)&0xff)>>1; + + if(level_flags>3) level_flags=3; + header |= (level_flags<<6); + if(strstart!=0) header |= PRESET_DICT; + header+=31-(header % 31); + + status=BUSY_STATE; + putShortMSB(header); + + + // Save the adler32 of the preset dictionary: + if(strstart!=0){ + long adler=strm.adler.getValue(); + putShortMSB((int)(adler>>>16)); + putShortMSB((int)(adler&0xffff)); + } + strm.adler.reset(); + } + } + + // Flush as much pending output as possible + if(pending != 0) { + strm.flush_pending(); + if(strm.avail_out == 0) { + // Since avail_out is 0, deflate will be called again with + // more output space, but possibly with both pending and + // avail_in equal to zero. There won't be anything to do, + // but this is not an error situation so make sure we + // return OK instead of BUF_ERROR at next call of deflate: + last_flush = -1; + return Z_OK; + } + + // Make sure there is something to do and avoid duplicate consecutive + // flushes. For repeated and useless calls with Z_FINISH, we keep + // returning Z_STREAM_END instead of Z_BUFF_ERROR. + } + else if(strm.avail_in==0 && flush <= old_flush && + flush != Z_FINISH) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + // User must not provide more input after the first FINISH: + if(status == FINISH_STATE && strm.avail_in != 0) { + strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; + return Z_BUF_ERROR; + } + + // Start a new block or continue the current one. + if(strm.avail_in!=0 || lookahead!=0 || + (flush != Z_NO_FLUSH && status != FINISH_STATE)) { + int bstate=-1; + switch(config_table[level].func){ + case STORED: + bstate = deflate_stored(flush); + break; + case FAST: + bstate = deflate_fast(flush); + break; + case SLOW: + bstate = deflate_slow(flush); + break; + default: + } + + if (bstate==FinishStarted || bstate==FinishDone) { + status = FINISH_STATE; + } + if (bstate==NeedMore || bstate==FinishStarted) { + if(strm.avail_out == 0) { + last_flush = -1; // avoid BUF_ERROR next call, see above + } + return Z_OK; + // If flush != Z_NO_FLUSH && avail_out == 0, the next call + // of deflate should use the same flush parameter to make sure + // that the flush is complete. So we don't have to output an + // empty block here, this will be done at next call. This also + // ensures that for a very small output buffer, we emit at most + // one empty block. + } + + if (bstate==BlockDone) { + if(flush == Z_PARTIAL_FLUSH) { + _tr_align(); + } + else { // FULL_FLUSH or SYNC_FLUSH + _tr_stored_block(0, 0, false); + // For a full flush, this empty block will be recognized + // as a special marker by inflate_sync(). + if(flush == Z_FULL_FLUSH) { + //state.head[s.hash_size-1]=0; + for(int i=0; i>8)&0xff)); + put_byte((byte)((adler>>16)&0xff)); + put_byte((byte)((adler>>24)&0xff)); + put_byte((byte)(strm.total_in&0xff)); + put_byte((byte)((strm.total_in>>8)&0xff)); + put_byte((byte)((strm.total_in>>16)&0xff)); + put_byte((byte)((strm.total_in>>24)&0xff)); + + getGZIPHeader().setCRC(adler); + } + else{ + // Write the zlib trailer (adler32) + long adler=strm.adler.getValue(); + putShortMSB((int)(adler>>>16)); + putShortMSB((int)(adler&0xffff)); + } + + strm.flush_pending(); + + // If avail_out is zero, the application will call deflate again + // to flush the rest. + + if(wrap > 0) wrap = -wrap; // write the trailer only once! + return pending != 0 ? Z_OK : Z_STREAM_END; + } + + static int deflateCopy(ZStream dest, ZStream src){ + + if(src.dstate == null){ + return Z_STREAM_ERROR; + } + + if(src.next_in!=null){ + dest.next_in = new byte[src.next_in.length]; + System.arraycopy(src.next_in, 0, dest.next_in, 0, src.next_in.length); + } + dest.next_in_index = src.next_in_index; + dest.avail_in = src.avail_in; + dest.total_in = src.total_in; + + if(src.next_out!=null){ + dest.next_out = new byte[src.next_out.length]; + System.arraycopy(src.next_out, 0, dest.next_out ,0 , src.next_out.length); + } + + dest.next_out_index = src.next_out_index; + dest.avail_out = src.avail_out; + dest.total_out = src.total_out; + + dest.msg = src.msg; + dest.data_type = src.data_type; + dest.adler = src.adler.copy(); + + try{ + dest.dstate = (Deflate)src.dstate.clone(); + dest.dstate.strm = dest; + } + catch(CloneNotSupportedException e){ + // + } + return Z_OK; + } + + public Object clone() throws CloneNotSupportedException { + Deflate dest = (Deflate)super.clone(); + + dest.pending_buf = dup(dest.pending_buf); + dest.window = dup(dest.window); + + dest.prev = dup(dest.prev); + dest.head = dup(dest.head); + dest.dyn_ltree = dup(dest.dyn_ltree); + dest.dyn_dtree = dup(dest.dyn_dtree); + dest.bl_tree = dup(dest.bl_tree); + + dest.bl_count = dup(dest.bl_count); + dest.next_code = dup(dest.next_code); + dest.heap = dup(dest.heap); + dest.depth = dup(dest.depth); + + dest.l_desc.dyn_tree = dest.dyn_ltree; + dest.d_desc.dyn_tree = dest.dyn_dtree; + dest.bl_desc.dyn_tree = dest.bl_tree; + + /* + dest.l_desc.stat_desc = StaticTree.static_l_desc; + dest.d_desc.stat_desc = StaticTree.static_d_desc; + dest.bl_desc.stat_desc = StaticTree.static_bl_desc; + */ + + if(dest.gheader!=null){ + dest.gheader = (GZIPHeader)dest.gheader.clone(); + } + + return dest; + } + + private byte[] dup(byte[] buf){ + byte[] foo = new byte[buf.length]; + System.arraycopy(buf, 0, foo, 0, foo.length); + return foo; + } + private short[] dup(short[] buf){ + short[] foo = new short[buf.length]; + System.arraycopy(buf, 0, foo, 0, foo.length); + return foo; + } + private int[] dup(int[] buf){ + int[] foo = new int[buf.length]; + System.arraycopy(buf, 0, foo, 0, foo.length); + return foo; + } + + synchronized GZIPHeader getGZIPHeader(){ + if(gheader==null){ + gheader = new GZIPHeader(); + } + return gheader; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/Deflater.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Deflater.java new file mode 100644 index 00000000..ce0580dd --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Deflater.java @@ -0,0 +1,171 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final public class Deflater extends ZStream{ + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_WBITS=MAX_WBITS; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + private boolean finished = false; + + public Deflater(){ + super(); + } + + public Deflater(int level) throws GZIPException { + this(level, MAX_WBITS); + } + + public Deflater(int level, boolean nowrap) throws GZIPException { + this(level, MAX_WBITS, nowrap); + } + + public Deflater(int level, int bits) throws GZIPException { + this(level, bits, false); + } + + public Deflater(int level, int bits, boolean nowrap) throws GZIPException { + super(); + int ret = init(level, bits, nowrap); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public Deflater(int level, int bits, int memlevel, JZlib.WrapperType wrapperType) throws GZIPException { + super(); + int ret = init(level, bits, memlevel, wrapperType); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public Deflater(int level, int bits, int memlevel) throws GZIPException { + super(); + int ret = init(level, bits, memlevel); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public int init(int level){ + return init(level, MAX_WBITS); + } + public int init(int level, boolean nowrap){ + return init(level, MAX_WBITS, nowrap); + } + public int init(int level, int bits){ + return init(level, bits, false); + } + public int init(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){ + if(bits < 9 || bits > 15){ + return Z_STREAM_ERROR; + } + if(wrapperType == JZlib.W_NONE) { + bits *= -1; + } + else if(wrapperType == JZlib.W_GZIP) { + bits += 16; + } + else if(wrapperType == JZlib.W_ANY) { + return Z_STREAM_ERROR; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return init(level, bits, memlevel); + } + public int init(int level, int bits, int memlevel){ + finished = false; + dstate=new Deflate(this); + return dstate.deflateInit(level, bits, memlevel); + } + public int init(int level, int bits, boolean nowrap){ + finished = false; + dstate=new Deflate(this); + return dstate.deflateInit(level, nowrap?-bits:bits); + } + + public int deflate(int flush){ + if(dstate==null){ + return Z_STREAM_ERROR; + } + int ret = dstate.deflate(flush); + if(ret == Z_STREAM_END) + finished = true; + return ret; + } + public int end(){ + finished = true; + if(dstate==null) return Z_STREAM_ERROR; + int ret=dstate.deflateEnd(); + dstate=null; + free(); + return ret; + } + public int params(int level, int strategy){ + if(dstate==null) return Z_STREAM_ERROR; + return dstate.deflateParams(level, strategy); + } + public int setDictionary (byte[] dictionary, int dictLength){ + if(dstate == null) + return Z_STREAM_ERROR; + return dstate.deflateSetDictionary(dictionary, dictLength); + } + + public boolean finished(){ + return finished; + } + + public int copy(Deflater src){ + this.finished = src.finished; + return Deflate.deflateCopy(this, src); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/DeflaterOutputStream.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/DeflaterOutputStream.java new file mode 100644 index 00000000..4c9f0d25 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/DeflaterOutputStream.java @@ -0,0 +1,181 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jzlib; +import java.io.*; + +public class DeflaterOutputStream extends FilterOutputStream { + + protected final Deflater deflater; + + protected byte[] buffer; + + private boolean closed = false; + + private boolean syncFlush = false; + + private final byte[] buf1 = new byte[1]; + + protected boolean mydeflater = false; + + private boolean close_out = true; + + protected static final int DEFAULT_BUFSIZE = 512; + + public DeflaterOutputStream(OutputStream out) throws IOException { + this(out, + new Deflater(JZlib.Z_DEFAULT_COMPRESSION), + DEFAULT_BUFSIZE, true); + mydeflater = true; + } + + public DeflaterOutputStream(OutputStream out, Deflater def) throws IOException { + this(out, def, DEFAULT_BUFSIZE, true); + } + + public DeflaterOutputStream(OutputStream out, + Deflater deflater, + int size) throws IOException { + this(out, deflater, size, true); + } + public DeflaterOutputStream(OutputStream out, + Deflater deflater, + int size, + boolean close_out) throws IOException { + super(out); + if (out == null || deflater == null) { + throw new NullPointerException(); + } + else if (size <= 0) { + throw new IllegalArgumentException("buffer size must be greater than 0"); + } + this.deflater = deflater; + buffer = new byte[size]; + this.close_out = close_out; + } + + public void write(int b) throws IOException { + buf1[0] = (byte)(b & 0xff); + write(buf1, 0, 1); + } + + public void write(byte[] b, int off, int len) throws IOException { + if (deflater.finished()) { + throw new IOException("finished"); + } + else if (off<0 | len<0 | off+len>b.length) { + throw new IndexOutOfBoundsException(); + } + else if (len == 0) { + return; + } + else { + int flush = syncFlush ? JZlib.Z_SYNC_FLUSH : JZlib.Z_NO_FLUSH; + deflater.setInput(b, off, len, true); + while (deflater.avail_in>0) { + int err = deflate(flush); + if (err == JZlib.Z_STREAM_END) + break; + } + } + } + + public void finish() throws IOException { + while (!deflater.finished()) { + deflate(JZlib.Z_FINISH); + } + } + + public void close() throws IOException { + if (!closed) { + finish(); + if (mydeflater){ + deflater.end(); + } + if(close_out) + out.close(); + closed = true; + } + } + + protected int deflate(int flush) throws IOException { + deflater.setOutput(buffer, 0, buffer.length); + int err = deflater.deflate(flush); + switch(err) { + case JZlib.Z_OK: + case JZlib.Z_STREAM_END: + break; + case JZlib.Z_BUF_ERROR: + if(deflater.avail_in<=0 && flush!=JZlib.Z_FINISH){ + // flush() without any data + break; + } + default: + throw new IOException("failed to deflate"); + } + int len = deflater.next_out_index; + if (len > 0) { + out.write(buffer, 0, len); + } + return err; + } + + public void flush() throws IOException { + if (syncFlush && !deflater.finished()) { + while (true) { + int err = deflate(JZlib.Z_SYNC_FLUSH); + if (deflater.next_out_index < buffer.length) + break; + if (err == JZlib.Z_STREAM_END) + break; + } + } + out.flush(); + } + + public long getTotalIn() { + return deflater.getTotalIn(); + } + + public long getTotalOut() { + return deflater.getTotalOut(); + } + + public void setSyncFlush(boolean syncFlush){ + this.syncFlush = syncFlush; + } + + public boolean getSyncFlush(){ + return this.syncFlush; + } + + public Deflater getDeflater(){ + return deflater; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/GZIPException.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/GZIPException.java new file mode 100644 index 00000000..0beef40d --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/GZIPException.java @@ -0,0 +1,44 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +public class GZIPException extends java.io.IOException { + public GZIPException() { + super(); + } + public GZIPException(String s) { + super(s); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/GZIPHeader.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/GZIPHeader.java new file mode 100644 index 00000000..0405e00b --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/GZIPHeader.java @@ -0,0 +1,214 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +import java.io.UnsupportedEncodingException; + +/** + * @see "http://www.ietf.org/rfc/rfc1952.txt" + */ +public class GZIPHeader implements Cloneable { + + public static final byte OS_MSDOS = (byte) 0x00; + public static final byte OS_AMIGA = (byte) 0x01; + public static final byte OS_VMS = (byte) 0x02; + public static final byte OS_UNIX = (byte) 0x03; + public static final byte OS_ATARI = (byte) 0x05; + public static final byte OS_OS2 = (byte) 0x06; + public static final byte OS_MACOS = (byte) 0x07; + public static final byte OS_TOPS20 = (byte) 0x0a; + public static final byte OS_WIN32 = (byte) 0x0b; + public static final byte OS_VMCMS = (byte) 0x04; + public static final byte OS_ZSYSTEM = (byte) 0x08; + public static final byte OS_CPM = (byte) 0x09; + public static final byte OS_QDOS = (byte) 0x0c; + public static final byte OS_RISCOS = (byte) 0x0d; + public static final byte OS_UNKNOWN = (byte) 0xff; + + boolean text = false; + private boolean fhcrc = false; + long time; + int xflags; + int os = 255; + byte[] extra; + byte[] name; + byte[] comment; + int hcrc; + long crc; + boolean done = false; + long mtime = 0; + + public void setModifiedTime(long mtime) { + this.mtime = mtime; + } + + public long getModifiedTime() { + return mtime; + } + + public void setOS(int os) { + if((0<=os && os <=13) || os==255) + this.os=os; + else + throw new IllegalArgumentException("os: "+os); + } + + public int getOS(){ + return os; + } + + public void setName(String name) { + try{ + this.name=name.getBytes("ISO-8859-1"); + } + catch(UnsupportedEncodingException e){ + throw new IllegalArgumentException("name must be in ISO-8859-1 "+name); + } + } + + public String getName(){ + if(name==null) return ""; + try { + return new String(name, "ISO-8859-1"); + } + catch (UnsupportedEncodingException e) { + throw new InternalError(e.toString()); + } + } + + public void setComment(String comment) { + try{ + this.comment=comment.getBytes("ISO-8859-1"); + } + catch(UnsupportedEncodingException e){ + throw new IllegalArgumentException("comment must be in ISO-8859-1 "+name); + } + } + + public String getComment(){ + if(comment==null) return ""; + try { + return new String(comment, "ISO-8859-1"); + } + catch (UnsupportedEncodingException e) { + throw new InternalError(e.toString()); + } + } + + public void setCRC(long crc){ + this.crc = crc; + } + + public long getCRC(){ + return crc; + } + + void put(Deflate d){ + int flag = 0; + if(text){ + flag |= 1; // FTEXT + } + if(fhcrc){ + flag |= 2; // FHCRC + } + if(extra!=null){ + flag |= 4; // FEXTRA + } + if(name!=null){ + flag |= 8; // FNAME + } + if(comment!=null){ + flag |= 16; // FCOMMENT + } + int xfl = 0; + if(d.level == JZlib.Z_BEST_SPEED){ + xfl |= 4; + } + else if (d.level == JZlib.Z_BEST_COMPRESSION){ + xfl |= 2; + } + + d.put_short((short)0x8b1f); // ID1 ID2 + d.put_byte((byte)8); // CM(Compression Method) + d.put_byte((byte)flag); + d.put_byte((byte)mtime); + d.put_byte((byte)(mtime>>8)); + d.put_byte((byte)(mtime>>16)); + d.put_byte((byte)(mtime>>24)); + d.put_byte((byte)xfl); + d.put_byte((byte)os); + + if(extra!=null){ + d.put_byte((byte)extra.length); + d.put_byte((byte)(extra.length>>8)); + d.put_byte(extra, 0, extra.length); + } + + if(name!=null){ + d.put_byte(name, 0, name.length); + d.put_byte((byte)0); + } + + if(comment!=null){ + d.put_byte(comment, 0, comment.length); + d.put_byte((byte)0); + } + } + + @Override + public Object clone() throws CloneNotSupportedException { + GZIPHeader gheader = (GZIPHeader)super.clone(); + byte[] tmp; + if(gheader.extra!=null){ + tmp=new byte[gheader.extra.length]; + System.arraycopy(gheader.extra, 0, tmp, 0, tmp.length); + gheader.extra = tmp; + } + + if(gheader.name!=null){ + tmp=new byte[gheader.name.length]; + System.arraycopy(gheader.name, 0, tmp, 0, tmp.length); + gheader.name = tmp; + } + + if(gheader.comment!=null){ + tmp=new byte[gheader.comment.length]; + System.arraycopy(gheader.comment, 0, tmp, 0, tmp.length); + gheader.comment = tmp; + } + + return gheader; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/GZIPInputStream.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/GZIPInputStream.java new file mode 100644 index 00000000..5d29dca7 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/GZIPInputStream.java @@ -0,0 +1,145 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jzlib; +import java.io.*; + +public class GZIPInputStream extends InflaterInputStream { + + public GZIPInputStream(InputStream in) throws IOException { + this(in, DEFAULT_BUFSIZE, true); + } + + public GZIPInputStream(InputStream in, + int size, + boolean close_in) throws IOException { + this(in, new Inflater(15+16), size, close_in); + myinflater = true; + } + + public GZIPInputStream(InputStream in, + Inflater inflater, + int size, + boolean close_in) throws IOException { + super(in, inflater, size, close_in); + } + + public long getModifiedtime() { + return inflater.istate.getGZIPHeader().getModifiedTime(); + } + + public int getOS() { + return inflater.istate.getGZIPHeader().getOS(); + } + + public String getName() { + return inflater.istate.getGZIPHeader().getName(); + } + + public String getComment() { + return inflater.istate.getGZIPHeader().getComment(); + } + + public long getCRC() throws GZIPException { + if(inflater.istate.mode != 12 /*DONE*/) + throw new GZIPException("checksum is not calculated yet."); + return inflater.istate.getGZIPHeader().getCRC(); + } + + public void readHeader() throws IOException { + + byte[] empty = "".getBytes(); + inflater.setOutput(empty, 0, 0); + inflater.setInput(empty, 0, 0, false); + + byte[] b = new byte[10]; + + int n = fill(b); + if(n!=10){ + if(n>0){ + inflater.setInput(b, 0, n, false); + //inflater.next_in_index = n; + inflater.next_in_index = 0; + inflater.avail_in = n; + } + throw new IOException("no input"); + } + + inflater.setInput(b, 0, n, false); + + byte[] b1 = new byte[1]; + do{ + if(inflater.avail_in<=0){ + int i = in.read(b1); + if(i<=0) + throw new IOException("no input"); + inflater.setInput(b1, 0, 1, true); + } + + int err = inflater.inflate(JZlib.Z_NO_FLUSH); + + if(err!=0/*Z_OK*/){ + int len = 2048-inflater.next_in.length; + if(len>0){ + byte[] tmp = new byte[len]; + n = fill(tmp); + if(n>0){ + inflater.avail_in += inflater.next_in_index; + inflater.next_in_index = 0; + inflater.setInput(tmp, 0, n, true); + } + } + //inflater.next_in_index = inflater.next_in.length; + inflater.avail_in += inflater.next_in_index; + inflater.next_in_index = 0; + throw new IOException(inflater.msg); + } + } + while(inflater.istate.inParsingHeader()); + } + + private int fill(byte[] buf) { + int len = buf.length; + int n = 0; + do{ + int i = -1; + try { + i = in.read(buf, n, buf.length - n); + } + catch(IOException e){ + } + if(i == -1){ + break; + } + n+=i; + } + while(n>> 1){ + case 0: // stored + {b>>>=(3);k-=(3);} + t = k & 7; // go to byte boundary + + {b>>>=(t);k-=(t);} + mode = LENS; // get length of stored block + break; + case 1: // fixed + InfTree.inflate_trees_fixed(bl, bd, tl, td, z); + codes.init(bl[0], bd[0], tl[0], 0, td[0], 0); + + {b>>>=(3);k-=(3);} + + mode = CODES; + break; + case 2: // dynamic + + {b>>>=(3);k-=(3);} + + mode = TABLE; + break; + case 3: // illegal + + {b>>>=(3);k-=(3);} + mode = BAD; + z.msg = "invalid block type"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + break; + case LENS: + + while(k<(32)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>> 16) & 0xffff) != (b & 0xffff)){ + mode = BAD; + z.msg = "invalid stored block lengths"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + left = (b & 0xffff); + b = k = 0; // dump bits + mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE); + break; + case STORED: + if (n == 0){ + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + + if(m==0){ + if(q==end&&read!=0){ + q=0; m=(int)(qn) t = n; + if(t>m) t = m; + System.arraycopy(z.next_in, p, window, q, t); + p += t; n -= t; + q += t; m -= t; + if ((left -= t) != 0) + break; + mode = last!=0 ? DRY : TYPE; + break; + case TABLE: + + while(k<(14)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)< 29 || ((t >> 5) & 0x1f) > 29) + { + mode = BAD; + z.msg = "too many length or distance symbols"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if(blens==null || blens.length>>=(14);k-=(14);} + + index = 0; + mode = BTREE; + case BTREE: + while (index < 4 + (table >>> 10)){ + while(k<(3)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>>=(3);k-=(3);} + } + + while(index < 19){ + blens[border[index++]] = 0; + } + + bb[0] = 7; + t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z); + if (t != Z_OK){ + r = t; + if (r == Z_DATA_ERROR){ + blens=null; + mode = BAD; + } + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + + index = 0; + mode = DTREE; + case DTREE: + while (true){ + t = table; + if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){ + break; + } + + int[] h; + int i, j, c; + + t = bb[0]; + + while(k<(t)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>>=(t);k-=(t); + blens[index++] = c; + } + else { // c == 16..18 + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + + while(k<(t+i)){ + if(n!=0){ + r=Z_OK; + } + else{ + bitb=b; bitk=k; + z.avail_in=n; + z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + }; + n--; + b|=(z.next_in[p++]&0xff)<>>=(t);k-=(t); + + j += (b & inflate_mask[i]); + + b>>>=(i);k-=(i); + + i = index; + t = table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)){ + blens=null; + mode = BAD; + z.msg = "invalid bit length repeat"; + r = Z_DATA_ERROR; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + + c = c == 16 ? blens[i-1] : 0; + do{ + blens[i++] = c; + } + while (--j!=0); + index = i; + } + } + + tb[0]=-1; + { + bl[0] = 9; // must be <= 9 for lookahead assumptions + bd[0] = 6; // must be <= 9 for lookahead assumptions + t = table; + t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), + 1 + ((t >> 5) & 0x1f), + blens, bl, bd, tli, tdi, hufts, z); + + if (t != Z_OK){ + if (t == Z_DATA_ERROR){ + blens=null; + mode = BAD; + } + r = t; + + bitb=b; bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + return inflate_flush(r); + } + codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]); + } + mode = CODES; + case CODES: + bitb=b; bitk=k; + z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; + write=q; + + if ((r = codes.proc(r)) != Z_STREAM_END){ + return inflate_flush(r); + } + r = Z_OK; + codes.free(z); + + p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk; + q=write;m=(int)(q z.avail_out) n = z.avail_out; + if(n!=0 && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if(check && n>0){ + z.adler.update(window, q, n); + } + + // copy as far as end of window + System.arraycopy(window, q, z.next_out, p, n); + p += n; + q += n; + + // see if more to copy at beginning of window + if (q == end){ + // wrap pointers + q = 0; + if (write == end) + write = 0; + + // compute bytes to copy + n = write - q; + if (n > z.avail_out) n = z.avail_out; + if (n!=0 && r == Z_BUF_ERROR) r = Z_OK; + + // update counters + z.avail_out -= n; + z.total_out += n; + + // update check information + if(check && n>0){ + z.adler.update(window, q, n); + } + + // copy + System.arraycopy(window, q, z.next_out, p, n); + p += n; + q += n; + } + + // update pointers + z.next_out_index = p; + read = q; + + // done + return r; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/InfCodes.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/InfCodes.java new file mode 100644 index 00000000..aaf69cd4 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/InfCodes.java @@ -0,0 +1,610 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class InfCodes{ + + static final private int[] inflate_mask = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f, + 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff, + 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff, + 0x00007fff, 0x0000ffff + }; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + // waiting for "i:"=input, + // "o:"=output, + // "x:"=nothing + static final private int START=0; // x: set up for LEN + static final private int LEN=1; // i: get length/literal/eob next + static final private int LENEXT=2; // i: getting length extra (have base) + static final private int DIST=3; // i: get distance next + static final private int DISTEXT=4;// i: getting distance extra + static final private int COPY=5; // o: copying bytes in window, waiting for space + static final private int LIT=6; // o: got literal, waiting for output space + static final private int WASH=7; // o: got eob, possibly still output waiting + static final private int END=8; // x: got eob and all data flushed + static final private int BADCODE=9;// x: got error + + int mode; // current inflate_codes mode + + // mode dependent information + int len; + + int[] tree; // pointer into tree + int tree_index=0; + int need; // bits needed + + int lit; + + // if EXT or COPY, where and how much + int get; // bits to get for extra + int dist; // distance back to copy from + + byte lbits; // ltree bits decoded per branch + byte dbits; // dtree bits decoder per branch + int[] ltree; // literal/length/eob tree + int ltree_index; // literal/length/eob tree + int[] dtree; // distance tree + int dtree_index; // distance tree + + private final ZStream z; + private final InfBlocks s; + InfCodes(ZStream z, InfBlocks s){ + this.z=z; + this.s=s; + } + + void init(int bl, int bd, + int[] tl, int tl_index, + int[] td, int td_index){ + mode=START; + lbits=(byte)bl; + dbits=(byte)bd; + ltree=tl; + ltree_index=tl_index; + dtree = td; + dtree_index=td_index; + tree=null; + } + + int proc(int r){ + int j; // temporary storage + int[] t; // temporary pointer + int tindex; // temporary pointer + int e; // extra bits or operation + int b=0; // bit buffer + int k=0; // bits in bit buffer + int p=0; // input data pointer + int n; // bytes available there + int q; // output window write pointer + int m; // bytes to end of window or read pointer + int f; // pointer to copy strings from + + // copy input/output information to locals (UPDATE macro restores) + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; + q=s.write;m=q= 258 && n >= 10){ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + r = inflate_fast(lbits, dbits, + ltree, ltree_index, + dtree, dtree_index, + s, z); + + p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk; + q=s.write;m=q>>=(tree[tindex+1]); + k-=(tree[tindex+1]); + + e=tree[tindex]; + + if(e == 0){ // literal + lit = tree[tindex+2]; + mode = LIT; + break; + } + if((e & 16)!=0 ){ // length + get = e & 15; + len = tree[tindex+2]; + mode = LENEXT; + break; + } + if ((e & 64) == 0){ // next table + need = e; + tree_index = tindex/3+tree[tindex+2]; + break; + } + if ((e & 32)!=0){ // end of block + mode = WASH; + break; + } + mode = BADCODE; // invalid code + z.msg = "invalid literal/length code"; + r = Z_DATA_ERROR; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + + case LENEXT: // i: getting length extra (have base) + j = get; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + n--; b|=(z.next_in[p++]&0xff)<>=j; + k-=j; + + need = dbits; + tree = dtree; + tree_index=dtree_index; + mode = DIST; + case DIST: // i: get distance next + j = need; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + n--; b|=(z.next_in[p++]&0xff)<>=tree[tindex+1]; + k-=tree[tindex+1]; + + e = (tree[tindex]); + if((e & 16)!=0){ // distance + get = e & 15; + dist = tree[tindex+2]; + mode = DISTEXT; + break; + } + if ((e & 64) == 0){ // next table + need = e; + tree_index = tindex/3 + tree[tindex+2]; + break; + } + mode = BADCODE; // invalid code + z.msg = "invalid distance code"; + r = Z_DATA_ERROR; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + + case DISTEXT: // i: getting distance extra + j = get; + + while(k<(j)){ + if(n!=0)r=Z_OK; + else{ + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + return s.inflate_flush(r); + } + n--; b|=(z.next_in[p++]&0xff)<>=j; + k-=j; + + mode = COPY; + case COPY: // o: copying bytes in window, waiting for space + f = q - dist; + while(f < 0){ // modulo window size-"while" instead + f += s.end; // of "if" handles invalid distances + } + while (len!=0){ + + if(m==0){ + if(q==s.end&&s.read!=0){q=0;m=q 7){ // return unused byte, if any + k -= 8; + n++; + p--; // can always return one + } + + s.write=q; r=s.inflate_flush(r); + q=s.write;m=q= 258 && n >= 10 + // get literal/length code + while(k<(20)){ // max bits for literal/length code + n--; + b|=(z.next_in[p++]&0xff)<>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + s.window[q++] = (byte)tp[tp_index_t_3+2]; + m--; + continue; + } + do { + + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + if((e&16)!=0){ + e &= 15; + c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]); + + b>>=e; k-=e; + + // decode distance base of block to copy + while(k<(15)){ // max bits for distance code + n--; + b|=(z.next_in[p++]&0xff)<>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + if((e&16)!=0){ + // get extra bits to add to distance base + e &= 15; + while(k<(e)){ // get extra bits (up to 13) + n--; + b|=(z.next_in[p++]&0xff)<>=(e); k-=(e); + + // do the copy + m -= c; + if (q >= d){ // offset before dest + // just copy + r=q-d; + if(q-r>0 && 2>(q-r)){ + s.window[q++]=s.window[r++]; // minimum count is three, + s.window[q++]=s.window[r++]; // so unroll loop a little + c-=2; + } + else{ + System.arraycopy(s.window, r, s.window, q, 2); + q+=2; r+=2; c-=2; + } + } + else{ // else offset after destination + r=q-d; + do{ + r+=s.end; // force pointer in window + }while(r<0); // covers invalid distances + e=s.end-r; + if(c>e){ // if source crosses, + c-=e; // wrapped copy + if(q-r>0 && e>(q-r)){ + do{s.window[q++] = s.window[r++];} + while(--e!=0); + } + else{ + System.arraycopy(s.window, r, s.window, q, e); + q+=e; r+=e; e=0; + } + r = 0; // copy rest from start of window + } + + } + + // copy all or what's left + if(q-r>0 && c>(q-r)){ + do{s.window[q++] = s.window[r++];} + while(--c!=0); + } + else{ + System.arraycopy(s.window, r, s.window, q, c); + q+=c; r+=c; c=0; + } + break; + } + else if((e&64)==0){ + t+=tp[tp_index_t_3+2]; + t+=(b&inflate_mask[e]); + tp_index_t_3=(tp_index+t)*3; + e=tp[tp_index_t_3]; + } + else{ + z.msg = "invalid distance code"; + + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_DATA_ERROR; + } + } + while(true); + break; + } + + if((e&64)==0){ + t+=tp[tp_index_t_3+2]; + t+=(b&inflate_mask[e]); + tp_index_t_3=(tp_index+t)*3; + if((e=tp[tp_index_t_3])==0){ + + b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]); + + s.window[q++]=(byte)tp[tp_index_t_3+2]; + m--; + break; + } + } + else if((e&32)!=0){ + + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_STREAM_END; + } + else{ + z.msg="invalid literal/length code"; + + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_DATA_ERROR; + } + } + while(true); + } + while(m>=258 && n>= 10); + + // not enough input or output--restore pointers and return + c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3; + + s.bitb=b;s.bitk=k; + z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; + s.write=q; + + return Z_OK; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/InfTree.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/InfTree.java new file mode 100644 index 00000000..80a2b7b6 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/InfTree.java @@ -0,0 +1,518 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class InfTree{ + + static final private int MANY=1440; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + static final int fixed_bl = 9; + static final int fixed_bd = 5; + + static final int[] fixed_tl = { + 96,7,256, 0,8,80, 0,8,16, 84,8,115, + 82,7,31, 0,8,112, 0,8,48, 0,9,192, + 80,7,10, 0,8,96, 0,8,32, 0,9,160, + 0,8,0, 0,8,128, 0,8,64, 0,9,224, + 80,7,6, 0,8,88, 0,8,24, 0,9,144, + 83,7,59, 0,8,120, 0,8,56, 0,9,208, + 81,7,17, 0,8,104, 0,8,40, 0,9,176, + 0,8,8, 0,8,136, 0,8,72, 0,9,240, + 80,7,4, 0,8,84, 0,8,20, 85,8,227, + 83,7,43, 0,8,116, 0,8,52, 0,9,200, + 81,7,13, 0,8,100, 0,8,36, 0,9,168, + 0,8,4, 0,8,132, 0,8,68, 0,9,232, + 80,7,8, 0,8,92, 0,8,28, 0,9,152, + 84,7,83, 0,8,124, 0,8,60, 0,9,216, + 82,7,23, 0,8,108, 0,8,44, 0,9,184, + 0,8,12, 0,8,140, 0,8,76, 0,9,248, + 80,7,3, 0,8,82, 0,8,18, 85,8,163, + 83,7,35, 0,8,114, 0,8,50, 0,9,196, + 81,7,11, 0,8,98, 0,8,34, 0,9,164, + 0,8,2, 0,8,130, 0,8,66, 0,9,228, + 80,7,7, 0,8,90, 0,8,26, 0,9,148, + 84,7,67, 0,8,122, 0,8,58, 0,9,212, + 82,7,19, 0,8,106, 0,8,42, 0,9,180, + 0,8,10, 0,8,138, 0,8,74, 0,9,244, + 80,7,5, 0,8,86, 0,8,22, 192,8,0, + 83,7,51, 0,8,118, 0,8,54, 0,9,204, + 81,7,15, 0,8,102, 0,8,38, 0,9,172, + 0,8,6, 0,8,134, 0,8,70, 0,9,236, + 80,7,9, 0,8,94, 0,8,30, 0,9,156, + 84,7,99, 0,8,126, 0,8,62, 0,9,220, + 82,7,27, 0,8,110, 0,8,46, 0,9,188, + 0,8,14, 0,8,142, 0,8,78, 0,9,252, + 96,7,256, 0,8,81, 0,8,17, 85,8,131, + 82,7,31, 0,8,113, 0,8,49, 0,9,194, + 80,7,10, 0,8,97, 0,8,33, 0,9,162, + 0,8,1, 0,8,129, 0,8,65, 0,9,226, + 80,7,6, 0,8,89, 0,8,25, 0,9,146, + 83,7,59, 0,8,121, 0,8,57, 0,9,210, + 81,7,17, 0,8,105, 0,8,41, 0,9,178, + 0,8,9, 0,8,137, 0,8,73, 0,9,242, + 80,7,4, 0,8,85, 0,8,21, 80,8,258, + 83,7,43, 0,8,117, 0,8,53, 0,9,202, + 81,7,13, 0,8,101, 0,8,37, 0,9,170, + 0,8,5, 0,8,133, 0,8,69, 0,9,234, + 80,7,8, 0,8,93, 0,8,29, 0,9,154, + 84,7,83, 0,8,125, 0,8,61, 0,9,218, + 82,7,23, 0,8,109, 0,8,45, 0,9,186, + 0,8,13, 0,8,141, 0,8,77, 0,9,250, + 80,7,3, 0,8,83, 0,8,19, 85,8,195, + 83,7,35, 0,8,115, 0,8,51, 0,9,198, + 81,7,11, 0,8,99, 0,8,35, 0,9,166, + 0,8,3, 0,8,131, 0,8,67, 0,9,230, + 80,7,7, 0,8,91, 0,8,27, 0,9,150, + 84,7,67, 0,8,123, 0,8,59, 0,9,214, + 82,7,19, 0,8,107, 0,8,43, 0,9,182, + 0,8,11, 0,8,139, 0,8,75, 0,9,246, + 80,7,5, 0,8,87, 0,8,23, 192,8,0, + 83,7,51, 0,8,119, 0,8,55, 0,9,206, + 81,7,15, 0,8,103, 0,8,39, 0,9,174, + 0,8,7, 0,8,135, 0,8,71, 0,9,238, + 80,7,9, 0,8,95, 0,8,31, 0,9,158, + 84,7,99, 0,8,127, 0,8,63, 0,9,222, + 82,7,27, 0,8,111, 0,8,47, 0,9,190, + 0,8,15, 0,8,143, 0,8,79, 0,9,254, + 96,7,256, 0,8,80, 0,8,16, 84,8,115, + 82,7,31, 0,8,112, 0,8,48, 0,9,193, + + 80,7,10, 0,8,96, 0,8,32, 0,9,161, + 0,8,0, 0,8,128, 0,8,64, 0,9,225, + 80,7,6, 0,8,88, 0,8,24, 0,9,145, + 83,7,59, 0,8,120, 0,8,56, 0,9,209, + 81,7,17, 0,8,104, 0,8,40, 0,9,177, + 0,8,8, 0,8,136, 0,8,72, 0,9,241, + 80,7,4, 0,8,84, 0,8,20, 85,8,227, + 83,7,43, 0,8,116, 0,8,52, 0,9,201, + 81,7,13, 0,8,100, 0,8,36, 0,9,169, + 0,8,4, 0,8,132, 0,8,68, 0,9,233, + 80,7,8, 0,8,92, 0,8,28, 0,9,153, + 84,7,83, 0,8,124, 0,8,60, 0,9,217, + 82,7,23, 0,8,108, 0,8,44, 0,9,185, + 0,8,12, 0,8,140, 0,8,76, 0,9,249, + 80,7,3, 0,8,82, 0,8,18, 85,8,163, + 83,7,35, 0,8,114, 0,8,50, 0,9,197, + 81,7,11, 0,8,98, 0,8,34, 0,9,165, + 0,8,2, 0,8,130, 0,8,66, 0,9,229, + 80,7,7, 0,8,90, 0,8,26, 0,9,149, + 84,7,67, 0,8,122, 0,8,58, 0,9,213, + 82,7,19, 0,8,106, 0,8,42, 0,9,181, + 0,8,10, 0,8,138, 0,8,74, 0,9,245, + 80,7,5, 0,8,86, 0,8,22, 192,8,0, + 83,7,51, 0,8,118, 0,8,54, 0,9,205, + 81,7,15, 0,8,102, 0,8,38, 0,9,173, + 0,8,6, 0,8,134, 0,8,70, 0,9,237, + 80,7,9, 0,8,94, 0,8,30, 0,9,157, + 84,7,99, 0,8,126, 0,8,62, 0,9,221, + 82,7,27, 0,8,110, 0,8,46, 0,9,189, + 0,8,14, 0,8,142, 0,8,78, 0,9,253, + 96,7,256, 0,8,81, 0,8,17, 85,8,131, + 82,7,31, 0,8,113, 0,8,49, 0,9,195, + 80,7,10, 0,8,97, 0,8,33, 0,9,163, + 0,8,1, 0,8,129, 0,8,65, 0,9,227, + 80,7,6, 0,8,89, 0,8,25, 0,9,147, + 83,7,59, 0,8,121, 0,8,57, 0,9,211, + 81,7,17, 0,8,105, 0,8,41, 0,9,179, + 0,8,9, 0,8,137, 0,8,73, 0,9,243, + 80,7,4, 0,8,85, 0,8,21, 80,8,258, + 83,7,43, 0,8,117, 0,8,53, 0,9,203, + 81,7,13, 0,8,101, 0,8,37, 0,9,171, + 0,8,5, 0,8,133, 0,8,69, 0,9,235, + 80,7,8, 0,8,93, 0,8,29, 0,9,155, + 84,7,83, 0,8,125, 0,8,61, 0,9,219, + 82,7,23, 0,8,109, 0,8,45, 0,9,187, + 0,8,13, 0,8,141, 0,8,77, 0,9,251, + 80,7,3, 0,8,83, 0,8,19, 85,8,195, + 83,7,35, 0,8,115, 0,8,51, 0,9,199, + 81,7,11, 0,8,99, 0,8,35, 0,9,167, + 0,8,3, 0,8,131, 0,8,67, 0,9,231, + 80,7,7, 0,8,91, 0,8,27, 0,9,151, + 84,7,67, 0,8,123, 0,8,59, 0,9,215, + 82,7,19, 0,8,107, 0,8,43, 0,9,183, + 0,8,11, 0,8,139, 0,8,75, 0,9,247, + 80,7,5, 0,8,87, 0,8,23, 192,8,0, + 83,7,51, 0,8,119, 0,8,55, 0,9,207, + 81,7,15, 0,8,103, 0,8,39, 0,9,175, + 0,8,7, 0,8,135, 0,8,71, 0,9,239, + 80,7,9, 0,8,95, 0,8,31, 0,9,159, + 84,7,99, 0,8,127, 0,8,63, 0,9,223, + 82,7,27, 0,8,111, 0,8,47, 0,9,191, + 0,8,15, 0,8,143, 0,8,79, 0,9,255 + }; + static final int[] fixed_td = { + 80,5,1, 87,5,257, 83,5,17, 91,5,4097, + 81,5,5, 89,5,1025, 85,5,65, 93,5,16385, + 80,5,3, 88,5,513, 84,5,33, 92,5,8193, + 82,5,9, 90,5,2049, 86,5,129, 192,5,24577, + 80,5,2, 87,5,385, 83,5,25, 91,5,6145, + 81,5,7, 89,5,1537, 85,5,97, 93,5,24577, + 80,5,4, 88,5,769, 84,5,49, 92,5,12289, + 82,5,13, 90,5,3073, 86,5,193, 192,5,24577 + }; + + // Tables for deflate from PKZIP's appnote.txt. + static final int[] cplens = { // Copy lengths for literal codes 257..285 + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 + }; + + // see note #13 above about 258 + static final int[] cplext = { // Extra bits for literal codes 257..285 + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid + }; + + static final int[] cpdist = { // Copy offsets for distance codes 0..29 + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577 + }; + + static final int[] cpdext = { // Extra bits for distance codes + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + // If BMAX needs to be larger than 16, then h and x[] should be uLong. + static final int BMAX=15; // maximum bit length of any code + + int[] hn = null; // hufts used in space + int[] v = null; // work area for huft_build + int[] c = null; // bit length count table + int[] r = null; // table entry for structure assignment + int[] u = null; // table stack + int[] x = null; // bit offsets, then code stack + + private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX) + int bindex, + int n, // number of codes (assumed <= 288) + int s, // number of simple-valued codes (0..s-1) + int[] d, // list of base values for non-simple codes + int[] e, // list of extra bits for non-simple codes + int[] t, // result: starting table + int[] m, // maximum lookup bits, returns actual + int[] hp,// space for trees + int[] hn,// hufts used in space + int[] v // working area: values in order of bit length + ){ + // Given a list of code lengths and a maximum table size, make a set of + // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + // if the given code set is incomplete (the tables are still built in this + // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of + // lengths), or Z_MEM_ERROR if not enough memory. + + int a; // counter for codes of length k + int f; // i repeats in table every f entries + int g; // maximum code length + int h; // table level + int i; // counter, current code + int j; // counter + int k; // number of bits in current code + int l; // bits per table (returned in m) + int mask; // (1 << w) - 1, to avoid cc -O bug on HP + int p; // pointer into c[], b[], or v[] + int q; // points to current table + int w; // bits before this table == (l * h) + int xp; // pointer into x + int y; // number of dummy codes added + int z; // number of entries in current table + + // Generate counts for each bit length + + p = 0; i = n; + do { + c[b[bindex+p]]++; p++; i--; // assume all entries <= BMAX + }while(i!=0); + + if(c[0] == n){ // null input--all zero length codes + t[0] = -1; + m[0] = 0; + return Z_OK; + } + + // Find minimum and maximum length, bound *m by those + l = m[0]; + for (j = 1; j <= BMAX; j++) + if(c[j]!=0) break; + k = j; // minimum code length + if(l < j){ + l = j; + } + for (i = BMAX; i!=0; i--){ + if(c[i]!=0) break; + } + g = i; // maximum code length + if(l > i){ + l = i; + } + m[0] = l; + + // Adjust last length count to fill out codes, if needed + for (y = 1 << j; j < i; j++, y <<= 1){ + if ((y -= c[j]) < 0){ + return Z_DATA_ERROR; + } + } + if ((y -= c[i]) < 0){ + return Z_DATA_ERROR; + } + c[i] += y; + + // Generate starting offsets into the value table for each length + x[1] = j = 0; + p = 1; xp = 2; + while (--i!=0) { // note that i == g from above + x[xp] = (j += c[p]); + xp++; + p++; + } + + // Make a table of values in order of bit lengths + i = 0; p = 0; + do { + if ((j = b[bindex+p]) != 0){ + v[x[j]++] = i; + } + p++; + } + while (++i < n); + n = x[g]; // set n to length of v + + // Generate the Huffman codes and for each, make the table entries + x[0] = i = 0; // first Huffman code is zero + p = 0; // grab values in bit order + h = -1; // no tables yet--level -1 + w = -l; // bits decoded == (l * h) + u[0] = 0; // just to keep compilers happy + q = 0; // ditto + z = 0; // ditto + + // go through the bit lengths (k already is bits in shortest code) + for (; k <= g; k++){ + a = c[k]; + while (a--!=0){ + // here i is the Huffman code of length k bits for value *p + // make tables up to required level + while (k > w + l){ + h++; + w += l; // previous table always l bits + // compute minimum size table less than or equal to l bits + z = g - w; + z = (z > l) ? l : z; // table size upper limit + if((f=1<<(j=k-w))>a+1){ // try a k-w bit table + // too few codes for k-w bit table + f -= a + 1; // deduct codes from patterns left + xp = k; + if(j < z){ + while (++j < z){ // try smaller tables up to z bits + if((f <<= 1) <= c[++xp]) + break; // enough codes to use up j bits + f -= c[xp]; // else deduct codes from patterns + } + } + } + z = 1 << j; // table entries for j-bit table + + // allocate new table + if (hn[0] + z > MANY){ // (note: doesn't matter for fixed) + return Z_DATA_ERROR; // overflow of MANY + } + u[h] = q = /*hp+*/ hn[0]; // DEBUG + hn[0] += z; + + // connect to last table, if there is one + if(h!=0){ + x[h]=i; // save pattern for backing up + r[0]=(byte)j; // bits in this table + r[1]=(byte)l; // bits to dump before this table + j=i>>>(w - l); + r[2] = (int)(q - u[h-1] - j); // offset to this table + System.arraycopy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table + } + else{ + t[0] = q; // first table is returned result + } + } + + // set up table entry in r + r[1] = (byte)(k - w); + if (p >= n){ + r[0] = 128 + 64; // out of values--invalid code + } + else if (v[p] < s){ + r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block + r[2] = v[p++]; // simple code is just the value + } + else{ + r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists + r[2]=d[v[p++] - s]; + } + + // fill code-like entries with r + f=1<<(k-w); + for (j=i>>>w;j>>= 1){ + i ^= j; + } + i ^= j; + + // backup over finished tables + mask = (1 << w) - 1; // needed on HP, cc -O bug + while ((i & mask) != x[h]){ + h--; // don't need to update q + w -= l; + mask = (1 << w) - 1; + } + } + } + // Return Z_BUF_ERROR if we were given an incomplete table + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; + } + + int inflate_trees_bits(int[] c, // 19 code lengths + int[] bb, // bits tree desired/actual depth + int[] tb, // bits tree result + int[] hp, // space for trees + ZStream z // for messages + ){ + int result; + initWorkArea(19); + hn[0]=0; + result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); + + if(result == Z_DATA_ERROR){ + z.msg = "oversubscribed dynamic bit lengths tree"; + } + else if(result == Z_BUF_ERROR || bb[0] == 0){ + z.msg = "incomplete dynamic bit lengths tree"; + result = Z_DATA_ERROR; + } + return result; + } + + int inflate_trees_dynamic(int nl, // number of literal/length codes + int nd, // number of distance codes + int[] c, // that many (total) code lengths + int[] bl, // literal desired/actual bit depth + int[] bd, // distance desired/actual bit depth + int[] tl, // literal/length tree result + int[] td, // distance tree result + int[] hp, // space for trees + ZStream z // for messages + ){ + int result; + + // build literal/length tree + initWorkArea(288); + hn[0]=0; + result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v); + if (result != Z_OK || bl[0] == 0){ + if(result == Z_DATA_ERROR){ + z.msg = "oversubscribed literal/length tree"; + } + else if (result != Z_MEM_ERROR){ + z.msg = "incomplete literal/length tree"; + result = Z_DATA_ERROR; + } + return result; + } + + // build distance tree + initWorkArea(288); + result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v); + + if (result != Z_OK || (bd[0] == 0 && nl > 257)){ + if (result == Z_DATA_ERROR){ + z.msg = "oversubscribed distance tree"; + } + else if (result == Z_BUF_ERROR) { + z.msg = "incomplete distance tree"; + result = Z_DATA_ERROR; + } + else if (result != Z_MEM_ERROR){ + z.msg = "empty distance tree with lengths"; + result = Z_DATA_ERROR; + } + return result; + } + + return Z_OK; + } + + static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth + int[] bd, //distance desired/actual bit depth + int[][] tl,//literal/length tree result + int[][] td,//distance tree result + ZStream z //for memory allocation + ){ + bl[0]=fixed_bl; + bd[0]=fixed_bd; + tl[0]=fixed_tl; + td[0]=fixed_td; + return Z_OK; + } + + private void initWorkArea(int vsize){ + if(hn==null){ + hn=new int[1]; + v=new int[vsize]; + c=new int[BMAX+1]; + r=new int[3]; + u=new int[BMAX]; + x=new int[BMAX+1]; + } + if(v.length> 4) + 1; + if(w < 48) + w &= 15; + } + + if(w<8 ||w>15){ + inflateEnd(); + return Z_STREAM_ERROR; + } + if(blocks != null && wbits != w){ + blocks.free(); + blocks=null; + } + + // set window size + wbits=w; + + this.blocks=new InfBlocks(z, 1<>8))&0xff; + + if(((wrap&1)==0 || // check if zlib header allowed + (((this.method << 8)+b) % 31)!=0) && + (this.method&0xf)!=Z_DEFLATED){ + if(wrap == 4){ + z.next_in_index -= 2; + z.avail_in += 2; + z.total_in -= 2; + wrap = 0; + this.mode = BLOCKS; + break; + } + this.mode = BAD; + z.msg = "incorrect header check"; + // since zlib 1.2, it is allowted to inflateSync for this case. + /* + this.marker = 5; // can't try inflateSync + */ + break; + } + + if((this.method&0xf)!=Z_DEFLATED){ + this.mode = BAD; + z.msg="unknown compression method"; + // since zlib 1.2, it is allowted to inflateSync for this case. + /* + this.marker = 5; // can't try inflateSync + */ + break; + } + + if(wrap == 4){ + wrap = 1; + } + + if((this.method>>4)+8>this.wbits){ + this.mode = BAD; + z.msg="invalid window size"; + // since zlib 1.2, it is allowted to inflateSync for this case. + /* + this.marker = 5; // can't try inflateSync + */ + break; + } + + z.adler=new Adler32(); + + if((b&PRESET_DICT)==0){ + this.mode = BLOCKS; + break; + } + this.mode = DICT4; + case DICT4: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; + this.mode=DICT3; + case DICT3: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; + this.mode=DICT2; + case DICT2: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; + this.mode=DICT1; + case DICT1: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need += (z.next_in[z.next_in_index++]&0xffL); + z.adler.reset(this.need); + this.mode = DICT0; + return Z_NEED_DICT; + case DICT0: + this.mode = BAD; + z.msg = "need dictionary"; + this.marker = 0; // can try inflateSync + return Z_STREAM_ERROR; + case BLOCKS: + r = this.blocks.proc(r); + if(r == Z_DATA_ERROR){ + this.mode = BAD; + this.marker = 0; // can try inflateSync + break; + } + if(r == Z_OK){ + r = f; + } + if(r != Z_STREAM_END){ + return r; + } + r = f; + this.was=z.adler.getValue(); + this.blocks.reset(); + if(this.wrap==0){ + this.mode=DONE; + break; + } + this.mode=CHECK4; + case CHECK4: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; + this.mode=CHECK3; + case CHECK3: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; + this.mode = CHECK2; + case CHECK2: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; + this.mode = CHECK1; + case CHECK1: + + if(z.avail_in==0)return r;r=f; + + z.avail_in--; z.total_in++; + this.need+=(z.next_in[z.next_in_index++]&0xffL); + + if(flags!=0){ // gzip + this.need = ((this.need&0xff000000)>>24 | + (this.need&0x00ff0000)>>8 | + (this.need&0x0000ff00)<<8 | + (this.need&0x0000ffff)<<24)&0xffffffffL; + } + + if(((int)(this.was)) != ((int)(this.need))){ + z.msg = "incorrect data check"; + // chack is delayed + /* + this.mode = BAD; + this.marker = 5; // can't try inflateSync + break; + */ + } + else if(flags!=0 && gheader!=null){ + gheader.crc = this.need; + } + + this.mode = LENGTH; + case LENGTH: + if (wrap!=0 && flags!=0) { + + try { r=readBytes(4, r, f); } + catch(Return e){ return e.r; } + + if(z.msg!=null && z.msg.equals("incorrect data check")){ + this.mode = BAD; + this.marker = 5; // can't try inflateSync + break; + } + + if (this.need != (z.total_out & 0xffffffffL)) { + z.msg = "incorrect length check"; + this.mode = BAD; + break; + } + z.msg = null; + } + else { + if(z.msg!=null && z.msg.equals("incorrect data check")){ + this.mode = BAD; + this.marker = 5; // can't try inflateSync + break; + } + } + + this.mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + + case FLAGS: + + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + + flags = ((int)this.need)&0xffff; + + if ((flags & 0xff) != Z_DEFLATED) { + z.msg = "unknown compression method"; + this.mode = BAD; + break; + } + if ((flags & 0xe000)!=0) { + z.msg = "unknown header flags set"; + this.mode = BAD; + break; + } + + if ((flags & 0x0200)!=0){ + checksum(2, this.need); + } + + this.mode = TIME; + + case TIME: + try { r=readBytes(4, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null) + gheader.time = this.need; + if ((flags & 0x0200)!=0){ + checksum(4, this.need); + } + this.mode = OS; + case OS: + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null){ + gheader.xflags = ((int)this.need)&0xff; + gheader.os = (((int)this.need)>>8)&0xff; + } + if ((flags & 0x0200)!=0){ + checksum(2, this.need); + } + this.mode = EXLEN; + case EXLEN: + if ((flags & 0x0400)!=0) { + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null){ + gheader.extra = new byte[((int)this.need)&0xffff]; + } + if ((flags & 0x0200)!=0){ + checksum(2, this.need); + } + } + else if(gheader!=null){ + gheader.extra=null; + } + this.mode = EXTRA; + + case EXTRA: + if ((flags & 0x0400)!=0) { + try { + r=readBytes(r, f); + if(gheader!=null){ + byte[] foo = tmp_string.toByteArray(); + tmp_string=null; + if(foo.length == gheader.extra.length){ + System.arraycopy(foo, 0, gheader.extra, 0, foo.length); + } + else{ + z.msg = "bad extra field length"; + this.mode = BAD; + break; + } + } + } + catch(Return e){ return e.r; } + } + else if(gheader!=null){ + gheader.extra=null; + } + this.mode = NAME; + case NAME: + if ((flags & 0x0800)!=0) { + try { + r=readString(r, f); + if(gheader!=null){ + gheader.name=tmp_string.toByteArray(); + } + tmp_string=null; + } + catch(Return e){ return e.r; } + } + else if(gheader!=null){ + gheader.name=null; + } + this.mode = COMMENT; + case COMMENT: + if ((flags & 0x1000)!=0) { + try { + r=readString(r, f); + if(gheader!=null){ + gheader.comment=tmp_string.toByteArray(); + } + tmp_string=null; + } + catch(Return e){ return e.r; } + } + else if(gheader!=null){ + gheader.comment=null; + } + this.mode = HCRC; + case HCRC: + if ((flags & 0x0200)!=0) { + try { r=readBytes(2, r, f); } + catch(Return e){ return e.r; } + if(gheader!=null){ + gheader.hcrc=(int)(this.need&0xffff); + } + if(this.need != (z.adler.getValue()&0xffffL)){ + this.mode = BAD; + z.msg = "header crc mismatch"; + this.marker = 5; // can't try inflateSync + break; + } + } + z.adler = new CRC32(); + + this.mode = BLOCKS; + break; + default: + return Z_STREAM_ERROR; + } + } + } + + int inflateSetDictionary(byte[] dictionary, int dictLength){ + if(z==null || (this.mode != DICT0 && this.wrap != 0)){ + return Z_STREAM_ERROR; + } + + int index=0; + int length = dictLength; + + if(this.mode==DICT0){ + long adler_need=z.adler.getValue(); + z.adler.reset(); + z.adler.update(dictionary, 0, dictLength); + if(z.adler.getValue()!=adler_need){ + return Z_DATA_ERROR; + } + } + + z.adler.reset(); + + if(length >= (1<0){ + if(z.avail_in==0){ throw new Return(r); }; r=f; + z.avail_in--; z.total_in++; + this.need = this.need | + ((z.next_in[z.next_in_index++]&0xff)<<((n-need_bytes)*8)); + need_bytes--; + } + if(n==2){ + this.need&=0xffffL; + } + else if(n==4) { + this.need&=0xffffffffL; + } + need_bytes=-1; + return r; + } + class Return extends Exception{ + int r; + Return(int r){this.r=r; } + } + + private java.io.ByteArrayOutputStream tmp_string = null; + private int readString(int r, int f) throws Return{ + if(tmp_string == null){ + tmp_string=new java.io.ByteArrayOutputStream(); + } + int b=0; + do { + if(z.avail_in==0){ throw new Return(r); }; r=f; + z.avail_in--; z.total_in++; + b = z.next_in[z.next_in_index]; + if(b!=0) tmp_string.write(z.next_in, z.next_in_index, 1); + z.adler.update(z.next_in, z.next_in_index, 1); + z.next_in_index++; + }while(b!=0); + return r; + } + + private int readBytes(int r, int f) throws Return{ + if(tmp_string == null){ + tmp_string=new java.io.ByteArrayOutputStream(); + } + int b=0; + while(this.need>0){ + if(z.avail_in==0){ throw new Return(r); }; r=f; + z.avail_in--; z.total_in++; + b = z.next_in[z.next_in_index]; + tmp_string.write(z.next_in, z.next_in_index, 1); + z.adler.update(z.next_in, z.next_in_index, 1); + z.next_in_index++; + this.need--; + } + return r; + } + + private void checksum(int n, long v){ + for(int i=0; i>=8; + } + z.adler.update(crcbuf, 0, n); + } + + public GZIPHeader getGZIPHeader(){ + return gheader; + } + + boolean inParsingHeader(){ + switch(mode){ + case HEAD: + case DICT4: + case DICT3: + case DICT2: + case DICT1: + case FLAGS: + case TIME: + case OS: + case EXLEN: + case EXTRA: + case NAME: + case COMMENT: + case HCRC: + return true; + default: + return false; + } + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/Inflater.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Inflater.java new file mode 100644 index 00000000..0fb0b098 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Inflater.java @@ -0,0 +1,168 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final public class Inflater extends ZStream{ + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_WBITS=MAX_WBITS; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + public Inflater() { + super(); + init(); + } + + public Inflater(JZlib.WrapperType wrapperType) throws GZIPException { + this(DEF_WBITS, wrapperType); + } + + public Inflater(int w, JZlib.WrapperType wrapperType) throws GZIPException { + super(); + int ret = init(w, wrapperType); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + public Inflater(int w) throws GZIPException { + this(w, false); + } + + public Inflater(boolean nowrap) throws GZIPException { + this(DEF_WBITS, nowrap); + } + + public Inflater(int w, boolean nowrap) throws GZIPException { + super(); + int ret = init(w, nowrap); + if(ret!=Z_OK) + throw new GZIPException(ret+": "+msg); + } + + private boolean finished = false; + + public int init(){ + return init(DEF_WBITS); + } + + public int init(JZlib.WrapperType wrapperType){ + return init(DEF_WBITS, wrapperType); + } + + public int init(int w, JZlib.WrapperType wrapperType) { + boolean nowrap = false; + if(wrapperType == JZlib.W_NONE){ + nowrap = true; + } + else if(wrapperType == JZlib.W_GZIP) { + w += 16; + } + else if(wrapperType == JZlib.W_ANY) { + w |= Inflate.INFLATE_ANY; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return init(w, nowrap); + } + + public int init(boolean nowrap){ + return init(DEF_WBITS, nowrap); + } + + public int init(int w){ + return init(w, false); + } + + public int init(int w, boolean nowrap){ + finished = false; + istate=new Inflate(this); + return istate.inflateInit(nowrap?-w:w); + } + + public int inflate(int f){ + if(istate==null) return Z_STREAM_ERROR; + int ret = istate.inflate(f); + if(ret == Z_STREAM_END) + finished = true; + return ret; + } + + public int end(){ + finished = true; + if(istate==null) return Z_STREAM_ERROR; + int ret=istate.inflateEnd(); +// istate = null; + return ret; + } + + public int sync(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSync(); + } + + public int syncPoint(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSyncPoint(); + } + + public int setDictionary(byte[] dictionary, int dictLength){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSetDictionary(dictionary, dictLength); + } + + public boolean finished(){ + return istate.mode==12 /*DONE*/; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/InflaterInputStream.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/InflaterInputStream.java new file mode 100644 index 00000000..0420582a --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/InflaterInputStream.java @@ -0,0 +1,247 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jzlib; +import java.io.*; + +public class InflaterInputStream extends FilterInputStream { + protected final Inflater inflater; + protected byte[] buf; + + private boolean closed = false; + + private boolean eof = false; + + private boolean close_in = true; + + protected static final int DEFAULT_BUFSIZE = 512; + + public InflaterInputStream(InputStream in) throws IOException { + this(in, false); + } + + public InflaterInputStream(InputStream in, boolean nowrap) throws IOException { + this(in, new Inflater(nowrap)); + myinflater = true; + } + + public InflaterInputStream(InputStream in, Inflater inflater) throws IOException { + this(in, inflater, DEFAULT_BUFSIZE); + } + + public InflaterInputStream(InputStream in, + Inflater inflater, int size) throws IOException { + this(in, inflater, size, true); + } + + public InflaterInputStream(InputStream in, + Inflater inflater, + int size, boolean close_in) throws IOException { + super(in); + if (in == null || inflater == null) { + throw new NullPointerException(); + } + else if (size <= 0) { + throw new IllegalArgumentException("buffer size must be greater than 0"); + } + this.inflater = inflater; + buf = new byte[size]; + this.close_in = close_in; + } + + protected boolean myinflater = false; + + private byte[] byte1 = new byte[1]; + + public int read() throws IOException { + if (closed) { throw new IOException("Stream closed"); } + return read(byte1, 0, 1) == -1 ? -1 : byte1[0] & 0xff; + } + + public int read(byte[] b, int off, int len) throws IOException { + if (closed) { throw new IOException("Stream closed"); } + if (b == null) { + throw new NullPointerException(); + } + else if (off < 0 || len < 0 || len > b.length - off) { + throw new IndexOutOfBoundsException(); + } + else if (len == 0) { + return 0; + } + else if (eof) { + return -1; + } + + int n = 0; + inflater.setOutput(b, off, len); + while(!eof) { + if(inflater.avail_in==0) + fill(); + int err = inflater.inflate(JZlib.Z_NO_FLUSH); + n += inflater.next_out_index - off; + off = inflater.next_out_index; + switch(err) { + case JZlib.Z_DATA_ERROR: + throw new IOException(inflater.msg); + case JZlib.Z_STREAM_END: + case JZlib.Z_NEED_DICT: + eof = true; + if(err == JZlib.Z_NEED_DICT) + return -1; + break; + default: + } + if(inflater.avail_out==0) + break; + } + return n; + } + + public int available() throws IOException { + if (closed) { throw new IOException("Stream closed"); } + if (eof) { + return 0; + } + else { + return 1; + } + } + + private byte[] b = new byte[512]; + + public long skip(long n) throws IOException { + if (n < 0) { + throw new IllegalArgumentException("negative skip length"); + } + + if (closed) { throw new IOException("Stream closed"); } + + int max = (int)Math.min(n, Integer.MAX_VALUE); + int total = 0; + while (total < max) { + int len = max - total; + if (len > b.length) { + len = b.length; + } + len = read(b, 0, len); + if (len == -1) { + eof = true; + break; + } + total += len; + } + return total; + } + + public void close() throws IOException { + if (!closed) { + if (myinflater) + inflater.end(); + if(close_in) + in.close(); + closed = true; + } + } + + protected void fill() throws IOException { + if (closed) { throw new IOException("Stream closed"); } + int len = in.read(buf, 0, buf.length); + if (len == -1) { + if(inflater.istate.wrap == 0 && + !inflater.finished()){ + buf[0]=0; + len=1; + } + else if(inflater.istate.was != -1){ // in reading trailer + throw new IOException("footer is not found"); + } + else{ + throw new EOFException("Unexpected end of ZLIB input stream"); + } + } + inflater.setInput(buf, 0, len, true); + } + + public boolean markSupported() { + return false; + } + + public synchronized void mark(int readlimit) { + } + + public synchronized void reset() throws IOException { + throw new IOException("mark/reset not supported"); + } + + public long getTotalIn() { + return inflater.getTotalIn(); + } + + public long getTotalOut() { + return inflater.getTotalOut(); + } + + public byte[] getAvailIn() { + if(inflater.avail_in<=0) + return null; + byte[] tmp = new byte[inflater.avail_in]; + System.arraycopy(inflater.next_in, inflater.next_in_index, + tmp, 0, inflater.avail_in); + return tmp; + } + + public void readHeader() throws IOException { + + byte[] empty = "".getBytes(); + inflater.setInput(empty, 0, 0, false); + inflater.setOutput(empty, 0, 0); + + int err = inflater.inflate(JZlib.Z_NO_FLUSH); + if(!inflater.istate.inParsingHeader()){ + return; + } + + byte[] b1 = new byte[1]; + do{ + int i = in.read(b1); + if(i<=0) + throw new IOException("no input"); + inflater.setInput(b1); + err = inflater.inflate(JZlib.Z_NO_FLUSH); + if(err!=0/*Z_OK*/) + throw new IOException(inflater.msg); + } + while(inflater.istate.inParsingHeader()); + } + + public Inflater getInflater(){ + return inflater; + } +} \ No newline at end of file diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/JZlib.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/JZlib.java new file mode 100644 index 00000000..a4bb3410 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/JZlib.java @@ -0,0 +1,92 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final public class JZlib{ + private static final String version="1.1.0"; + public static String version(){return version;} + + static final public int MAX_WBITS=15; // 32K LZ77 window + static final public int DEF_WBITS=MAX_WBITS; + + public enum WrapperType { + NONE, ZLIB, GZIP, ANY + } + + public static final WrapperType W_NONE = WrapperType.NONE; + public static final WrapperType W_ZLIB = WrapperType.ZLIB; + public static final WrapperType W_GZIP = WrapperType.GZIP; + public static final WrapperType W_ANY = WrapperType.ANY; + + // compression levels + static final public int Z_NO_COMPRESSION=0; + static final public int Z_BEST_SPEED=1; + static final public int Z_BEST_COMPRESSION=9; + static final public int Z_DEFAULT_COMPRESSION=(-1); + + // compression strategy + static final public int Z_FILTERED=1; + static final public int Z_HUFFMAN_ONLY=2; + static final public int Z_DEFAULT_STRATEGY=0; + + static final public int Z_NO_FLUSH=0; + static final public int Z_PARTIAL_FLUSH=1; + static final public int Z_SYNC_FLUSH=2; + static final public int Z_FULL_FLUSH=3; + static final public int Z_FINISH=4; + + static final public int Z_OK=0; + static final public int Z_STREAM_END=1; + static final public int Z_NEED_DICT=2; + static final public int Z_ERRNO=-1; + static final public int Z_STREAM_ERROR=-2; + static final public int Z_DATA_ERROR=-3; + static final public int Z_MEM_ERROR=-4; + static final public int Z_BUF_ERROR=-5; + static final public int Z_VERSION_ERROR=-6; + + // The three kinds of block type + static final public byte Z_BINARY = 0; + static final public byte Z_ASCII = 1; + static final public byte Z_UNKNOWN = 2; + + public static long adler32_combine(long adler1, long adler2, long len2){ + return Adler32.combine(adler1, adler2, len2); + } + + public static long crc32_combine(long crc1, long crc2, long len2){ + return CRC32.combine(crc1, crc2, len2); + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/StaticTree.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/StaticTree.java new file mode 100644 index 00000000..e35931c3 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/StaticTree.java @@ -0,0 +1,148 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class StaticTree{ + static final private int MAX_BITS=15; + + static final private int BL_CODES=19; + static final private int D_CODES=30; + static final private int LITERALS=256; + static final private int LENGTH_CODES=29; + static final private int L_CODES=(LITERALS+1+LENGTH_CODES); + + // Bit length codes must not exceed MAX_BL_BITS bits + static final int MAX_BL_BITS=7; + + static final short[] static_ltree = { + 12, 8, 140, 8, 76, 8, 204, 8, 44, 8, + 172, 8, 108, 8, 236, 8, 28, 8, 156, 8, + 92, 8, 220, 8, 60, 8, 188, 8, 124, 8, + 252, 8, 2, 8, 130, 8, 66, 8, 194, 8, + 34, 8, 162, 8, 98, 8, 226, 8, 18, 8, + 146, 8, 82, 8, 210, 8, 50, 8, 178, 8, + 114, 8, 242, 8, 10, 8, 138, 8, 74, 8, + 202, 8, 42, 8, 170, 8, 106, 8, 234, 8, + 26, 8, 154, 8, 90, 8, 218, 8, 58, 8, + 186, 8, 122, 8, 250, 8, 6, 8, 134, 8, + 70, 8, 198, 8, 38, 8, 166, 8, 102, 8, + 230, 8, 22, 8, 150, 8, 86, 8, 214, 8, + 54, 8, 182, 8, 118, 8, 246, 8, 14, 8, + 142, 8, 78, 8, 206, 8, 46, 8, 174, 8, + 110, 8, 238, 8, 30, 8, 158, 8, 94, 8, + 222, 8, 62, 8, 190, 8, 126, 8, 254, 8, + 1, 8, 129, 8, 65, 8, 193, 8, 33, 8, + 161, 8, 97, 8, 225, 8, 17, 8, 145, 8, + 81, 8, 209, 8, 49, 8, 177, 8, 113, 8, + 241, 8, 9, 8, 137, 8, 73, 8, 201, 8, + 41, 8, 169, 8, 105, 8, 233, 8, 25, 8, + 153, 8, 89, 8, 217, 8, 57, 8, 185, 8, + 121, 8, 249, 8, 5, 8, 133, 8, 69, 8, + 197, 8, 37, 8, 165, 8, 101, 8, 229, 8, + 21, 8, 149, 8, 85, 8, 213, 8, 53, 8, + 181, 8, 117, 8, 245, 8, 13, 8, 141, 8, + 77, 8, 205, 8, 45, 8, 173, 8, 109, 8, + 237, 8, 29, 8, 157, 8, 93, 8, 221, 8, + 61, 8, 189, 8, 125, 8, 253, 8, 19, 9, + 275, 9, 147, 9, 403, 9, 83, 9, 339, 9, + 211, 9, 467, 9, 51, 9, 307, 9, 179, 9, + 435, 9, 115, 9, 371, 9, 243, 9, 499, 9, + 11, 9, 267, 9, 139, 9, 395, 9, 75, 9, + 331, 9, 203, 9, 459, 9, 43, 9, 299, 9, + 171, 9, 427, 9, 107, 9, 363, 9, 235, 9, + 491, 9, 27, 9, 283, 9, 155, 9, 411, 9, + 91, 9, 347, 9, 219, 9, 475, 9, 59, 9, + 315, 9, 187, 9, 443, 9, 123, 9, 379, 9, + 251, 9, 507, 9, 7, 9, 263, 9, 135, 9, + 391, 9, 71, 9, 327, 9, 199, 9, 455, 9, + 39, 9, 295, 9, 167, 9, 423, 9, 103, 9, + 359, 9, 231, 9, 487, 9, 23, 9, 279, 9, + 151, 9, 407, 9, 87, 9, 343, 9, 215, 9, + 471, 9, 55, 9, 311, 9, 183, 9, 439, 9, + 119, 9, 375, 9, 247, 9, 503, 9, 15, 9, + 271, 9, 143, 9, 399, 9, 79, 9, 335, 9, + 207, 9, 463, 9, 47, 9, 303, 9, 175, 9, + 431, 9, 111, 9, 367, 9, 239, 9, 495, 9, + 31, 9, 287, 9, 159, 9, 415, 9, 95, 9, + 351, 9, 223, 9, 479, 9, 63, 9, 319, 9, + 191, 9, 447, 9, 127, 9, 383, 9, 255, 9, + 511, 9, 0, 7, 64, 7, 32, 7, 96, 7, + 16, 7, 80, 7, 48, 7, 112, 7, 8, 7, + 72, 7, 40, 7, 104, 7, 24, 7, 88, 7, + 56, 7, 120, 7, 4, 7, 68, 7, 36, 7, + 100, 7, 20, 7, 84, 7, 52, 7, 116, 7, + 3, 8, 131, 8, 67, 8, 195, 8, 35, 8, + 163, 8, 99, 8, 227, 8 + }; + + static final short[] static_dtree = { + 0, 5, 16, 5, 8, 5, 24, 5, 4, 5, + 20, 5, 12, 5, 28, 5, 2, 5, 18, 5, + 10, 5, 26, 5, 6, 5, 22, 5, 14, 5, + 30, 5, 1, 5, 17, 5, 9, 5, 25, 5, + 5, 5, 21, 5, 13, 5, 29, 5, 3, 5, + 19, 5, 11, 5, 27, 5, 7, 5, 23, 5 + }; + + static StaticTree static_l_desc = + new StaticTree(static_ltree, Tree.extra_lbits, + LITERALS+1, L_CODES, MAX_BITS); + + static StaticTree static_d_desc = + new StaticTree(static_dtree, Tree.extra_dbits, + 0, D_CODES, MAX_BITS); + + static StaticTree static_bl_desc = + new StaticTree(null, Tree.extra_blbits, + 0, BL_CODES, MAX_BL_BITS); + + short[] static_tree; // static tree or null + int[] extra_bits; // extra bits for each code or null + int extra_base; // base index for extra_bits + int elems; // max number of elements in the tree + int max_length; // max bit length for the codes + + private StaticTree(short[] static_tree, + int[] extra_bits, + int extra_base, + int elems, + int max_length){ + this.static_tree=static_tree; + this.extra_bits=extra_bits; + this.extra_base=extra_base; + this.elems=elems; + this.max_length=max_length; + } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/Tree.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Tree.java new file mode 100644 index 00000000..38cb40f2 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/Tree.java @@ -0,0 +1,367 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +final class Tree{ + static final private int MAX_BITS=15; + static final private int BL_CODES=19; + static final private int D_CODES=30; + static final private int LITERALS=256; + static final private int LENGTH_CODES=29; + static final private int L_CODES=(LITERALS+1+LENGTH_CODES); + static final private int HEAP_SIZE=(2*L_CODES+1); + + // Bit length codes must not exceed MAX_BL_BITS bits + static final int MAX_BL_BITS=7; + + // end of block literal code + static final int END_BLOCK=256; + + // repeat previous bit length 3-6 times (2 bits of repeat count) + static final int REP_3_6=16; + + // repeat a zero length 3-10 times (3 bits of repeat count) + static final int REPZ_3_10=17; + + // repeat a zero length 11-138 times (7 bits of repeat count) + static final int REPZ_11_138=18; + + // extra bits for each length code + static final int[] extra_lbits={ + 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0 + }; + + // extra bits for each distance code + static final int[] extra_dbits={ + 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 + }; + + // extra bits for each bit length code + static final int[] extra_blbits={ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7 + }; + + static final byte[] bl_order={ + 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; + + + // The lengths of the bit length codes are sent in order of decreasing + // probability, to avoid transmitting the lengths for unused bit + // length codes. + + static final int Buf_size=8*2; + + // see definition of array dist_code below + static final int DIST_CODE_LEN=512; + + static final byte[] _dist_code = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, + 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 + }; + + static final byte[] _length_code={ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, + 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, + 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 + }; + + static final int[] base_length = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, + 64, 80, 96, 112, 128, 160, 192, 224, 0 + }; + + static final int[] base_dist = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 + }; + + // Mapping from a distance to a distance code. dist is the distance - 1 and + // must not have side effects. _dist_code[256] and _dist_code[257] are never + // used. + static int d_code(int dist){ + return ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>>7)]); + } + + short[] dyn_tree; // the dynamic tree + int max_code; // largest code with non zero frequency + StaticTree stat_desc; // the corresponding static tree + + // Compute the optimal bit lengths for a tree and update the total bit length + // for the current block. + // IN assertion: the fields freq and dad are set, heap[heap_max] and + // above are the tree nodes sorted by increasing frequency. + // OUT assertions: the field len is set to the optimal bit length, the + // array bl_count contains the frequencies for each bit length. + // The length opt_len is updated; static_len is also updated if stree is + // not null. + void gen_bitlen(Deflate s){ + short[] tree = dyn_tree; + short[] stree = stat_desc.static_tree; + int[] extra = stat_desc.extra_bits; + int base = stat_desc.extra_base; + int max_length = stat_desc.max_length; + int h; // heap index + int n, m; // iterate over the tree elements + int bits; // bit length + int xbits; // extra bits + short f; // frequency + int overflow = 0; // number of elements with bit length too large + + for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0; + + // In a first pass, compute the optimal bit lengths (which may + // overflow in the case of the bit length tree). + tree[s.heap[s.heap_max]*2+1] = 0; // root of the heap + + for(h=s.heap_max+1; h max_length){ bits = max_length; overflow++; } + tree[n*2+1] = (short)bits; + // We overwrite tree[n*2+1] which is no longer needed + + if (n > max_code) continue; // not a leaf node + + s.bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n*2]; + s.opt_len += f * (bits + xbits); + if (stree!=null) s.static_len += f * (stree[n*2+1] + xbits); + } + if (overflow == 0) return; + + // This happens for example on obj2 and pic of the Calgary corpus + // Find the first bit length which could increase: + do { + bits = max_length-1; + while(s.bl_count[bits]==0) bits--; + s.bl_count[bits]--; // move one leaf down the tree + s.bl_count[bits+1]+=2; // move one overflow item as its brother + s.bl_count[max_length]--; + // The brother of the overflow item also moves one step up, + // but this does not affect bl_count[max_length] + overflow -= 2; + } + while (overflow > 0); + + for (bits = max_length; bits != 0; bits--) { + n = s.bl_count[bits]; + while (n != 0) { + m = s.heap[--h]; + if (m > max_code) continue; + if (tree[m*2+1] != bits) { + s.opt_len += ((long)bits - (long)tree[m*2+1])*(long)tree[m*2]; + tree[m*2+1] = (short)bits; + } + n--; + } + } + } + + // Construct one Huffman tree and assigns the code bit strings and lengths. + // Update the total bit length for the current block. + // IN assertion: the field freq is set for all tree elements. + // OUT assertions: the fields len and code are set to the optimal bit length + // and corresponding code. The length opt_len is updated; static_len is + // also updated if stree is not null. The field max_code is set. + void build_tree(Deflate s){ + short[] tree=dyn_tree; + short[] stree=stat_desc.static_tree; + int elems=stat_desc.elems; + int n, m; // iterate over heap elements + int max_code=-1; // largest code with non zero frequency + int node; // new node being created + + // Construct the initial heap, with least frequent element in + // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + // heap[0] is not used. + s.heap_len = 0; + s.heap_max = HEAP_SIZE; + + for(n=0; n=1; n--) + s.pqdownheap(tree, n); + + // Construct the Huffman tree by repeatedly combining the least two + // frequent nodes. + + node=elems; // next internal node of the tree + do{ + // n = node of least frequency + n=s.heap[1]; + s.heap[1]=s.heap[s.heap_len--]; + s.pqdownheap(tree, 1); + m=s.heap[1]; // m = node of next least frequency + + s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency + s.heap[--s.heap_max] = m; + + // Create a new node father of n and m + tree[node*2] = (short)(tree[n*2] + tree[m*2]); + s.depth[node] = (byte)(Math.max(s.depth[n],s.depth[m])+1); + tree[n*2+1] = tree[m*2+1] = (short)node; + + // and insert the new node in the heap + s.heap[1] = node++; + s.pqdownheap(tree, 1); + } + while(s.heap_len>=2); + + s.heap[--s.heap_max] = s.heap[1]; + + // At this point, the fields freq and dad are set. We can now + // generate the bit lengths. + + gen_bitlen(s); + + // The field len is now set, we can generate the bit codes + gen_codes(tree, max_code, s.bl_count, s.next_code); + } + + // Generate the codes for a given tree and bit counts (which need not be + // optimal). + // IN assertion: the array bl_count contains the bit length statistics for + // the given tree and the field len is set for all tree elements. + // OUT assertion: the field code is set for all tree elements of non + // zero code length. + private final static void gen_codes( + short[] tree, // the tree to decorate + int max_code, // largest code with non zero frequency + short[] bl_count, // number of codes at each bit length + short[] next_code){ + short code = 0; // running code value + int bits; // bit index + int n; // code index + + // The distribution counts are first used to generate the code values + // without bit reversal. + next_code[0]=0; + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (short)((code + bl_count[bits-1]) << 1); + } + + // Check that the bit counts in bl_count are consistent. The last code + // must be all ones. + //Assert (code + bl_count[MAX_BITS]-1 == (1<>>=1; + res<<=1; + } + while(--len>0); + return res>>>1; + } +} + diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/ZInputStream.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/ZInputStream.java new file mode 100644 index 00000000..cbd38e15 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/ZInputStream.java @@ -0,0 +1,126 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jcraft.jzlib; +import java.io.*; + +/** + * ZInputStream + * + * @deprecated use DeflaterOutputStream or InflaterInputStream + */ +@Deprecated +public class ZInputStream extends FilterInputStream { + + protected int flush=JZlib.Z_NO_FLUSH; + protected boolean compress; + protected InputStream in=null; + + protected Deflater deflater; + protected InflaterInputStream iis; + + public ZInputStream(InputStream in) throws IOException { + this(in, false); + } + public ZInputStream(InputStream in, boolean nowrap) throws IOException { + super(in); + iis = new InflaterInputStream(in, nowrap); + compress=false; + } + + public ZInputStream(InputStream in, int level) throws IOException { + super(in); + this.in=in; + deflater = new Deflater(); + deflater.init(level); + compress=true; + } + + private byte[] buf1 = new byte[1]; + public int read() throws IOException { + if(read(buf1, 0, 1)==-1) return -1; + return(buf1[0]&0xFF); + } + + private byte[] buf = new byte[512]; + + public int read(byte[] b, int off, int len) throws IOException { + if(compress){ + deflater.setOutput(b, off, len); + while(true){ + int datalen = in.read(buf, 0, buf.length); + if(datalen == -1) return -1; + deflater.setInput(buf, 0, datalen, true); + int err = deflater.deflate(flush); + if(deflater.next_out_index>0) + return deflater.next_out_index; + if(err == JZlib.Z_STREAM_END) + return 0; + if(err == JZlib.Z_STREAM_ERROR || + err == JZlib.Z_DATA_ERROR){ + throw new ZStreamException("deflating: "+deflater.msg); + } + } + } + else{ + return iis.read(b, off, len); + } + } + + public long skip(long n) throws IOException { + int len=512; + if(n0){ + inflater.setOutput(buf, 0, buf.length); + err = inflater.inflate(flush); + if(inflater.next_out_index>0) + out.write(buf, 0, inflater.next_out_index); + if(err != JZlib.Z_OK) + break; + } + if(err != JZlib.Z_OK) + throw new ZStreamException("inflating: "+inflater.msg); + return; + } + } + + public int getFlushMode() { + return flush; + } + + public void setFlushMode(int flush) { + this.flush=flush; + } + + public void finish() throws IOException { + int err; + if(compress){ + int tmp = flush; + int flush = JZlib.Z_FINISH; + try{ + write("".getBytes(), 0, 0); + } + finally { flush = tmp; } + } + else{ + dos.finish(); + } + flush(); + } + public synchronized void end() { + if(end) return; + if(compress){ + try { dos.finish(); } catch(Exception e){} + } + else{ + inflater.end(); + } + end=true; + } + public void close() throws IOException { + try{ + try{finish();} + catch (IOException ignored) {} + } + finally{ + end(); + out.close(); + out=null; + } + } + + public long getTotalIn() { + if(compress) return dos.getTotalIn(); + else return inflater.total_in; + } + + public long getTotalOut() { + if(compress) return dos.getTotalOut(); + else return inflater.total_out; + } + + public void flush() throws IOException { + out.flush(); + } + +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/ZStream.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/ZStream.java new file mode 100644 index 00000000..0afa4fd0 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/ZStream.java @@ -0,0 +1,377 @@ +/* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */ +/* +Copyright (c) 2000-2011 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +/** + * ZStream + * + * @deprecated Not for public use in the future. + */ +@Deprecated +public class ZStream{ + + static final private int MAX_WBITS=15; // 32K LZ77 window + static final private int DEF_WBITS=MAX_WBITS; + + static final private int Z_NO_FLUSH=0; + static final private int Z_PARTIAL_FLUSH=1; + static final private int Z_SYNC_FLUSH=2; + static final private int Z_FULL_FLUSH=3; + static final private int Z_FINISH=4; + + static final private int MAX_MEM_LEVEL=9; + + static final private int Z_OK=0; + static final private int Z_STREAM_END=1; + static final private int Z_NEED_DICT=2; + static final private int Z_ERRNO=-1; + static final private int Z_STREAM_ERROR=-2; + static final private int Z_DATA_ERROR=-3; + static final private int Z_MEM_ERROR=-4; + static final private int Z_BUF_ERROR=-5; + static final private int Z_VERSION_ERROR=-6; + + public byte[] next_in; // next input byte + public int next_in_index; + public int avail_in; // number of bytes available at next_in + public long total_in; // total nb of input bytes read so far + + public byte[] next_out; // next output byte should be put there + public int next_out_index; + public int avail_out; // remaining free space at next_out + public long total_out; // total nb of bytes output so far + + public String msg; + + Deflate dstate; + Inflate istate; + + int data_type; // best guess about the data type: ascii or binary + + Checksum adler; + + public ZStream(){ + this(new Adler32()); + } + + public ZStream(Checksum adler){ + this.adler=adler; + } + + public int inflateInit(){ + return inflateInit(DEF_WBITS); + } + public int inflateInit(boolean nowrap){ + return inflateInit(DEF_WBITS, nowrap); + } + public int inflateInit(int w){ + return inflateInit(w, false); + } + public int inflateInit(JZlib.WrapperType wrapperType) { + return inflateInit(DEF_WBITS, wrapperType); + } + public int inflateInit(int w, JZlib.WrapperType wrapperType) { + boolean nowrap = false; + if(wrapperType == JZlib.W_NONE){ + nowrap = true; + } + else if(wrapperType == JZlib.W_GZIP) { + w += 16; + } + else if(wrapperType == JZlib.W_ANY) { + w |= Inflate.INFLATE_ANY; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return inflateInit(w, nowrap); + } + public int inflateInit(int w, boolean nowrap){ + istate=new Inflate(this); + return istate.inflateInit(nowrap?-w:w); + } + + public int inflate(int f){ + if(istate==null) return Z_STREAM_ERROR; + return istate.inflate(f); + } + public int inflateEnd(){ + if(istate==null) return Z_STREAM_ERROR; + int ret=istate.inflateEnd(); +// istate = null; + return ret; + } + public int inflateSync(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSync(); + } + public int inflateSyncPoint(){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSyncPoint(); + } + public int inflateSetDictionary(byte[] dictionary, int dictLength){ + if(istate == null) + return Z_STREAM_ERROR; + return istate.inflateSetDictionary(dictionary, dictLength); + } + public boolean inflateFinished(){ + return istate.mode==12 /*DONE*/; + } + + public int deflateInit(int level){ + return deflateInit(level, MAX_WBITS); + } + public int deflateInit(int level, boolean nowrap){ + return deflateInit(level, MAX_WBITS, nowrap); + } + public int deflateInit(int level, int bits){ + return deflateInit(level, bits, false); + } + public int deflateInit(int level, int bits, int memlevel, JZlib.WrapperType wrapperType){ + if(bits < 9 || bits > 15){ + return Z_STREAM_ERROR; + } + if(wrapperType == JZlib.W_NONE) { + bits *= -1; + } + else if(wrapperType == JZlib.W_GZIP) { + bits += 16; + } + else if(wrapperType == JZlib.W_ANY) { + return Z_STREAM_ERROR; + } + else if(wrapperType == JZlib.W_ZLIB) { + } + return this.deflateInit(level, bits, memlevel); + } + public int deflateInit(int level, int bits, int memlevel){ + dstate=new Deflate(this); + return dstate.deflateInit(level, bits, memlevel); + } + public int deflateInit(int level, int bits, boolean nowrap){ + dstate=new Deflate(this); + return dstate.deflateInit(level, nowrap?-bits:bits); + } + public int deflate(int flush){ + if(dstate==null){ + return Z_STREAM_ERROR; + } + return dstate.deflate(flush); + } + public int deflateEnd(){ + if(dstate==null) return Z_STREAM_ERROR; + int ret=dstate.deflateEnd(); + dstate=null; + return ret; + } + public int deflateParams(int level, int strategy){ + if(dstate==null) return Z_STREAM_ERROR; + return dstate.deflateParams(level, strategy); + } + public int deflateSetDictionary (byte[] dictionary, int dictLength){ + if(dstate == null) + return Z_STREAM_ERROR; + return dstate.deflateSetDictionary(dictionary, dictLength); + } + + // Flush as much pending output as possible. All deflate() output goes + // through this function so some applications may wish to modify it + // to avoid allocating a large strm->next_out buffer and copying into it. + // (See also read_buf()). + void flush_pending(){ + int len=dstate.pending; + + if(len>avail_out) len=avail_out; + if(len==0) return; + + if(dstate.pending_buf.length<=dstate.pending_out || + next_out.length<=next_out_index || + dstate.pending_buf.length<(dstate.pending_out+len) || + next_out.length<(next_out_index+len)){ + //System.out.println(dstate.pending_buf.length+", "+dstate.pending_out+ + // ", "+next_out.length+", "+next_out_index+", "+len); + //System.out.println("avail_out="+avail_out); + } + + System.arraycopy(dstate.pending_buf, dstate.pending_out, + next_out, next_out_index, len); + + next_out_index+=len; + dstate.pending_out+=len; + total_out+=len; + avail_out-=len; + dstate.pending-=len; + if(dstate.pending==0){ + dstate.pending_out=0; + } + } + + // Read a new buffer from the current input stream, update the adler32 + // and total number of bytes read. All deflate() input goes through + // this function so some applications may wish to modify it to avoid + // allocating a large strm->next_in buffer and copying from it. + // (See also flush_pending()). + int read_buf(byte[] buf, int start, int size) { + int len=avail_in; + + if(len>size) len=size; + if(len==0) return 0; + + avail_in-=len; + + if(dstate.wrap!=0) { + adler.update(next_in, next_in_index, len); + } + System.arraycopy(next_in, next_in_index, buf, start, len); + next_in_index += len; + total_in += len; + return len; + } + + public long getAdler(){ + return adler.getValue(); + } + + public void free(){ + next_in=null; + next_out=null; + msg=null; + } + + public void setOutput(byte[] buf){ + setOutput(buf, 0, buf.length); + } + + public void setOutput(byte[] buf, int off, int len){ + next_out = buf; + next_out_index = off; + avail_out = len; + } + + public void setInput(byte[] buf){ + setInput(buf, 0, buf.length, false); + } + + public void setInput(byte[] buf, boolean append){ + setInput(buf, 0, buf.length, append); + } + + public void setInput(byte[] buf, int off, int len, boolean append){ + if(len<=0 && append && next_in!=null) return; + + if(avail_in>0 && append){ + byte[] tmp = new byte[avail_in+len]; + System.arraycopy(next_in, next_in_index, tmp, 0, avail_in); + System.arraycopy(buf, off, tmp, avail_in, len); + next_in=tmp; + next_in_index=0; + avail_in+=len; + } + else{ + next_in=buf; + next_in_index=off; + avail_in=len; + } + } + + public byte[] getNextIn(){ + return next_in; + } + + public void setNextIn(byte[] next_in){ + this.next_in = next_in; + } + + public int getNextInIndex(){ + return next_in_index; + } + + public void setNextInIndex(int next_in_index){ + this.next_in_index = next_in_index; + } + + public int getAvailIn(){ + return avail_in; + } + + public void setAvailIn(int avail_in){ + this.avail_in = avail_in; + } + + public byte[] getNextOut(){ + return next_out; + } + + public void setNextOut(byte[] next_out){ + this.next_out = next_out; + } + + public int getNextOutIndex(){ + return next_out_index; + } + + public void setNextOutIndex(int next_out_index){ + this.next_out_index = next_out_index; + } + + public int getAvailOut(){ + return avail_out; + + } + + public void setAvailOut(int avail_out){ + this.avail_out = avail_out; + } + + public long getTotalOut(){ + return total_out; + } + + public long getTotalIn(){ + return total_in; + } + + public String getMessage(){ + return msg; + } + + /** + * Those methods are expected to be override by Inflater and Deflater. + * In the future, they will become abstract methods. + */ + public int end(){ return Z_OK; } + public boolean finished(){ return false; } +} diff --git a/src/java/JavaFileStorage/src/com/jcraft/jzlib/ZStreamException.java b/src/java/JavaFileStorage/src/com/jcraft/jzlib/ZStreamException.java new file mode 100644 index 00000000..308bb8a1 --- /dev/null +++ b/src/java/JavaFileStorage/src/com/jcraft/jzlib/ZStreamException.java @@ -0,0 +1,44 @@ +/* -*-mode:java; c-basic-offset:2; -*- */ +/* +Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + + 3. The names of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT, +INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * This program is based on zlib-1.1.3, so all credit should go authors + * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu) + * and contributors of zlib. + */ + +package com.jcraft.jzlib; + +public class ZStreamException extends java.io.IOException { + public ZStreamException() { + super(); + } + public ZStreamException(String s) { + super(s); + } +} diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/GoogleDriveFileStorage.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/GoogleDriveFileStorage.java index 38876577..c39cf97e 100644 --- a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/GoogleDriveFileStorage.java +++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/GoogleDriveFileStorage.java @@ -67,7 +67,7 @@ public class GoogleDriveFileStorage extends JavaFileStorageBase { - public static String getRootPathForAccount(String accountName) throws UnsupportedEncodingException { + public String getRootPathForAccount(String accountName) throws UnsupportedEncodingException { return GDRIVE_PROTOCOL_ID+"://"+encode(accountName)+"/"; } diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java index a7963d3e..e129ba68 100644 --- a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java +++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorage.java @@ -25,6 +25,7 @@ public interface FileStorageSetupInitiatorActivity void startSelectFileProcess(String path, boolean isForSave, int requestCode); void startFileUsageProcess(String path, int requestCode, boolean alwaysReturnSuccess); void onImmediateResult(int requestCode, int result, Intent intent); + void performManualFileSelect(boolean isForSave, int requestCode, String protocolId); Activity getActivity(); } diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorageBase.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorageBase.java index 7832053a..df2f1a1f 100644 --- a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorageBase.java +++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/JavaFileStorageBase.java @@ -27,7 +27,7 @@ public abstract class JavaFileStorageBase implements JavaFileStorage{ } - protected static String encode(final String unencoded) + protected String encode(final String unencoded) throws UnsupportedEncodingException { return UTF8_PREFIX+java.net.URLEncoder.encode(unencoded, HTTP.UTF_8); } diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/KitKatFileStorage.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/KitKatFileStorage.java new file mode 100644 index 00000000..1899daaf --- /dev/null +++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/KitKatFileStorage.java @@ -0,0 +1,10 @@ +package keepass2android.javafilestorage; + +import android.content.Context; + +public class KitKatFileStorage { + public KitKatFileStorage(Context ctx) + { +// ctx.getContentResolver(). + } +} diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SftpStorage.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SftpStorage.java new file mode 100644 index 00000000..bcdd1393 --- /dev/null +++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SftpStorage.java @@ -0,0 +1,427 @@ +package keepass2android.javafilestorage; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.protocol.HTTP; + +import com.jcraft.jsch.Channel; +import com.jcraft.jsch.ChannelSftp; +import com.jcraft.jsch.ChannelSftp.LsEntry; +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; +import com.jcraft.jsch.SftpATTRS; +import com.jcraft.jsch.SftpException; +import com.jcraft.jsch.UserInfo; + +import android.content.Intent; +import android.os.Bundle; + +public class SftpStorage extends JavaFileStorageBase { + + public static final int DEFAULT_SFTP_PORT = 22; + JSch jsch; + + class ConnectionInfo + { + String host; + String username; + String password; + String localPath; + int port; + } + + public SftpStorage() { + + } + + private static final String SFTP_PROTOCOL_ID = "sftp"; + + @Override + public boolean checkForFileChangeFast(String path, + String previousFileVersion) throws Exception { + String currentVersion = getCurrentFileVersionFast(path); + if (currentVersion == null) + return false; + return currentVersion.equals(previousFileVersion) == false; + } + + @Override + public String getCurrentFileVersionFast(String path) { + + return null; // no simple way to get the version "fast" + } + + @Override + public InputStream openFileForRead(String path) throws Exception { + + ChannelSftp c = init(path); + + try { + byte[] buff = new byte[8000]; + + int bytesRead = 0; + + InputStream in = c.get(extractSessionPath(path)); + ByteArrayOutputStream bao = new ByteArrayOutputStream(); + + while ((bytesRead = in.read(buff)) != -1) { + bao.write(buff, 0, bytesRead); + } + + byte[] data = bao.toByteArray(); + + ByteArrayInputStream bin = new ByteArrayInputStream(data); + c.getSession().disconnect(); + + return bin; + + } catch (Exception e) { + tryDisconnect(c); + throw convertException(e); + } + } + + private void tryDisconnect(ChannelSftp c) { + try { + c.getSession().disconnect(); + } catch (JSchException je) { + + } + } + + @Override + public void uploadFile(String path, byte[] data, boolean writeTransactional) + throws Exception { + + ChannelSftp c = init(path); + try { + InputStream in = new ByteArrayInputStream(data); + String targetPath = extractSessionPath(path); + if (writeTransactional) + { + //upload to temporary location: + String tmpPath = targetPath+".tmp"; + c.put(in, tmpPath); + //remove previous file: + try + { + c.rm(targetPath); + } + catch (SftpException e) + { + //ignore. Can happen if file didn't exist before + } + //rename tmp to target path: + c.rename(tmpPath, targetPath); + } + else + { + c.put(in, targetPath); + } + + tryDisconnect(c); + } catch (Exception e) { + tryDisconnect(c); + throw e; + } + + } + + @Override + public String createFolder(String parentPath, String newDirName) + throws Exception { + + try { + ChannelSftp c = init(parentPath); + String newPath = concatPaths(parentPath, newDirName); + c.mkdir(extractSessionPath(newPath)); + tryDisconnect(c); + return newPath; + } catch (Exception e) { + throw convertException(e); + } + + } + + private String extractSessionPath(String newPath) { + String withoutProtocol = newPath + .substring(getProtocolPrefix().length()); + return withoutProtocol.substring(withoutProtocol.indexOf("/")); + } + + private String extractUserPwdHost(String path) { + String withoutProtocol = path + .substring(getProtocolPrefix().length()); + return withoutProtocol.substring(0,withoutProtocol.indexOf("/")); + } + + private String concatPaths(String parentPath, String newDirName) { + String res = parentPath; + if (!res.endsWith("/")) + res += "/"; + res += newDirName; + return res; + } + + @Override + public String createFilePath(String parentPath, String newFileName) + throws Exception { + if (parentPath.endsWith("/") == false) + parentPath += "/"; + return parentPath + newFileName; + } + + @Override + public List listFiles(String parentPath) throws Exception { + + ChannelSftp c = init(parentPath); + return listFiles(parentPath, c); + + } + + private void setFromAttrs(FileEntry fileEntry, SftpATTRS attrs) { + fileEntry.isDirectory = attrs.isDir(); + fileEntry.canRead = true; // currently not inferred from the + // permissions. + fileEntry.canWrite = true; // currently not inferred from the + // permissions. + fileEntry.lastModifiedTime = ((long) attrs.getMTime()) * 1000; + if (fileEntry.isDirectory) + fileEntry.sizeInBytes = 0; + else + fileEntry.sizeInBytes = attrs.getSize(); + } + + private Exception convertException(Exception e) { + + if (SftpException.class.isAssignableFrom(e.getClass()) ) + { + SftpException sftpEx = (SftpException)e; + if (sftpEx.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) + return new FileNotFoundException(sftpEx.getMessage()); + } + + return e; + + } + + @Override + public FileEntry getFileEntry(String filename) throws Exception { + + ChannelSftp c = init(filename); + try { + FileEntry fileEntry = new FileEntry(); + String sessionPath = extractSessionPath(filename); + SftpATTRS attr = c.stat(sessionPath); + setFromAttrs(fileEntry, attr); + fileEntry.path = filename; + fileEntry.displayName = getFilename(sessionPath); + tryDisconnect(c); + return fileEntry; + } catch (Exception e) { + logDebug("Exception in getFileEntry! " + e); + tryDisconnect(c); + throw convertException(e); + } + } + + @Override + public void delete(String path) throws Exception { + + ChannelSftp c = init(path); + delete(path, c); + } + + private void delete(String path, ChannelSftp c) throws Exception { + String sessionLocalPath = extractSessionPath(path); + try { + if (c.stat(sessionLocalPath).isDir()) + { + List contents = listFiles(path, c); + for (FileEntry fe: contents) + { + delete(fe.path, c); + } + c.rmdir(sessionLocalPath); + } + else + { + c.rm(sessionLocalPath); + } + } catch (Exception e) { + tryDisconnect(c); + throw convertException(e); + } + + } + + private List listFiles(String path, ChannelSftp c) throws Exception { + try { + List res = new ArrayList(); + @SuppressWarnings("rawtypes") + java.util.Vector vv = c.ls(extractSessionPath(path)); + if (vv != null) { + for (int ii = 0; ii < vv.size(); ii++) { + + Object obj = vv.elementAt(ii); + if (obj instanceof com.jcraft.jsch.ChannelSftp.LsEntry) { + LsEntry lsEntry = (com.jcraft.jsch.ChannelSftp.LsEntry) obj; + + if ((lsEntry.getFilename().equals(".")) + ||(lsEntry.getFilename().equals("..")) + ) + continue; + + FileEntry fileEntry = new FileEntry(); + fileEntry.displayName = lsEntry.getFilename(); + fileEntry.path = createFilePath(path, fileEntry.displayName); + SftpATTRS attrs = lsEntry.getAttrs(); + setFromAttrs(fileEntry, attrs); + res.add(fileEntry); + } + + } + } + return res; + } catch (Exception e) { + tryDisconnect(c); + throw convertException(e); + } + } + + @Override + public void startSelectFile( + JavaFileStorage.FileStorageSetupInitiatorActivity activity, + boolean isForSave, int requestCode) { + activity.performManualFileSelect(isForSave, requestCode, getProtocolId()); + } + + @Override + protected String decode(String encodedString) + throws UnsupportedEncodingException { + return java.net.URLDecoder.decode(encodedString, HTTP.UTF_8); + } + + @Override + protected String encode(final String unencoded) + throws UnsupportedEncodingException { + return java.net.URLEncoder.encode(unencoded, HTTP.UTF_8); + } + + ChannelSftp init(String filename) throws JSchException, UnsupportedEncodingException { + jsch = new JSch(); + ConnectionInfo ci = splitStringToConnectionInfo(filename); + + Session session = jsch.getSession(ci.username, ci.host, ci.port); + + UserInfo ui = new SftpUserInfo(ci.password); + session.setUserInfo(ui); + + session.connect(); + + Channel channel = session.openChannel("sftp"); + channel.connect(); + ChannelSftp c = (ChannelSftp) channel; + + logDebug("success: init Sftp"); + return c; + + } + + private ConnectionInfo splitStringToConnectionInfo(String filename) + throws UnsupportedEncodingException { + ConnectionInfo ci = new ConnectionInfo(); + ci.host = extractUserPwdHost(filename); + String userPwd = ci.host.substring(0, ci.host.indexOf('@')); + ci.username = decode(userPwd.substring(0, userPwd.indexOf(":"))); + ci.password = decode(userPwd.substring(userPwd.indexOf(":")+1)); + ci.host = ci.host.substring(ci.host.indexOf('@') + 1); + ci.port = DEFAULT_SFTP_PORT; + int portSeparatorIndex = ci.host.indexOf(":"); + if (portSeparatorIndex >= 0) + { + ci.port = Integer.parseInt(ci.host.substring(portSeparatorIndex+1)); + ci.host = ci.host.substring(0, portSeparatorIndex); + } + return ci; + } + + @Override + public void prepareFileUsage(JavaFileStorage.FileStorageSetupInitiatorActivity activity, String path, int requestCode, boolean alwaysReturnSuccess) { + Intent intent = new Intent(); + intent.putExtra(EXTRA_PATH, path); + activity.onImmediateResult(requestCode, RESULT_FILEUSAGE_PREPARED, intent); + } + + @Override + public String getProtocolId() { + return SFTP_PROTOCOL_ID; + } + + @Override + public void onResume(JavaFileStorage.FileStorageSetupActivity setupAct) { + + } + + @Override + public boolean requiresSetup(String path) { + return false; + } + + @Override + public void onCreate(FileStorageSetupActivity activity, + Bundle savedInstanceState) { + + } + + @Override + public String getDisplayName(String path) { + try + { + ConnectionInfo ci = splitStringToConnectionInfo(path); + return getProtocolPrefix()+ci.username+"@"+ci.host+extractSessionPath(path); + } + catch (Exception e) + { + return extractSessionPath(path); + } + } + + @Override + public String getFilename(String path) throws Exception { + if (path.endsWith("/")) + path = path.substring(0, path.length()-1); + int lastIndex = path.lastIndexOf("/"); + if (lastIndex >= 0) + return path.substring(lastIndex + 1); + else + return path; + } + + @Override + public void onStart(FileStorageSetupActivity activity) { + + } + + @Override + public void onActivityResult(FileStorageSetupActivity activity, + int requestCode, int resultCode, Intent data) { + + + } + + public String buildFullPath( String host, int port, String localPath, String username, String password) throws UnsupportedEncodingException + { + if (port != DEFAULT_SFTP_PORT) + host += ":"+String.valueOf(port); + return getProtocolPrefix()+encode(username)+":"+encode(password)+"@"+host+localPath; + + } +} diff --git a/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SftpUserInfo.java b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SftpUserInfo.java new file mode 100644 index 00000000..e01594db --- /dev/null +++ b/src/java/JavaFileStorage/src/keepass2android/javafilestorage/SftpUserInfo.java @@ -0,0 +1,46 @@ +package keepass2android.javafilestorage; + +import android.util.Log; + +import com.jcraft.jsch.UserInfo; + +public class SftpUserInfo implements UserInfo { + String _password; + + public SftpUserInfo(String password) { + _password = password; + } + + @Override + public String getPassphrase() { + + return null; + } + + @Override + public String getPassword() { + + return _password; + } + + @Override + public boolean promptPassword(String message) { + return true; + } + + @Override + public boolean promptPassphrase(String message) { + return false; //passphrase not supported + } + + @Override + public boolean promptYesNo(String message) { + return true; //continue all operations without user action + } + + @Override + public void showMessage(String message) { + Log.d("KP2AJ", message); + } + +} diff --git a/src/keepass2android/ChangeLog.cs b/src/keepass2android/ChangeLog.cs index 7dcd24b9..7736b62c 100644 --- a/src/keepass2android/ChangeLog.cs +++ b/src/keepass2android/ChangeLog.cs @@ -22,6 +22,7 @@ namespace keepass2android AlertDialog.Builder builder = new AlertDialog.Builder(ctx); builder.SetTitle(ctx.GetString(Resource.String.ChangeLog_title)); String[] changeLog = { + ctx.GetString(Resource.String.ChangeLog_0_9_3), ctx.GetString(Resource.String.ChangeLog_0_9_2), ctx.GetString(Resource.String.ChangeLog_0_9_1), ctx.GetString(Resource.String.ChangeLog_0_9), diff --git a/src/keepass2android/CreateDatabaseActivity.cs b/src/keepass2android/CreateDatabaseActivity.cs index d042beb0..d59dccce 100644 --- a/src/keepass2android/CreateDatabaseActivity.cs +++ b/src/keepass2android/CreateDatabaseActivity.cs @@ -311,7 +311,10 @@ namespace keepass2android OnActivityResult, defaultPath => { - Util.ShowFilenameDialog(this, OnCreateButton, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url), + if (defaultPath.StartsWith("sftp://")) + Util.ShowSftpDialog(this, OnReceiveSftpData); + else + Util.ShowFilenameDialog(this, OnCreateButton, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url), Intents.RequestCodeFileBrowseForOpen); } ), true, RequestCodeDbFilename, protocolId); @@ -378,6 +381,12 @@ namespace keepass2android } + private bool OnReceiveSftpData(string filename) + { + StartFileChooser(filename, RequestCodeDbFilename, true); + return true; + } + private static string ConvertFilenameToIocPath(string filename) { if ((filename != null) && (filename.StartsWith("file://"))) diff --git a/src/keepass2android/KeePass.cs b/src/keepass2android/KeePass.cs index cbcf7094..1739480f 100644 --- a/src/keepass2android/KeePass.cs +++ b/src/keepass2android/KeePass.cs @@ -14,7 +14,6 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file You should have received a copy of the GNU General Public License along with Keepass2Android. If not, see . */ -using System; using Android.App; using Android.Content; @@ -24,7 +23,11 @@ using Android.Preferences; using Android.Content.PM; using Android.Text; using Android.Text.Method; +using Java.Lang; +using Java.Lang.Reflect; using KeePassLib.Serialization; +using Exception = System.Exception; +using String = System.String; namespace keepass2android { @@ -59,13 +62,25 @@ namespace keepass2android base.OnResume(); Kp2aLog.Log("KeePass.OnResume"); } - + protected override void OnStart() { base.OnStart(); Kp2aLog.Log("KeePass.OnStart"); + if (GetCurrentRuntimeValue().StartsWith("ART")) + { + new AlertDialog.Builder(this) + .SetTitle("Warning") + .SetMessage( + "It looks like you are running ART (Android Runtime). Please note: At the time of this app's release, Google says ART is experimental. And indeed, the early releases of ART (e.g. in Android 4.4, 4.4.1 and 4.4.2) contain a bug which causes crashes in Mono for Android apps including Keepass2Android. This bug was fixed after the 4.4.2 release so if you have a later Android release, you might be able to use this app. If not, please switch to Dalvik. Please do not downrate Keepass2Android for this problem, it's not our bug :-). Thanks! See our website (keepass2android.codeplex.com) for more information on this issue.") + .SetPositiveButton("OK", (sender, args) => LaunchNextActivity()) + .Create() + .Show(); + return; + } + ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this); bool showChangeLog = false; @@ -81,8 +96,9 @@ namespace keepass2android edit.PutInt(GetString(Resource.String.LastInfoVersionCode_key), packageInfo.VersionCode); EditorCompat.Apply(edit); } - - } catch (PackageManager.NameNotFoundException) + + } + catch (PackageManager.NameNotFoundException) { } @@ -90,21 +106,81 @@ namespace keepass2android if (showChangeLog) { ChangeLog.ShowChangeLog(this, LaunchNextActivity); - - } else { LaunchNextActivity(); } - - - - } - + + + + + private static String SELECT_RUNTIME_PROPERTY = "persist.sys.dalvik.vm.lib"; + private static String LIB_DALVIK = "libdvm.so"; + private static String LIB_ART = "libart.so"; + private static String LIB_ART_D = "libartd.so"; + + private String GetCurrentRuntimeValue() + { + try + { + Class systemProperties = Class.ForName("android.os.SystemProperties"); + try + { + Method get = systemProperties.GetMethod("get", + Class.FromType(typeof (Java.Lang.String)), + Class.FromType(typeof (Java.Lang.String))); + if (get == null) + { + return "WTF?!"; + } + try + { + String value = (String) get.Invoke( + systemProperties, SELECT_RUNTIME_PROPERTY, + /* Assuming default is */"Dalvik"); + if (LIB_DALVIK.Equals(value)) + { + return "Dalvik"; + } + else if (LIB_ART.Equals(value)) + { + return "ART"; + } + else if (LIB_ART_D.Equals(value)) + { + return "ART debug build"; + } + + return value; + } + catch (IllegalAccessException e) + { + return "IllegalAccessException"; + } + catch (IllegalArgumentException e) + { + return "IllegalArgumentException"; + } + catch (InvocationTargetException e) + { + return "InvocationTargetException"; + } + } + catch (NoSuchMethodException e) + { + return "SystemProperties.get(String key, String def) method is not found"; + } + } + catch (ClassNotFoundException e) + { + return "SystemProperties class is not found"; + } + } + IOConnectionInfo LoadIoc(string defaultFileName) { return App.Kp2a.FileDbHelper.CursorToIoc(App.Kp2a.FileDbHelper.FetchFileByName(defaultFileName)); diff --git a/src/keepass2android/Properties/AndroidManifest_net.xml b/src/keepass2android/Properties/AndroidManifest_net.xml index 192ac74c..76be0a52 100644 --- a/src/keepass2android/Properties/AndroidManifest_net.xml +++ b/src/keepass2android/Properties/AndroidManifest_net.xml @@ -1,5 +1,5 @@  - + diff --git a/src/keepass2android/Resources/Resource.designer.cs b/src/keepass2android/Resources/Resource.designer.cs index 2304a835..2d9ef921 100644 --- a/src/keepass2android/Resources/Resource.designer.cs +++ b/src/keepass2android/Resources/Resource.designer.cs @@ -1889,73 +1889,76 @@ namespace keepass2android public const int ic_storage_https = 2130837816; // aapt resource value: 0x7f020139 - public const int ic_storage_skydrive = 2130837817; + public const int ic_storage_sftp = 2130837817; // aapt resource value: 0x7f02013a - public const int ic_unlocked_gray = 2130837818; + public const int ic_storage_skydrive = 2130837818; // aapt resource value: 0x7f02013b - public const int location_web_site = 2130837819; + public const int ic_unlocked_gray = 2130837819; // aapt resource value: 0x7f02013c - public const int navigation_accept = 2130837820; + public const int location_web_site = 2130837820; // aapt resource value: 0x7f02013d - public const int navigation_accept_dark = 2130837821; + public const int navigation_accept = 2130837821; // aapt resource value: 0x7f02013e - public const int navigation_cancel = 2130837822; + public const int navigation_accept_dark = 2130837822; // aapt resource value: 0x7f02013f - public const int navigation_previous_item = 2130837823; + public const int navigation_cancel = 2130837823; // aapt resource value: 0x7f020140 - public const int navigation_previous_item_dark = 2130837824; + public const int navigation_previous_item = 2130837824; // aapt resource value: 0x7f020141 - public const int notify = 2130837825; + public const int navigation_previous_item_dark = 2130837825; // aapt resource value: 0x7f020142 - public const int notify_keyboard = 2130837826; + public const int notify = 2130837826; // aapt resource value: 0x7f020143 - public const int oktoberfest = 2130837827; + public const int notify_keyboard = 2130837827; // aapt resource value: 0x7f020144 - public const int RedButton = 2130837828; + public const int oktoberfest = 2130837828; // aapt resource value: 0x7f020145 - public const int section_header = 2130837829; + public const int RedButton = 2130837829; // aapt resource value: 0x7f020146 - public const int sym_keyboard = 2130837830; + public const int section_header = 2130837830; // aapt resource value: 0x7f020147 - public const int sym_keyboard_delete = 2130837831; + public const int sym_keyboard = 2130837831; // aapt resource value: 0x7f020148 - public const int sym_keyboard_done = 2130837832; + public const int sym_keyboard_delete = 2130837832; // aapt resource value: 0x7f020149 - public const int sym_keyboard_kp2a = 2130837833; + public const int sym_keyboard_done = 2130837833; // aapt resource value: 0x7f02014a - public const int sym_keyboard_return = 2130837834; + public const int sym_keyboard_kp2a = 2130837834; // aapt resource value: 0x7f02014b - public const int sym_keyboard_search = 2130837835; + public const int sym_keyboard_return = 2130837835; // aapt resource value: 0x7f02014c - public const int sym_keyboard_shift = 2130837836; + public const int sym_keyboard_search = 2130837836; // aapt resource value: 0x7f02014d - public const int sym_keyboard_space = 2130837837; + public const int sym_keyboard_shift = 2130837837; // aapt resource value: 0x7f02014e - public const int transparent = 2130837838; + public const int sym_keyboard_space = 2130837838; // aapt resource value: 0x7f02014f - public const int YellowButton = 2130837839; + public const int transparent = 2130837839; + + // aapt resource value: 0x7f020150 + public const int YellowButton = 2130837840; static Drawable() { @@ -2105,17 +2108,17 @@ namespace keepass2android // aapt resource value: 0x7f070057 public const int afc_listview_menu = 2131165271; - // aapt resource value: 0x7f07012d - public const int afc_menuitem_home = 2131165485; + // aapt resource value: 0x7f070134 + public const int afc_menuitem_home = 2131165492; - // aapt resource value: 0x7f070130 - public const int afc_menuitem_new_folder = 2131165488; + // aapt resource value: 0x7f070137 + public const int afc_menuitem_new_folder = 2131165495; - // aapt resource value: 0x7f07012e - public const int afc_menuitem_sort = 2131165486; + // aapt resource value: 0x7f070135 + public const int afc_menuitem_sort = 2131165493; - // aapt resource value: 0x7f07012f - public const int afc_menuitem_switch_viewmode = 2131165487; + // aapt resource value: 0x7f070136 + public const int afc_menuitem_switch_viewmode = 2131165494; // aapt resource value: 0x7f070077 public const int afc_progress_bar = 2131165303; @@ -2303,14 +2306,14 @@ namespace keepass2android // aapt resource value: 0x7f0700c7 public const int create = 2131165383; - // aapt resource value: 0x7f07012b - public const int cred_password = 2131165483; + // aapt resource value: 0x7f070132 + public const int cred_password = 2131165490; - // aapt resource value: 0x7f07012c - public const int cred_remember_mode = 2131165484; + // aapt resource value: 0x7f070133 + public const int cred_remember_mode = 2131165491; - // aapt resource value: 0x7f07012a - public const int cred_username = 2131165482; + // aapt resource value: 0x7f070131 + public const int cred_username = 2131165489; // aapt resource value: 0x7f070029 public const int default_activity_button = 2131165225; @@ -2537,8 +2540,8 @@ namespace keepass2android // aapt resource value: 0x7f0700ec public const int group_text = 2131165420; - // aapt resource value: 0x7f070128 - public const int help = 2131165480; + // aapt resource value: 0x7f07012f + public const int help = 2131165487; // aapt resource value: 0x7f070017 public const int home = 2131165207; @@ -2576,6 +2579,9 @@ namespace keepass2android // aapt resource value: 0x7f0700fd public const int init_otp = 2131165437; + // aapt resource value: 0x7f07012c + public const int initial_dir = 2131165484; + // aapt resource value: 0x7f0700e6 public const int insert_element = 2131165414; @@ -2627,53 +2633,53 @@ namespace keepass2android // aapt resource value: 0x7f07002a public const int list_item = 2131165226; - // aapt resource value: 0x7f07013a - public const int menu_about = 2131165498; - - // aapt resource value: 0x7f070139 - public const int menu_app_settings = 2131165497; - - // aapt resource value: 0x7f070138 - public const int menu_cancel_edit = 2131165496; + // aapt resource value: 0x7f070141 + public const int menu_about = 2131165505; // aapt resource value: 0x7f070140 - public const int menu_change_db = 2131165504; - - // aapt resource value: 0x7f07013c - public const int menu_change_master_key = 2131165500; - - // aapt resource value: 0x7f070131 - public const int menu_donate = 2131165489; - - // aapt resource value: 0x7f070133 - public const int menu_goto_url = 2131165491; - - // aapt resource value: 0x7f070134 - public const int menu_lock = 2131165492; - - // aapt resource value: 0x7f070136 - public const int menu_rate = 2131165494; - - // aapt resource value: 0x7f07013b - public const int menu_search = 2131165499; + public const int menu_app_settings = 2131165504; // aapt resource value: 0x7f07013f - public const int menu_search_advanced = 2131165503; + public const int menu_cancel_edit = 2131165503; - // aapt resource value: 0x7f07013e - public const int menu_sort = 2131165502; + // aapt resource value: 0x7f070147 + public const int menu_change_db = 2131165511; - // aapt resource value: 0x7f070135 - public const int menu_suggest_improvements = 2131165493; + // aapt resource value: 0x7f070143 + public const int menu_change_master_key = 2131165507; + + // aapt resource value: 0x7f070138 + public const int menu_donate = 2131165496; + + // aapt resource value: 0x7f07013a + public const int menu_goto_url = 2131165498; + + // aapt resource value: 0x7f07013b + public const int menu_lock = 2131165499; // aapt resource value: 0x7f07013d - public const int menu_sync = 2131165501; + public const int menu_rate = 2131165501; - // aapt resource value: 0x7f070132 - public const int menu_toggle_pass = 2131165490; + // aapt resource value: 0x7f070142 + public const int menu_search = 2131165506; - // aapt resource value: 0x7f070137 - public const int menu_translate = 2131165495; + // aapt resource value: 0x7f070146 + public const int menu_search_advanced = 2131165510; + + // aapt resource value: 0x7f070145 + public const int menu_sort = 2131165509; + + // aapt resource value: 0x7f07013c + public const int menu_suggest_improvements = 2131165500; + + // aapt resource value: 0x7f070144 + public const int menu_sync = 2131165508; + + // aapt resource value: 0x7f070139 + public const int menu_toggle_pass = 2131165497; + + // aapt resource value: 0x7f07013e + public const int menu_translate = 2131165502; // aapt resource value: 0x7f070015 public const int middle = 2131165205; @@ -2774,6 +2780,9 @@ namespace keepass2android // aapt resource value: 0x7f070053 public const int plugin1 = 2131165267; + // aapt resource value: 0x7f070128 + public const int portsep = 2131165480; + // aapt resource value: 0x7f070037 public const int progress_circular = 2131165239; @@ -2849,6 +2858,21 @@ namespace keepass2android // aapt resource value: 0x7f070122 public const int select_other_entry = 2131165474; + // aapt resource value: 0x7f070127 + public const int sftp_host = 2131165479; + + // aapt resource value: 0x7f07012d + public const int sftp_initial_dir = 2131165485; + + // aapt resource value: 0x7f07012b + public const int sftp_password = 2131165483; + + // aapt resource value: 0x7f070129 + public const int sftp_port = 2131165481; + + // aapt resource value: 0x7f07012a + public const int sftp_user = 2131165482; + // aapt resource value: 0x7f07002f public const int shortcut = 2131165231; @@ -2867,8 +2891,8 @@ namespace keepass2android // aapt resource value: 0x7f0700c1 public const int start_create = 2131165377; - // aapt resource value: 0x7f070127 - public const int start_create_import = 2131165479; + // aapt resource value: 0x7f07012e + public const int start_create_import = 2131165486; // aapt resource value: 0x7f0700bf public const int start_open_file = 2131165375; @@ -2885,8 +2909,8 @@ namespace keepass2android // aapt resource value: 0x7f070003 public const int terrain = 2131165187; - // aapt resource value: 0x7f070129 - public const int text = 2131165481; + // aapt resource value: 0x7f070130 + public const int text = 2131165488; // aapt resource value: 0x7f0700ce public const int textView = 2131165390; @@ -3212,16 +3236,19 @@ namespace keepass2android public const int set_password = 2130903118; // aapt resource value: 0x7f03004f - public const int StartScreenButtons = 2130903119; + public const int sftpcredentials = 2130903119; // aapt resource value: 0x7f030050 - public const int support_simple_spinner_dropdown_item = 2130903120; + public const int StartScreenButtons = 2130903120; // aapt resource value: 0x7f030051 - public const int text_with_help = 2130903121; + public const int support_simple_spinner_dropdown_item = 2130903121; // aapt resource value: 0x7f030052 - public const int url_credentials = 2130903122; + public const int text_with_help = 2130903122; + + // aapt resource value: 0x7f030053 + public const int url_credentials = 2130903123; static Layout() { @@ -3364,53 +3391,56 @@ namespace keepass2android // aapt resource value: 0x7f0801d0 public const int CannotMoveGroupHere = 2131231184; - // aapt resource value: 0x7f0801ff - public const int CertificateFailure = 2131231231; - - // aapt resource value: 0x7f0801fe - public const int CertificateWarning = 2131231230; - - // aapt resource value: 0x7f08020d - public const int ChangeLog = 2131231245; - - // aapt resource value: 0x7f08020c - public const int ChangeLog_0_7 = 2131231244; - - // aapt resource value: 0x7f08020a - public const int ChangeLog_0_8 = 2131231242; - - // aapt resource value: 0x7f080209 - public const int ChangeLog_0_8_1 = 2131231241; - - // aapt resource value: 0x7f080208 - public const int ChangeLog_0_8_2 = 2131231240; - - // aapt resource value: 0x7f080207 - public const int ChangeLog_0_8_3 = 2131231239; - - // aapt resource value: 0x7f080206 - public const int ChangeLog_0_8_4 = 2131231238; - - // aapt resource value: 0x7f080205 - public const int ChangeLog_0_8_5 = 2131231237; - - // aapt resource value: 0x7f080204 - public const int ChangeLog_0_8_6 = 2131231236; - // aapt resource value: 0x7f080203 - public const int ChangeLog_0_9 = 2131231235; + public const int CertificateFailure = 2131231235; // aapt resource value: 0x7f080202 - public const int ChangeLog_0_9_1 = 2131231234; + public const int CertificateWarning = 2131231234; - // aapt resource value: 0x7f080201 - public const int ChangeLog_0_9_2 = 2131231233; + // aapt resource value: 0x7f080212 + public const int ChangeLog = 2131231250; + + // aapt resource value: 0x7f080211 + public const int ChangeLog_0_7 = 2131231249; + + // aapt resource value: 0x7f08020f + public const int ChangeLog_0_8 = 2131231247; + + // aapt resource value: 0x7f08020e + public const int ChangeLog_0_8_1 = 2131231246; + + // aapt resource value: 0x7f08020d + public const int ChangeLog_0_8_2 = 2131231245; + + // aapt resource value: 0x7f08020c + public const int ChangeLog_0_8_3 = 2131231244; // aapt resource value: 0x7f08020b - public const int ChangeLog_keptDonate = 2131231243; + public const int ChangeLog_0_8_4 = 2131231243; - // aapt resource value: 0x7f080200 - public const int ChangeLog_title = 2131231232; + // aapt resource value: 0x7f08020a + public const int ChangeLog_0_8_5 = 2131231242; + + // aapt resource value: 0x7f080209 + public const int ChangeLog_0_8_6 = 2131231241; + + // aapt resource value: 0x7f080208 + public const int ChangeLog_0_9 = 2131231240; + + // aapt resource value: 0x7f080207 + public const int ChangeLog_0_9_1 = 2131231239; + + // aapt resource value: 0x7f080206 + public const int ChangeLog_0_9_2 = 2131231238; + + // aapt resource value: 0x7f080205 + public const int ChangeLog_0_9_3 = 2131231237; + + // aapt resource value: 0x7f080210 + public const int ChangeLog_keptDonate = 2131231248; + + // aapt resource value: 0x7f080204 + public const int ChangeLog_title = 2131231236; // aapt resource value: 0x7f080095 public const int CheckForFileChangesOnSave_key = 2131230869; @@ -3445,14 +3475,14 @@ namespace keepass2android // aapt resource value: 0x7f0801c2 public const int CouldNotSaveToRemote = 2131231170; - // aapt resource value: 0x7f0801f1 - public const int CouldntLoadOtpAuxFile = 2131231217; + // aapt resource value: 0x7f0801f5 + public const int CouldntLoadOtpAuxFile = 2131231221; - // aapt resource value: 0x7f0801f2 - public const int CouldntLoadOtpAuxFile_Hint = 2131231218; + // aapt resource value: 0x7f0801f6 + public const int CouldntLoadOtpAuxFile_Hint = 2131231222; - // aapt resource value: 0x7f0801f8 - public const int CouldntParseOtpSecret = 2131231224; + // aapt resource value: 0x7f0801fc + public const int CouldntParseOtpSecret = 2131231228; // aapt resource value: 0x7f0800a4 public const int CreditsText = 2131230884; @@ -3472,8 +3502,8 @@ namespace keepass2android // aapt resource value: 0x7f0801ce public const int ErrorOcurred = 2131231182; - // aapt resource value: 0x7f0801fa - public const int ErrorUpdatingOtpAuxFile = 2131231226; + // aapt resource value: 0x7f0801fe + public const int ErrorUpdatingOtpAuxFile = 2131231230; // aapt resource value: 0x7f0800bc public const int FileHandling_prefs = 2131230908; @@ -3529,8 +3559,8 @@ namespace keepass2android // aapt resource value: 0x7f080196 public const int OpenKp2aKeyboardAutomatically_title = 2131231126; - // aapt resource value: 0x7f0801f9 - public const int OtpKeyError = 2131231225; + // aapt resource value: 0x7f0801fd + public const int OtpKeyError = 2131231229; // aapt resource value: 0x7f0801b4 public const int ParsingDatabase = 2131231156; @@ -3634,8 +3664,8 @@ namespace keepass2android // aapt resource value: 0x7f080179 public const int SaveAttachment_doneMessage = 2131231097; - // aapt resource value: 0x7f0801fb - public const int SavingOtpAuxFile = 2131231227; + // aapt resource value: 0x7f0801ff + public const int SavingOtpAuxFile = 2131231231; // aapt resource value: 0x7f0801b0 public const int SettingPassword = 2131231152; @@ -4048,8 +4078,8 @@ namespace keepass2android // aapt resource value: 0x7f0800bd public const int brackets = 2131230909; - // aapt resource value: 0x7f0801e5 - public const int button_change_location = 2131231205; + // aapt resource value: 0x7f0801e9 + public const int button_change_location = 2131231209; // aapt resource value: 0x7f0800be public const int cancel = 2131230910; @@ -4159,8 +4189,8 @@ namespace keepass2android // aapt resource value: 0x7f080184 public const int database_loaded_unlocked = 2131231108; - // aapt resource value: 0x7f0801e2 - public const int database_location = 2131231202; + // aapt resource value: 0x7f0801e6 + public const int database_location = 2131231206; // aapt resource value: 0x7f08013a public const int database_name = 2131231034; @@ -4219,6 +4249,9 @@ namespace keepass2android // aapt resource value: 0x7f080166 public const int enter_filename_details_url = 2131231078; + // aapt resource value: 0x7f0801d7 + public const int enter_sftp_login_title = 2131231191; + // aapt resource value: 0x7f0800cf public const int entry_accessed = 2131230927; @@ -4270,8 +4303,8 @@ namespace keepass2android // aapt resource value: 0x7f0800dd public const int entry_user_name = 2131230941; - // aapt resource value: 0x7f0801ed - public const int error_adding_keyfile = 2131231213; + // aapt resource value: 0x7f0801f1 + public const int error_adding_keyfile = 2131231217; // aapt resource value: 0x7f0800e0 public const int error_can_not_handle_uri = 2131230944; @@ -4342,44 +4375,44 @@ namespace keepass2android // aapt resource value: 0x7f0800f2 public const int file_browser = 2131230962; + // aapt resource value: 0x7f0801e5 + public const int filestorage_setup_title = 2131231205; + // aapt resource value: 0x7f0801e1 - public const int filestorage_setup_title = 2131231201; - - // aapt resource value: 0x7f0801dd - public const int filestoragehelp_dropboxKP2A = 2131231197; - - // aapt resource value: 0x7f0801d6 - public const int filestoragename_androidget = 2131231190; - - // aapt resource value: 0x7f0801d7 - public const int filestoragename_androidsend = 2131231191; - - // aapt resource value: 0x7f0801db - public const int filestoragename_dropbox = 2131231195; - - // aapt resource value: 0x7f0801dc - public const int filestoragename_dropboxKP2A = 2131231196; - - // aapt resource value: 0x7f0801d5 - public const int filestoragename_file = 2131231189; - - // aapt resource value: 0x7f0801d8 - public const int filestoragename_ftp = 2131231192; - - // aapt resource value: 0x7f0801de - public const int filestoragename_gdrive = 2131231198; - - // aapt resource value: 0x7f0801d9 - public const int filestoragename_http = 2131231193; + public const int filestoragehelp_dropboxKP2A = 2131231201; // aapt resource value: 0x7f0801da - public const int filestoragename_https = 2131231194; + public const int filestoragename_androidget = 2131231194; - // aapt resource value: 0x7f0801e0 - public const int filestoragename_sftp = 2131231200; + // aapt resource value: 0x7f0801db + public const int filestoragename_androidsend = 2131231195; // aapt resource value: 0x7f0801df - public const int filestoragename_skydrive = 2131231199; + public const int filestoragename_dropbox = 2131231199; + + // aapt resource value: 0x7f0801e0 + public const int filestoragename_dropboxKP2A = 2131231200; + + // aapt resource value: 0x7f0801d9 + public const int filestoragename_file = 2131231193; + + // aapt resource value: 0x7f0801dc + public const int filestoragename_ftp = 2131231196; + + // aapt resource value: 0x7f0801e2 + public const int filestoragename_gdrive = 2131231202; + + // aapt resource value: 0x7f0801dd + public const int filestoragename_http = 2131231197; + + // aapt resource value: 0x7f0801de + public const int filestoragename_https = 2131231198; + + // aapt resource value: 0x7f0801e4 + public const int filestoragename_sftp = 2131231204; + + // aapt resource value: 0x7f0801e3 + public const int filestoragename_skydrive = 2131231203; // aapt resource value: 0x7f08006e public const int further_author_names = 2131230830; @@ -4390,20 +4423,20 @@ namespace keepass2android // aapt resource value: 0x7f0800f3 public const int generate_password = 2131230963; - // aapt resource value: 0x7f0801fd - public const int get_regular_version = 2131231229; + // aapt resource value: 0x7f080201 + public const int get_regular_version = 2131231233; // aapt resource value: 0x7f0800f4 public const int group = 2131230964; - // aapt resource value: 0x7f0801e3 - public const int help_database_location = 2131231203; - - // aapt resource value: 0x7f0801ea - public const int help_key_file = 2131231210; - // aapt resource value: 0x7f0801e7 - public const int help_master_password = 2131231207; + public const int help_database_location = 2131231207; + + // aapt resource value: 0x7f0801ee + public const int help_key_file = 2131231214; + + // aapt resource value: 0x7f0801eb + public const int help_master_password = 2131231211; // aapt resource value: 0x7f0800f5 public const int hint_comment = 2131230965; @@ -4411,8 +4444,8 @@ namespace keepass2android // aapt resource value: 0x7f0800f6 public const int hint_conf_pass = 2131230966; - // aapt resource value: 0x7f0801e4 - public const int hint_database_location = 2131231204; + // aapt resource value: 0x7f0801e8 + public const int hint_database_location = 2131231208; // aapt resource value: 0x7f0800f7 public const int hint_generated_password = 2131230967; @@ -4420,8 +4453,8 @@ namespace keepass2android // aapt resource value: 0x7f0800f8 public const int hint_group_name = 2131230968; - // aapt resource value: 0x7f0801eb - public const int hint_key_file = 2131231211; + // aapt resource value: 0x7f0801ef + public const int hint_key_file = 2131231215; // aapt resource value: 0x7f0800f9 public const int hint_keyfile = 2131230969; @@ -4432,8 +4465,8 @@ namespace keepass2android // aapt resource value: 0x7f0800fc public const int hint_login_pass = 2131230972; - // aapt resource value: 0x7f0801e8 - public const int hint_master_password = 2131231208; + // aapt resource value: 0x7f0801ec + public const int hint_master_password = 2131231212; // aapt resource value: 0x7f0800ff public const int hint_override_url = 2131230975; @@ -4441,6 +4474,12 @@ namespace keepass2android // aapt resource value: 0x7f0800fb public const int hint_pass = 2131230971; + // aapt resource value: 0x7f0801d4 + public const int hint_sftp_host = 2131231188; + + // aapt resource value: 0x7f0801d5 + public const int hint_sftp_port = 2131231189; + // aapt resource value: 0x7f080100 public const int hint_tags = 2131230976; @@ -4465,8 +4504,11 @@ namespace keepass2android // aapt resource value: 0x7f080016 public const int ime_name = 2131230742; - // aapt resource value: 0x7f0801ee - public const int init_otp = 2131231214; + // aapt resource value: 0x7f0801f2 + public const int init_otp = 2131231218; + + // aapt resource value: 0x7f0801d6 + public const int initial_directory = 2131231190; // aapt resource value: 0x7f080148 public const int insert_element_here = 2131231048; @@ -4480,8 +4522,8 @@ namespace keepass2android // aapt resource value: 0x7f08006f public const int issues = 2131230831; - // aapt resource value: 0x7f0801e9 - public const int key_file = 2131231209; + // aapt resource value: 0x7f0801ed + public const int key_file = 2131231213; // aapt resource value: 0x7f080105 public const int keyfile_does_not_exist = 2131230981; @@ -4528,8 +4570,8 @@ namespace keepass2android // aapt resource value: 0x7f080108 public const int list_size_title = 2131230984; - // aapt resource value: 0x7f0801fc - public const int loading = 2131231228; + // aapt resource value: 0x7f080200 + public const int loading = 2131231232; // aapt resource value: 0x7f08010a public const int loading_database = 2131230986; @@ -4549,8 +4591,8 @@ namespace keepass2android // aapt resource value: 0x7f08012e public const int master_key_type = 2131231022; - // aapt resource value: 0x7f0801e6 - public const int master_password = 2131231206; + // aapt resource value: 0x7f0801ea + public const int master_password = 2131231210; // aapt resource value: 0x7f08010f public const int menu_about = 2131230991; @@ -4663,26 +4705,26 @@ namespace keepass2android // aapt resource value: 0x7f0801cd public const int otp_aux_file = 2131231181; - // aapt resource value: 0x7f0801f5 - public const int otp_discarded_because_db_open = 2131231221; - - // aapt resource value: 0x7f0801f3 - public const int otp_discarded_because_no_db = 2131231219; - - // aapt resource value: 0x7f0801f4 - public const int otp_discarded_no_space = 2131231220; - - // aapt resource value: 0x7f0801ef - public const int otp_explanation = 2131231215; - - // aapt resource value: 0x7f0801f0 - public const int otp_hint = 2131231216; - - // aapt resource value: 0x7f0801f6 - public const int otps_pending = 2131231222; + // aapt resource value: 0x7f0801f9 + public const int otp_discarded_because_db_open = 2131231225; // aapt resource value: 0x7f0801f7 - public const int otpsecret_hint = 2131231223; + public const int otp_discarded_because_no_db = 2131231223; + + // aapt resource value: 0x7f0801f8 + public const int otp_discarded_no_space = 2131231224; + + // aapt resource value: 0x7f0801f3 + public const int otp_explanation = 2131231219; + + // aapt resource value: 0x7f0801f4 + public const int otp_hint = 2131231220; + + // aapt resource value: 0x7f0801fa + public const int otps_pending = 2131231226; + + // aapt resource value: 0x7f0801fb + public const int otpsecret_hint = 2131231227; // aapt resource value: 0x7f08012c public const int pass_filename = 2131231020; @@ -4777,8 +4819,8 @@ namespace keepass2android // aapt resource value: 0x7f080146 public const int select_other_entry = 2131231046; - // aapt resource value: 0x7f0801d4 - public const int select_storage_type = 2131231188; + // aapt resource value: 0x7f0801d8 + public const int select_storage_type = 2131231192; // aapt resource value: 0x7f0800ae public const int short_app_name = 2131230894; @@ -4846,8 +4888,8 @@ namespace keepass2android // aapt resource value: 0x7f08014c public const int uppercase = 2131231052; - // aapt resource value: 0x7f0801ec - public const int use_key_file = 2131231212; + // aapt resource value: 0x7f0801f0 + public const int use_key_file = 2131231216; // aapt resource value: 0x7f080150 public const int version_history = 2131231056; diff --git a/src/keepass2android/Resources/drawable-hdpi/ic_storage_sftp.png b/src/keepass2android/Resources/drawable-hdpi/ic_storage_sftp.png new file mode 100644 index 00000000..b56c0fc5 Binary files /dev/null and b/src/keepass2android/Resources/drawable-hdpi/ic_storage_sftp.png differ diff --git a/src/keepass2android/Resources/drawable/ic_storage_sftp.png b/src/keepass2android/Resources/drawable/ic_storage_sftp.png new file mode 100644 index 00000000..2155f6cd Binary files /dev/null and b/src/keepass2android/Resources/drawable/ic_storage_sftp.png differ diff --git a/src/keepass2android/Resources/layout/sftp_credentials.axml b/src/keepass2android/Resources/layout/sftp_credentials.axml new file mode 100644 index 00000000..f36879d2 --- /dev/null +++ b/src/keepass2android/Resources/layout/sftp_credentials.axml @@ -0,0 +1,61 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/keepass2android/Resources/layout/sftpcredentials.xml b/src/keepass2android/Resources/layout/sftpcredentials.xml new file mode 100644 index 00000000..d67a5d55 --- /dev/null +++ b/src/keepass2android/Resources/layout/sftpcredentials.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/keepass2android/Resources/values-de/strings.xml b/src/keepass2android/Resources/values-de/strings.xml index 595333f2..9a7ad5ec 100644 --- a/src/keepass2android/Resources/values-de/strings.xml +++ b/src/keepass2android/Resources/values-de/strings.xml @@ -321,7 +321,7 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die Wenn du Keepass2Android nicht den Zugriff auf die gesamte Dropbox erlauben möchtest, kannst du diese Option wählen. Dann musst du nur Zugriff auf den Ordner Apps/Keepass2Android gewähren. Das ist besonders sinnvoll, wenn du eine neue Datenbank anlegst. Wenn du schon eine Datenbank hast, kannst du diese Option wählen um den Ordner anzulegen, und dann die Datei (vom PC aus) in den neuen Ordner kopieren. Wähle die Option dann nochmal zum Laden der Datei. Google Drive SkyDrive - SFTP (SSH File Transfer Protocol) + SFTP (SSH File Transfer) Dateizugriff initialisieren Speicherort der Datenbank Du kannst deine Datenbank lokal auf deinem Android-Gerät oder in der Cloud speichern (nur in der Nicht-Offline-Version). Keepass2Android macht die Datenbank dann auch verfügbar, wenn du offline bist. Da die Datenbank sicher mit der AES 256-Bit-Verschlüsselung geschützt ist, erhält auch dann niemand außer dir Zugriff auf deine Datenbank. Wir empfehlen die Benutzung von Dropbox: Es ist auf allen Geräten verfügbar und bietet automatisch Backups aller Dateiversionen. diff --git a/src/keepass2android/Resources/values/strings.xml b/src/keepass2android/Resources/values/strings.xml index 4fbf6b8f..88a7df64 100644 --- a/src/keepass2android/Resources/values/strings.xml +++ b/src/keepass2android/Resources/values/strings.xml @@ -328,7 +328,13 @@ Tell me more! No, I don\'t like it that much + host (ex: 192.168.0.1) + port + Initial directory (optional): + Enter SFTP login data: + Select the storage type: + Local file Get from third-party app @@ -341,7 +347,7 @@ If you do not want to give KP2A access to your full Dropbox, you may select this option. It will request only access to the folder Apps/Keepass2Android. This is especially suited when creating a new database. If you already have a database, click this option to create the folder, then place your file inside the folder (from your PC) and then select this option again for opening the file. Google Drive SkyDrive - SFTP (SSH File Transfer Protocol) + SFTP (SSH File Transfer) File access initialization @@ -385,6 +391,12 @@ Change log + + Version 0.9.3 preview\n + * Added SFTP support\n + * Bug fixes\n + + Version 0.9.2\n * Added OTP support (compatible with OtpKeyProv plugin)\n diff --git a/src/keepass2android/Utils/Util.cs b/src/keepass2android/Utils/Util.cs index c544968b..d5768c90 100644 --- a/src/keepass2android/Utils/Util.cs +++ b/src/keepass2android/Utils/Util.cs @@ -212,6 +212,33 @@ namespace keepass2android public delegate bool FileSelectedHandler(string filename); + public static void ShowSftpDialog(Activity activity, FileSelectedHandler onStartBrowse) + { + AlertDialog.Builder builder = new AlertDialog.Builder(activity); + View dlgContents = activity.LayoutInflater.Inflate(Resource.Layout.sftpcredentials, null); + builder.SetView(dlgContents); + builder.SetPositiveButton(Android.Resource.String.Ok, + (sender, args) => + { + string host = dlgContents.FindViewById(Resource.Id.sftp_host).Text; + string portText = dlgContents.FindViewById(Resource.Id.sftp_port).Text; + int port = Keepass2android.Javafilestorage.SftpStorage.DefaultSftpPort; + if (!string.IsNullOrEmpty(portText)) + int.TryParse(portText, out port); + string user = dlgContents.FindViewById(Resource.Id.sftp_user).Text; + string password = dlgContents.FindViewById(Resource.Id.sftp_password).Text; + string initialPath = dlgContents.FindViewById(Resource.Id.sftp_initial_dir).Text; + string sftpPath = new Keepass2android.Javafilestorage.SftpStorage().BuildFullPath(host, port, initialPath, user, + password); + onStartBrowse(sftpPath); + }); + builder.SetNegativeButton(Android.Resource.String.Cancel, (sender, args) => {}); + builder.SetTitle(activity.GetString(Resource.String.enter_sftp_login_title)); + Dialog dialog = builder.Create(); + + dialog.Show(); + } + public static void ShowFilenameDialog(Activity activity, FileSelectedHandler onOpen, FileSelectedHandler onCreate, bool showBrowseButton, string defaultFilename, string detailsText, int requestCodeBrowse) { diff --git a/src/keepass2android/app/App.cs b/src/keepass2android/app/App.cs index 145ca6cd..43e02024 100644 --- a/src/keepass2android/app/App.cs +++ b/src/keepass2android/app/App.cs @@ -399,6 +399,7 @@ namespace keepass2android new DropboxAppFolderFileStorage(Application.Context, this), new GoogleDriveFileStorage(Application.Context, this), new SkyDriveFileStorage(Application.Context, this), + new SftpFileStorage(this), #endif #endif new BuiltInFileStorage(this) diff --git a/src/keepass2android/fileselect/FileSelectActivity.cs b/src/keepass2android/fileselect/FileSelectActivity.cs index 34932466..c82ce354 100644 --- a/src/keepass2android/fileselect/FileSelectActivity.cs +++ b/src/keepass2android/fileselect/FileSelectActivity.cs @@ -321,8 +321,10 @@ namespace keepass2android OnActivityResult, defaultPath => { - - Util.ShowFilenameDialog(this, OnOpenButton, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url), + if (defaultPath.StartsWith("sftp://")) + Util.ShowSftpDialog(this, OnReceivedSftpData); + else + Util.ShowFilenameDialog(this, OnOpenButton, null, false, defaultPath, GetString(Resource.String.enter_filename_details_url), Intents.RequestCodeFileBrowseForOpen); } ), false, 0, protocolId); @@ -377,7 +379,19 @@ namespace keepass2android Toast.MakeText(this, data.GetStringExtra("EXTRA_ERROR_MESSAGE"), ToastLength.Long).Show(); } } - #if !EXCLUDE_FILECHOOSER + + private bool OnReceivedSftpData(string filename) + { + IOConnectionInfo ioc = new IOConnectionInfo { Path = filename }; +#if !EXCLUDE_FILECHOOSER + StartFileChooser(ioc.Path); +#else + LaunchPasswordActivityForIoc(ioc); +#endif + return true; + } + +#if !EXCLUDE_FILECHOOSER private void StartFileChooser(string defaultPath) { Kp2aLog.Log("FSA: defaultPath="+defaultPath); diff --git a/src/keepass2android/keepass2android.csproj b/src/keepass2android/keepass2android.csproj index 7e559988..e4d71306 100644 --- a/src/keepass2android/keepass2android.csproj +++ b/src/keepass2android/keepass2android.csproj @@ -20,16 +20,17 @@ v4.2 - + 1G + armeabi,armeabi-v7a True full False bin\Debug - DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE + DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE prompt 4 False @@ -114,14 +115,14 @@ - - + + @@ -166,11 +167,6 @@ - - - - -
    @@ -212,6 +208,9 @@ AndroidResource + + Designer + False @@ -904,4 +903,10 @@ + + + + + + \ No newline at end of file