You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2014/01/29 12:02:11 UTC
[1/5] git commit: More checks for ciphers before actually executing
the test
Updated Branches:
refs/heads/master a5e32ddae -> 03aa3979d
More checks for ciphers before actually executing the test
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/1d800d37
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/1d800d37
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/1d800d37
Branch: refs/heads/master
Commit: 1d800d37ab473ec3704ee879d05033375f2ec88c
Parents: a5e32dd
Author: Guillaume Nodet <gn...@apache.org>
Authored: Wed Jan 29 10:14:09 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Wed Jan 29 10:14:09 2014 +0100
----------------------------------------------------------------------
.../src/test/java/org/apache/sshd/CipherTest.java | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1d800d37/sshd-core/src/test/java/org/apache/sshd/CipherTest.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/test/java/org/apache/sshd/CipherTest.java b/sshd-core/src/test/java/org/apache/sshd/CipherTest.java
index c992ff5..0b7e2d1 100644
--- a/sshd-core/src/test/java/org/apache/sshd/CipherTest.java
+++ b/sshd-core/src/test/java/org/apache/sshd/CipherTest.java
@@ -61,7 +61,7 @@ public class CipherTest {
@Test
public void testAES192CBC() throws Exception {
- if (SecurityUtils.isBouncyCastleRegistered()) {
+ if (SecurityUtils.isBouncyCastleRegistered() && checkCipher(com.jcraft.jsch.jce.AES192CBC.class.getName())) {
setUp(new AES192CBC.Factory());
runTest();
}
@@ -69,7 +69,7 @@ public class CipherTest {
@Test
public void testAES256CBC() throws Exception {
- if (SecurityUtils.isBouncyCastleRegistered()) {
+ if (SecurityUtils.isBouncyCastleRegistered() && checkCipher(com.jcraft.jsch.jce.AES256CBC.class.getName())) {
setUp(new AES256CBC.Factory());
runTest();
}
@@ -156,4 +156,18 @@ public class CipherTest {
c.disconnect();
s.disconnect();
}
+
+ static boolean checkCipher(String cipher){
+ try{
+ Class c=Class.forName(cipher);
+ com.jcraft.jsch.Cipher _c = (com.jcraft.jsch.Cipher)(c.newInstance());
+ _c.init(com.jcraft.jsch.Cipher.ENCRYPT_MODE,
+ new byte[_c.getBlockSize()],
+ new byte[_c.getIVSize()]);
+ return true;
+ }
+ catch(Exception e){
+ return false;
+ }
+ }
}
[2/5] Add more moduli for DHGEX
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/1ea3dfe2/sshd-core/src/main/filtered-resources/org/apache/sshd/moduli
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/filtered-resources/org/apache/sshd/moduli b/sshd-core/src/main/filtered-resources/org/apache/sshd/moduli
index 0504d9c..cbeac9e 100644
--- a/sshd-core/src/main/filtered-resources/org/apache/sshd/moduli
+++ b/sshd-core/src/main/filtered-resources/org/apache/sshd/moduli
@@ -191,8 +191,70 @@
20140127162755 2 6 100 4095 2 C082C6D5214016F2748DBC7D756DF9A769F0FCA6A162ACAF8DF354C82684FA5D6471B940AB4283F6BF477624A7A880AE06B1AB60E0EA339B0875244F28869D5661A0DC75425A889F6BD03E937983F896DB02E3E5D782F68B7463E88DEC396ED8C03F7F832DD1D1056EAC8444AEB64C73DB754BAAFCB4CBD642CD5C6257794434494E8A2DFBA7EAA108935B4045CB49EE0E6A2EB6E75E72CFF6B9B7BE69A61D44511EE6CA207C43012CE8DA86C293AD25FE9B3610806DF16CEE48537784CCF04C2A3AA5F1CE5CA302E3D5B07B925B32910A72CCDAC361582836287AF4E7D20A0C314EC58292EDC1C67E9DEE7FC0A88A1ADCE1C6EC45D2398E523858892086888B60E12CD3374A454BF59890A98B4D7A784B64D809CB59207CF9360193C920896F731DA355CABDFCBDF827EFB03D300D94AB207C52B00E78146680A793F3EA65D4428F1BC2456AACDC99985DB10934182F431195FB517DC37F643360EC34859E86D49602E1A2454204982F4AECBC4C7411322E4FCD4AE8EE5076B0D4707E61878EF568FE50AC8B4786DDC2AD7391B8FA9D23651A5D695DF30A4C29CEFB57ABC21DE062D4C16E345AB416CCF69B3AA2C8076BD7730DDD2AF3249D7AA5D0613439F38DC97536758BF31687122B6D5FC32AEA7E306020A5DA4CBC719F9BFCB1E17EE1968D21E
CCBAAB24923B7D7FFF30714C4713472C0BBF4D846D39E0215E33A50EB
20140127163207 2 6 100 4095 2 C082C6D5214016F2748DBC7D756DF9A769F0FCA6A162ACAF8DF354C82684FA5D6471B940AB4283F6BF477624A7A880AE06B1AB60E0EA339B0875244F28869D5661A0DC75425A889F6BD03E937983F896DB02E3E5D782F68B7463E88DEC396ED8C03F7F832DD1D1056EAC8444AEB64C73DB754BAAFCB4CBD642CD5C6257794434494E8A2DFBA7EAA108935B4045CB49EE0E6A2EB6E75E72CFF6B9B7BE69A61D44511EE6CA207C43012CE8DA86C293AD25FE9B3610806DF16CEE48537784CCF04C2A3AA5F1CE5CA302E3D5B07B925B32910A72CCDAC361582836287AF4E7D20A0C314EC58292EDC1C67E9DEE7FC0A88A1ADCE1C6EC45D2398E523858892086888B60E12CD3374A454BF59890A98B4D7A784B64D809CB59207CF9360193C920896F731DA355CABDFCBDF827EFB03D300D94AB207C52B00E78146680A793F3EA65D4428F1BC2456AACDC99985DB10934182F431195FB517DC37F643360EC34859E86D49602E1A2454204982F4AECBC4C7411322E4FCD4AE8EE5076B0D4707E61878EF568FE50AC8B4786DDC2AD7391B8FA9D23651A5D695DF30A4C29CEFB57ABC21DE062D4C16E345AB416CCF69B3AA2C8076BD7730DDD2AF3249D7AA5D0613439F38DC97536758BF31687122B6D5FC32AEA7E306020A5DA4CBC719F9BFCB1E17EE1968D21E
CCBAAB24923B7D7FFF30714C4713472C0BBF4D846D39E0215E4237843
20140127164725 2 6 100 4095 2 C082C6D5214016F2748DBC7D756DF9A769F0FCA6A162ACAF8DF354C82684FA5D6471B940AB4283F6BF477624A7A880AE06B1AB60E0EA339B0875244F28869D5661A0DC75425A889F6BD03E937983F896DB02E3E5D782F68B7463E88DEC396ED8C03F7F832DD1D1056EAC8444AEB64C73DB754BAAFCB4CBD642CD5C6257794434494E8A2DFBA7EAA108935B4045CB49EE0E6A2EB6E75E72CFF6B9B7BE69A61D44511EE6CA207C43012CE8DA86C293AD25FE9B3610806DF16CEE48537784CCF04C2A3AA5F1CE5CA302E3D5B07B925B32910A72CCDAC361582836287AF4E7D20A0C314EC58292EDC1C67E9DEE7FC0A88A1ADCE1C6EC45D2398E523858892086888B60E12CD3374A454BF59890A98B4D7A784B64D809CB59207CF9360193C920896F731DA355CABDFCBDF827EFB03D300D94AB207C52B00E78146680A793F3EA65D4428F1BC2456AACDC99985DB10934182F431195FB517DC37F643360EC34859E86D49602E1A2454204982F4AECBC4C7411322E4FCD4AE8EE5076B0D4707E61878EF568FE50AC8B4786DDC2AD7391B8FA9D23651A5D695DF30A4C29CEFB57ABC21DE062D4C16E345AB416CCF69B3AA2C8076BD7730DDD2AF3249D7AA5D0613439F38DC97536758BF31687122B6D5FC32AEA7E306020A5DA4CBC719F9BFCB1E17EE1968D21E
CCBAAB24923B7D7FFF30714C4713472C0BBF4D846D39E0215E7483963
-#
+20140127153847 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67495FE2CAFF
+20140127155006 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674960B4CB3B
+20140127155244 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674960DA0077
+20140127161220 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B6749624E28F7
+20140127164409 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B6749649C4E7B
+20140127164838 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674964D8ED63
+20140127170427 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674966275EDB
+20140127171339 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674966DCA593
+20140127173958 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674969029D67
+20140127175621 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67496A63DC2F
+20140127183032 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67496B9C842F
+20140127191446 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67496F84A9C3
+20140127221132 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674970C52A43
+20140127233749 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674977C6B72F
+20140128001200 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67497AA81907
+20140128002233 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67497B8F8C33
+20140128071028 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67497E6C8E1B
+20140128075101 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674981A806EB
+20140128080531 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674982C07257
+20140128085557 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674986FCB3B7
+20140128091050 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67498834366B
+20140128092003 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674988ECCDC3
+20140128093442 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67498A16F1BF
+20140128101520 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67498D5F2933
+20140128105516 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B674990B67C43
+20140128112506 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67499328E877
+20140128113709 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B6749942B8BDF
+20140128114938 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67499535D7BB
+20140128130910 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67499B294BE7
+20140128131726 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67499BD22FE7
+20140128132330 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67499C46B163
+20140128135052 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67499E4EE58B
+20140128140553 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B67499F7869EB
+20140128142434 2 6 100 6143 5 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B6749A0E7E07F
+20140128144629 2 6 100 6143 2 D1A0D510832FFDC8C85B7D88F15B390C9732BD815FF78F80745C4E8CAA2D44FBEB2B5A899EEE74BBB6578827FE640055BA9443ED5E17CA5EB1A1EC40BB35A1E2364D609681FC8598AD443D7099E99070FB47934683DAAC08FBEF1D4C4F027B4035EC06C856D56E71A24418F46B59867DD9EC08F4049322279D54876850055A23543889B8EB10A8A5C69064A7AAB5A4D47886A0B7A0D445849BD9F934E2C760B03D970B36E8A6C986D7375E4A919EF2CDE615727B795C4421C6E6C75F5B05185C6BB21EB3470E825098A2056E0CD08DA7E71433F0276324CCB886A9EFE81072C71BEEA1540D12E90EB4F5360CDAF653D3BBF79E99B4A380E41DC36A0ECB4CF62E365B6C000F520C088F671BC41308E060137F39E5B3C5B457C1DA6C8AB7F49788954882E9D821ADD1B32946E93083AF43FF2BFDD1DAB780243BC5A49C76BDB760401DBA4FA4784AB6D6266F7A96481A42DF41A37468DCB2590634FB9CFA12C4EF39D7E7F2D5E9B69BA7AC9BC6E220936EFC0F582E7D987948E7FC06DBD3A3B327A0BEB47632D8C0B48950A73421AA5DD56EAEF55805E9B292A6C2ABA1D15B70B1FCDD65726938A2A348479FD884BE1D555B3B30610E6B520D5FAAE4A502165D264D104F8DCAFF53EF95EA656CAFFD4FE8B5EAB36BAAE5CB35E03F9A7DDC2EEFAE0E43E82
07C3FB21ABF4387C53A4B0293479358580003717A21704029F64537CD8F1E894F47FD2C47E9F8529F69149AE17E656AD3B540A1E169BE27C1FE1015161BB14AE1595E6D7538DBD6ACB35BBE4BD08226450FDB79AA0F18BFD7C1DBF7734DE15427AA2FF77C39B7DCDB95BB77DD8F73EBF77A560116AC2CB3D6B8E4C03335F518BFB89F68E9B9EDD1637199FAE18122560807481F71CFDBB064D6089D096F6F24C9BAB95D06B9FBB402D6D0EB42A3B49C16ADBB7DDA9FD6BDA2C16588DC0A5E536DBD15D3CD3D8EE9EC0D87821882E88C61B9FB54B8CAD17E0A61A7AA49A2634F63E25B1369298EEB3A98124FFFDA08CE2AE1F31A630039A846A049F412D5B8F0B8836F9D864099A16D7D8AD1CD52F87D5760612035A91B6749A2836F3B
+20140127185120 2 6 100 7669 2 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CAD6D9B43
+20140127221849 2 6 100 7669 2 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CAFA3B87B
+20140127234504 2 6 100 7669 5 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CB38FE6E7
+20140128081253 2 6 100 7669 5 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CB9D91ECF
+20140128083705 2 6 100 7669 2 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CBAF67C3B
+20140128090727 2 6 100 7669 2 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CBC6A316B
+20140128094023 2 6 100 7669 5 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CBDE9DE37
+20140128115717 2 6 100 7669 2 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CC44B3BF3
+20140128145631 2 6 100 7669 2 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CCC3477DB
+20140128154502 2 6 100 7669 5 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CCE62734F
+20140128160200 2 6 100 7669 2 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CCF2D50A3
+20140128162142 2 6 100 7669 2 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CD01657BB
+20140128165549 2 6 100 7669 5 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CD1BA1327
+20140128213518 2 6 100 7669 2 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CDE012663
+20140128225939 2 6 100 7669 5 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69C022DBA00658C1D6C2D5A8D7EBFF0A5D662436247F7146332E2582D3FBE2FB6FB1D9B42F4108987B0FBB6B1139B5424ED923729782DFCD38592AC0BBB02C76D0B6A982E1B11116C7132632D08BA79A4100ADFFC5F10D634B453AB2137EBCD075888FA1AFC924116753847570DE375A38A4FA3E8A402D9384E286E811AB0CAD5C9EFEAE5419B833CE1FB1EDF
+20140128234252 2 6 100 7669 2 3EBBC157E30944F37FBBA2C1557F183EA5F1B56A337B7CF3D473DAF0C433A574BE6AD0AC0575D46837D24AFC69B59B734656E2EC48BAC56A7C0F4BC55E31DB777DAE179AF31851987319FD0ACA05D7D77D3201FC21E058D2E3DB8DCC370FCADB86FAA3682141D834718F91CFDB22B6573DA5221F7FF2E847FB27A74B3A149ADA43D4F2CFAC22E3CE52AE5BB3EC2C562C277570CAA8426918D376231782DA4976030A3887090846756E80B8F0CFE40EC286E6E3219A0B372A9B2F709598EC22D38EE361B9B1E95594D09608BAAD85B64C04FF26402AA41A49EB7315A58809A09ADAF7A9F0DEC06883CB24AD6DBF2BD0A97656605A4376AB3B18639885691172305BA1979E8FC0420B1FD14A1A45E99EE786A55762AD1B12FDBE97484A8B56AE48A3A4DF66D0B51E3FC6425B7D7701A2BD34681264E1ECC3A1CB4593993ADE7BA401DE125D3DF1C93B8943A3ADB0EDA8BB74188B1A91B7224443C5482CF239B4C150AF92889C20C8ACA6B4E1579BCB89C17020E697E459111A7B6B8A6376E56631AD23852933C5F27E845CDA350AA15C2F196B42244E0C1CBFCFAE6EF85B1C9DA9EF7E22C5F66E0D528E9CBFFB36F9D1B54492A5CE4E7EB3A9C5FD47667A8FF62E58690AFB7F800AA9493D9B81B770E745D0D5677F93195E1B829EF7B0F5A4E84AD8861B9
CA6537274D11D29F0274927E337D8FD6D8258D9C278B7E313856F94B93DF3FCB9AA4A7DA43D4C62242DB9DBB57293B72F9599BC8494DE936556C6BDD403D5992AC2AEA730506A843E6B448E8756FB08374BA4280C7A0021E11E18ACB4BD7E04F609C1650E247E87D599406DBE4FB402041E9DCEAE09DCA9934AB48600D4B16FCE1479A4F0BF9059A3477373665B4F2D63452EA5E7BCE9EDE911816A82A8A3F89335E6BDB1A7B2A9CB496E7E9EDB479348B273AB52CE91D4A206FFC5F8688577F2B0B155C1987FA2516749052D89FECB2DC9BF97014C1E9CB228E9F77B4996D696C167D7D4C877CB8B564CCC89F56CDDB867D7DA320642275800A317E45AD0ADD0B89132CD6228F60A2AD2397F7B8BD7D554C790696EEF5976CF1E6E906DED1AB94AE5E76C9777B939422139762202BF18E21A58FA681BFE8E5D86E09CB3EB821B512F89EACB550F9368BD8297EE4DF69
<TRUNCATED>
[4/5] [SSHD-282] Abstract the SSH Service to make it more pluggable
Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
new file mode 100644
index 0000000..2f7b070
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java
@@ -0,0 +1,271 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.session;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.sshd.agent.common.AgentForwardSupport;
+import org.apache.sshd.client.channel.AbstractClientChannel;
+import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.TcpipForwarder;
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.DefaultCloseFuture;
+import org.apache.sshd.common.future.SshFuture;
+import org.apache.sshd.common.future.SshFutureListener;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.server.x11.X11ForwardSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base implementation of ConnectionService.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public abstract class AbstractConnectionService implements ConnectionService {
+
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ /** Map of channels keyed by the identifier */
+ protected final Map<Integer, Channel> channels = new ConcurrentHashMap<Integer, Channel>();
+ /** Next channel identifier */
+ protected static final AtomicInteger nextChannelId = new AtomicInteger(100);
+
+ protected final Session session;
+
+ /** The tcpip forwarder */
+ protected final TcpipForwarder tcpipForwarder;
+ protected final AgentForwardSupport agentForward;
+ protected final X11ForwardSupport x11Forward;
+ protected final CloseFuture closeFuture;
+ protected volatile boolean closing;
+
+ protected AbstractConnectionService(Session session) {
+ this.session = session;
+ agentForward = new AgentForwardSupport(this);
+ x11Forward = new X11ForwardSupport(this);
+ tcpipForwarder = session.getFactoryManager().getTcpipForwarderFactory().create(this);
+ closeFuture = new DefaultCloseFuture(getSession().getLock());
+ }
+
+ public AbstractSession getSession() {
+ return (AbstractSession) session;
+ }
+
+ public void start() {
+ }
+
+ public TcpipForwarder getTcpipForwarder() {
+ return tcpipForwarder;
+ }
+
+ public CloseFuture close(boolean immediately) {
+ tcpipForwarder.close();
+ agentForward.close();
+ x11Forward.close();
+ synchronized (getSession().getLock()) {
+ if (!closing) {
+ try {
+ closing = true;
+ log.debug("Closing session");
+ List<Channel> channelToClose = new ArrayList<Channel>(channels.values());
+ if (channelToClose.size() > 0) {
+ final AtomicInteger latch = new AtomicInteger(channelToClose.size());
+ for (Channel channel : channelToClose) {
+ log.debug("Closing channel {}", channel.getId());
+ channel.close(immediately).addListener(new SshFutureListener() {
+ public void operationComplete(SshFuture sshFuture) {
+ if (latch.decrementAndGet() == 0) {
+ closeFuture.setClosed();
+ }
+ }
+ });
+ }
+ } else {
+ closeFuture.setClosed();
+ }
+ } catch (Throwable t) {
+ log.warn("Error closing session", t);
+ }
+ }
+ return closeFuture;
+ }
+ }
+
+ protected int getNextChannelId() {
+ return nextChannelId.incrementAndGet();
+ }
+
+ /**
+ * Register a newly created channel with a new unique identifier
+ *
+ * @param channel the channel to register
+ * @return the id of this channel
+ * @throws Exception
+ */
+ public int registerChannel(Channel channel) throws IOException {
+ int channelId = getNextChannelId();
+ channel.init(this, session, channelId);
+ channels.put(channelId, channel);
+ return channelId;
+ }
+
+ /**
+ * Remove this channel from the list of managed channels
+ *
+ * @param channel the channel
+ */
+ public void unregisterChannel(Channel channel) {
+ channels.remove(channel.getId());
+ }
+
+ public void channelOpenConfirmation(Buffer buffer) throws IOException {
+ Channel channel = getChannel(buffer);
+ log.debug("Received SSH_MSG_CHANNEL_OPEN_CONFIRMATION on channel {}", channel.getId());
+ int recipient = buffer.getInt();
+ int rwsize = buffer.getInt();
+ int rmpsize = buffer.getInt();
+ channel.handleOpenSuccess(recipient, rwsize, rmpsize, buffer);
+ }
+
+ public void channelOpenFailure(Buffer buffer) throws IOException {
+ AbstractClientChannel channel = (AbstractClientChannel) getChannel(buffer);
+ log.debug("Received SSH_MSG_CHANNEL_OPEN_FAILURE on channel {}", channel.getId());
+ channels.remove(channel.getId());
+ channel.handleOpenFailure(buffer);
+ }
+
+ /**
+ * Process incoming data on a channel
+ *
+ * @param buffer the buffer containing the data
+ * @throws IOException if an error occurs
+ */
+ public void channelData(Buffer buffer) throws IOException {
+ Channel channel = getChannel(buffer);
+ channel.handleData(buffer);
+ }
+
+ /**
+ * Process incoming extended data on a channel
+ *
+ * @param buffer the buffer containing the data
+ * @throws IOException if an error occurs
+ */
+ public void channelExtendedData(Buffer buffer) throws IOException {
+ Channel channel = getChannel(buffer);
+ channel.handleExtendedData(buffer);
+ }
+
+ /**
+ * Process a window adjust packet on a channel
+ *
+ * @param buffer the buffer containing the window adjustement parameters
+ * @throws IOException if an error occurs
+ */
+ public void channelWindowAdjust(Buffer buffer) throws IOException {
+ try {
+ Channel channel = getChannel(buffer);
+ channel.handleWindowAdjust(buffer);
+ } catch (SshException e) {
+ log.info(e.getMessage());
+ }
+ }
+
+ /**
+ * Process end of file on a channel
+ *
+ * @param buffer the buffer containing the packet
+ * @throws IOException if an error occurs
+ */
+ public void channelEof(Buffer buffer) throws IOException {
+ Channel channel = getChannel(buffer);
+ channel.handleEof();
+ }
+
+ /**
+ * Close a channel due to a close packet received
+ *
+ * @param buffer the buffer containing the packet
+ * @throws IOException if an error occurs
+ */
+ public void channelClose(Buffer buffer) throws IOException {
+ Channel channel = getChannel(buffer);
+ channel.handleClose();
+ unregisterChannel(channel);
+ }
+
+ /**
+ * Service a request on a channel
+ *
+ * @param buffer the buffer containing the request
+ * @throws IOException if an error occurs
+ */
+ public void channelRequest(Buffer buffer) throws IOException {
+ Channel channel = getChannel(buffer);
+ String type = buffer.getString();
+ boolean wantReply = buffer.getBoolean();
+ boolean success = channel.handleRequest(type, buffer);
+ if (wantReply) {
+ Buffer replyBuffer = session.createBuffer(
+ success ? SshConstants.Message.SSH_MSG_CHANNEL_SUCCESS
+ : SshConstants.Message.SSH_MSG_CHANNEL_FAILURE, 0);
+ replyBuffer.putInt(channel.getRecipient());
+ session.writePacket(replyBuffer);
+ }
+ }
+
+ /**
+ * Process a failure on a channel
+ *
+ * @param buffer the buffer containing the packet
+ * @throws IOException if an error occurs
+ */
+ public void channelFailure(Buffer buffer) throws IOException {
+ Channel channel = getChannel(buffer);
+ channel.handleFailure();
+ }
+
+ /**
+ * Retrieve the channel designated by the given packet
+ *
+ * @param buffer the incoming packet
+ * @return the target channel
+ * @throws IOException if the channel does not exists
+ */
+ protected Channel getChannel(Buffer buffer) throws IOException {
+ int recipient = buffer.getInt();
+ Channel channel = channels.get(recipient);
+ if (channel == null) {
+ buffer.rpos(buffer.rpos() - 5);
+ SshConstants.Message cmd = buffer.getCommand();
+ throw new SshException("Received " + cmd + " on unknown channel " + recipient);
+ }
+ return channel;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
index 7766a53..a7c6ec7 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
@@ -37,6 +37,7 @@ import org.apache.sshd.common.KeyExchange;
import org.apache.sshd.common.Mac;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Random;
+import org.apache.sshd.common.Service;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.SessionListener;
import org.apache.sshd.common.SshConstants;
@@ -84,8 +85,6 @@ public abstract class AbstractSession implements Session {
protected final IoSession ioSession;
/** The pseudo random generator */
protected final Random random;
- /** The tcpip forwarder */
- protected final TcpipForwarder tcpipForwarder;
/** Lock object for this session state */
protected final Object lock = new Object();
/**
@@ -96,10 +95,8 @@ public abstract class AbstractSession implements Session {
protected volatile boolean closing;
/** Boolean indicating if this session has been authenticated or not */
protected boolean authed;
- /** Map of channels keyed by the identifier */
- protected final Map<Integer, Channel> channels = new ConcurrentHashMap<Integer, Channel>();
- /** Next channel identifier */
- protected static AtomicInteger nextChannelId = new AtomicInteger(100);
+ /** The name of the authenticated useer */
+ protected String username;
/** Session listener */
protected final List<SessionListener> listeners = new ArrayList<SessionListener>();
@@ -140,7 +137,8 @@ public abstract class AbstractSession implements Session {
protected final Object requestLock = new Object();
protected final AtomicReference<Buffer> requestResult = new AtomicReference<Buffer>();
protected final Map<AttributeKey<?>, Object> attributes = new ConcurrentHashMap<AttributeKey<?>, Object>();
- protected String username;
+
+ protected Service currentService;
private volatile State state = State.ReceiveKexInit;
@@ -154,7 +152,7 @@ public abstract class AbstractSession implements Session {
this.factoryManager = factoryManager;
this.ioSession = ioSession;
this.random = factoryManager.getRandomFactory().create();
- this.tcpipForwarder = factoryManager.getTcpipForwarderFactory().create(this);
+// this.tcpipForwarder = factoryManager.getTcpipForwarderFactory().create(this);
}
/**
@@ -245,6 +243,15 @@ public abstract class AbstractSession implements Session {
return factoryManager;
}
+ public boolean isAuthenticated() {
+ return authed;
+ }
+
+ public void setAuthenticated(String username) {
+ this.authed = true;
+ this.username = username;
+ }
+
/**
* Main input point for the MINA framework.
*
@@ -292,7 +299,6 @@ public abstract class AbstractSession implements Session {
* {@link org.apache.sshd.common.SshException}.
*
* @param t the exception to process
- * @throws IOException
*/
public void exceptionCaught(Throwable t) {
// Ignore exceptions that happen while closing
@@ -339,26 +345,17 @@ public abstract class AbstractSession implements Session {
}
}
}
- tcpipForwarder.close();
synchronized (lock) {
if (!closing) {
try {
closing = true;
- log.debug("Closing session");
- List<Channel> channelToClose = new ArrayList<Channel>(channels.values());
- if (channelToClose.size() > 0) {
- final AtomicInteger latch = new AtomicInteger(channelToClose.size());
- for (Channel channel : channelToClose) {
- log.debug("Closing channel {}", channel.getId());
- channel.close(immediately).addListener(new SshFutureListener() {
- public void operationComplete(SshFuture sshFuture) {
- if (latch.decrementAndGet() == 0) {
- log.debug("Closing IoSession");
- ioSession.close(true).addListener(new IoSessionCloser());
- }
- }
- });
- }
+ if (currentService != null) {
+ currentService.close(immediately).addListener(new SshFutureListener<CloseFuture>() {
+ public void operationComplete(CloseFuture future) {
+ log.debug("Closing IoSession");
+ ioSession.close(immediately).addListener(new IoSessionCloser());
+ }
+ });
} else {
log.debug("Closing IoSession");
ioSession.close(immediately).addListener(new IoSessionCloser());
@@ -1002,18 +999,19 @@ public abstract class AbstractSession implements Session {
}
+ /*
protected int getNextChannelId() {
return nextChannelId.incrementAndGet();
}
public int registerChannel(Channel channel) throws IOException {
int channelId = getNextChannelId();
- channel.init(this, channelId);
+ channel.init(this, session, channelId);
channels.put(channelId, channel);
return channelId;
}
- protected void channelOpenConfirmation(Buffer buffer) throws IOException {
+ public void channelOpenConfirmation(Buffer buffer) throws IOException {
Channel channel = getChannel(buffer);
log.debug("Received SSH_MSG_CHANNEL_OPEN_CONFIRMATION on channel {}", channel.getId());
int recipient = buffer.getInt();
@@ -1022,42 +1020,24 @@ public abstract class AbstractSession implements Session {
channel.handleOpenSuccess(recipient, rwsize, rmpsize, buffer);
}
- protected void channelOpenFailure(Buffer buffer) throws IOException {
+ public void channelOpenFailure(Buffer buffer) throws IOException {
AbstractClientChannel channel = (AbstractClientChannel) getChannel(buffer);
log.debug("Received SSH_MSG_CHANNEL_OPEN_FAILURE on channel {}", channel.getId());
channels.remove(channel.getId());
channel.handleOpenFailure(buffer);
}
- /**
- * Process incoming data on a channel
- *
- * @param buffer the buffer containing the data
- * @throws Exception if an error occurs
- */
- protected void channelData(Buffer buffer) throws IOException {
+ public void channelData(Buffer buffer) throws IOException {
Channel channel = getChannel(buffer);
channel.handleData(buffer);
}
- /**
- * Process incoming extended data on a channel
- *
- * @param buffer the buffer containing the data
- * @throws Exception if an error occurs
- */
- protected void channelExtendedData(Buffer buffer) throws IOException {
+ public void channelExtendedData(Buffer buffer) throws IOException {
Channel channel = getChannel(buffer);
channel.handleExtendedData(buffer);
}
- /**
- * Process a window adjust packet on a channel
- *
- * @param buffer the buffer containing the window adjustement parameters
- * @throws Exception if an error occurs
- */
- protected void channelWindowAdjust(Buffer buffer) throws IOException {
+ public void channelWindowAdjust(Buffer buffer) throws IOException {
try {
Channel channel = getChannel(buffer);
channel.handleWindowAdjust(buffer);
@@ -1066,45 +1046,22 @@ public abstract class AbstractSession implements Session {
}
}
- /**
- * Process end of file on a channel
- *
- * @param buffer the buffer containing the packet
- * @throws Exception if an error occurs
- */
- protected void channelEof(Buffer buffer) throws IOException {
+ public void channelEof(Buffer buffer) throws IOException {
Channel channel = getChannel(buffer);
channel.handleEof();
}
- /**
- * Close a channel due to a close packet received
- *
- * @param buffer the buffer containing the packet
- * @throws Exception if an error occurs
- */
- protected void channelClose(Buffer buffer) throws IOException {
+ public void channelClose(Buffer buffer) throws IOException {
Channel channel = getChannel(buffer);
channel.handleClose();
unregisterChannel(channel);
}
- /**
- * Remove this channel from the list of managed channels
- *
- * @param channel the channel
- */
public void unregisterChannel(Channel channel) {
channels.remove(channel.getId());
}
- /**
- * Service a request on a channel
- *
- * @param buffer the buffer containing the request
- * @throws Exception if an error occurs
- */
- protected void channelRequest(Buffer buffer) throws IOException {
+ public void channelRequest(Buffer buffer) throws IOException {
Channel channel = getChannel(buffer);
String type = buffer.getString();
boolean wantReply = buffer.getBoolean();
@@ -1118,24 +1075,11 @@ public abstract class AbstractSession implements Session {
}
}
- /**
- * Process a failure on a channel
- *
- * @param buffer the buffer containing the packet
- * @throws Exception if an error occurs
- */
- protected void channelFailure(Buffer buffer) throws IOException {
+ public void channelFailure(Buffer buffer) throws IOException {
Channel channel = getChannel(buffer);
channel.handleFailure();
}
- /**
- * Retrieve the channel designated by the given packet
- *
- * @param buffer the incoming packet
- * @return the target channel
- * @throws IOException if the channel does not exists
- */
protected Channel getChannel(Buffer buffer) throws IOException {
int recipient = buffer.getInt();
Channel channel = channels.get(recipient);
@@ -1146,6 +1090,7 @@ public abstract class AbstractSession implements Session {
}
return channel;
}
+ */
/**
* Retrieve a configuration property as an integer
@@ -1193,6 +1138,10 @@ public abstract class AbstractSession implements Session {
return username;
}
+ public Object getLock() {
+ return lock;
+ }
+
/**
* {@inheritDoc}
*/
@@ -1215,10 +1164,4 @@ public abstract class AbstractSession implements Session {
}
}
- /**
- * {@inheritDoc}
- */
- public TcpipForwarder getTcpipForwarder() {
- return this.tcpipForwarder;
- }
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java
new file mode 100644
index 0000000..600986a
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/ConnectionService.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common.session;
+
+import java.io.IOException;
+
+import org.apache.sshd.agent.local.AgentForwardedChannel;
+import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.TcpipForwarder;
+
+/**
+ * Interface implementing ssh-connection service.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface ConnectionService extends Service {
+
+ /**
+ * Register a newly created channel with a new unique identifier
+ *
+ * @param channel the channel to register
+ * @return the id of this channel
+ * @throws Exception
+ */
+ int registerChannel(Channel channel) throws IOException;
+
+ /**
+ * Remove this channel from the list of managed channels
+ *
+ * @param channel the channel
+ */
+ void unregisterChannel(Channel channel);
+
+ /**
+ * Retrieve the tcpip forwarder
+ * @return
+ */
+ TcpipForwarder getTcpipForwarder();
+
+ // TODO: remove from interface, it's server side only
+ String initAgentForward() throws IOException;
+
+ // TODO: remove from interface, it's server side only
+ String createX11Display(boolean singleConnection, String authenticationProtocol, String authenticationCookie, int screen) throws IOException;
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
index 11ca72b..638dfcb 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
@@ -494,7 +494,7 @@ public class ChannelSession extends AbstractServerChannel {
return false;
}
- String authSocket = ((ServerSession) session).initAgentForward();
+ String authSocket = service.initAgentForward();
addEnvVariable(SshAgent.SSH_AUTHSOCKET_ENV_NAME, authSocket);
return true;
}
@@ -506,7 +506,7 @@ public class ChannelSession extends AbstractServerChannel {
return false;
}
- String display = ((ServerSession) session).createX11Display(buffer.getBoolean(), buffer.getString(),
+ String display = service.createX11Display(buffer.getBoolean(), buffer.getString(),
buffer.getString(), buffer.getInt());
if (display == null) {
return false;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
new file mode 100644
index 0000000..b5a4461
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerConnectionService.java
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.server.session;
+
+import java.io.IOException;
+
+import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.ServiceFactory;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.SshdSocketAddress;
+import org.apache.sshd.common.future.SshFutureListener;
+import org.apache.sshd.common.session.AbstractConnectionService;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.server.channel.OpenChannelException;
+
+/**
+ * Server side <code>ssh-connection</code> service.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ServerConnectionService extends AbstractConnectionService {
+
+ public static class Factory implements ServiceFactory {
+
+ public String getName() {
+ return "ssh-connection";
+ }
+
+ public Service create(Session session) throws IOException {
+ return new ServerConnectionService(session);
+ }
+ }
+
+
+ private boolean allowMoreSessions = true;
+
+ protected ServerConnectionService(Session s) throws SshException {
+ super(s);
+ if (!(s instanceof ServerSession)) {
+ throw new IllegalStateException("Server side service used on client side");
+ }
+ ServerSession session = (ServerSession) s;
+ if (!session.isAuthenticated()) {
+ throw new SshException("Session is not authenticated");
+ }
+ }
+
+ public void process(SshConstants.Message cmd, Buffer buffer) throws Exception {
+ switch (cmd) {
+ case SSH_MSG_CHANNEL_OPEN:
+ channelOpen(buffer);
+ break;
+ case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
+ channelOpenConfirmation(buffer);
+ break;
+ case SSH_MSG_CHANNEL_OPEN_FAILURE:
+ channelOpenFailure(buffer);
+ break;
+ case SSH_MSG_CHANNEL_REQUEST:
+ channelRequest(buffer);
+ break;
+ case SSH_MSG_CHANNEL_DATA:
+ channelData(buffer);
+ break;
+ case SSH_MSG_CHANNEL_EXTENDED_DATA:
+ channelExtendedData(buffer);
+ break;
+ case SSH_MSG_CHANNEL_FAILURE:
+ channelFailure(buffer);
+ break;
+ case SSH_MSG_CHANNEL_WINDOW_ADJUST:
+ channelWindowAdjust(buffer);
+ break;
+ case SSH_MSG_CHANNEL_EOF:
+ channelEof(buffer);
+ break;
+ case SSH_MSG_CHANNEL_CLOSE:
+ channelClose(buffer);
+ break;
+ case SSH_MSG_GLOBAL_REQUEST:
+ globalRequest(buffer);
+ break;
+ default:
+ throw new IllegalStateException("Unsupported command: " + cmd);
+ }
+ }
+
+ private void channelOpen(Buffer buffer) throws Exception {
+ String type = buffer.getString();
+ final int id = buffer.getInt();
+ final int rwsize = buffer.getInt();
+ final int rmpsize = buffer.getInt();
+
+ log.debug("Received SSH_MSG_CHANNEL_OPEN {}", type);
+
+ if (closing) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+ buf.putInt(id);
+ buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
+ buf.putString("SSH server is shutting down: " + type);
+ buf.putString("");
+ session.writePacket(buf);
+ return;
+ }
+ if (!allowMoreSessions) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+ buf.putInt(id);
+ buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
+ buf.putString("additional sessions disabled");
+ buf.putString("");
+ session.writePacket(buf);
+ return;
+ }
+
+ final Channel channel = NamedFactory.Utils.create(session.getFactoryManager().getChannelFactories(), type);
+ if (channel == null) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+ buf.putInt(id);
+ buf.putInt(SshConstants.SSH_OPEN_UNKNOWN_CHANNEL_TYPE);
+ buf.putString("Unsupported channel type: " + type);
+ buf.putString("");
+ session.writePacket(buf);
+ return;
+ }
+
+ final int channelId = registerChannel(channel);
+ channel.open(id, rwsize, rmpsize, buffer).addListener(new SshFutureListener<OpenFuture>() {
+ public void operationComplete(OpenFuture future) {
+ try {
+ if (future.isOpened()) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 0);
+ buf.putInt(id);
+ buf.putInt(channelId);
+ buf.putInt(channel.getLocalWindow().getSize());
+ buf.putInt(channel.getLocalWindow().getPacketSize());
+ session.writePacket(buf);
+ } else if (future.getException() != null) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+ buf.putInt(id);
+ if (future.getException() instanceof OpenChannelException) {
+ buf.putInt(((OpenChannelException) future.getException()).getReasonCode());
+ buf.putString(future.getException().getMessage());
+ } else {
+ buf.putInt(0);
+ buf.putString("Error opening channel: " + future.getException().getMessage());
+ }
+ buf.putString("");
+ session.writePacket(buf);
+ }
+ } catch (IOException e) {
+ session.exceptionCaught(e);
+ }
+ }
+ });
+ }
+
+ private void globalRequest(Buffer buffer) throws Exception {
+ String req = buffer.getString();
+ boolean wantReply = buffer.getBoolean();
+ log.debug("Received global request {}", req);
+ if (req.startsWith("keepalive@")) {
+ // Relatively standard KeepAlive directive, just wants failure
+ } else if (req.equals("no-more-sessions@openssh.com")) {
+ allowMoreSessions = false;
+ } else if (req.equals("tcpip-forward")) {
+ String address = buffer.getString();
+ int port = buffer.getInt();
+ try {
+ SshdSocketAddress bound = tcpipForwarder.localPortForwardingRequested(new SshdSocketAddress(address, port));
+ port = bound.getPort();
+ if (wantReply){
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_REQUEST_SUCCESS, 0);
+ buffer.putInt(port);
+ session.writePacket(buffer);
+ }
+ } catch (Exception e) {
+ log.debug("Error starting tcpip forward", e);
+ if (wantReply) {
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_REQUEST_FAILURE, 0);
+ session.writePacket(buffer);
+ }
+ }
+ return;
+ } else if (req.equals("cancel-tcpip-forward")) {
+ String address = buffer.getString();
+ int port = buffer.getInt();
+ tcpipForwarder.localPortForwardingCancelled(new SshdSocketAddress(address, port));
+ if (wantReply){
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_REQUEST_SUCCESS, 0);
+ session.writePacket(buffer);
+ }
+ return;
+ } else {
+ log.debug("Received SSH_MSG_GLOBAL_REQUEST {}", req);
+ log.warn("Unknown global request: {}", req);
+ }
+ if (wantReply) {
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_REQUEST_FAILURE, 0);
+ session.writePacket(buffer);
+ }
+ }
+
+ public String initAgentForward() throws IOException {
+ return agentForward.initialize();
+ }
+
+ public String createX11Display(boolean singleConnection, String authenticationProtocol, String authenticationCookie, int screen) throws IOException {
+ return x11Forward.createDisplay(singleConnection, authenticationProtocol, authenticationCookie, screen);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
index fe80f7c..9fc2a14 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerSession.java
@@ -28,10 +28,12 @@ import java.util.concurrent.ScheduledExecutorService;
import org.apache.sshd.SshServer;
import org.apache.sshd.agent.common.AgentForwardSupport;
+import org.apache.sshd.agent.local.ChannelAgentForwarding;
import org.apache.sshd.client.future.OpenFuture;
import org.apache.sshd.common.Channel;
-import org.apache.sshd.common.KeyExchange;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.ServiceFactory;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.SshException;
import org.apache.sshd.common.SshdSocketAddress;
@@ -60,42 +62,21 @@ import org.apache.sshd.server.x11.X11ForwardSupport;
*/
public class ServerSession extends AbstractSession {
- private long authTimeoutTimestamp = 0L;
+ private long authTimeoutTimestamp;
private long idleTimeoutTimestamp = 0L;
- private int maxAuthRequests = 20;
- private int nbAuthRequests;
- private int authTimeoutMs = 10 * 60 * 1000; // 10 minutes in milliseconds
+ private int authTimeoutMs = 2 * 60 * 1000; // 2 minutes in milliseconds
private int idleTimeoutMs = 10 * 60 * 1000; // 10 minutes in milliseconds
- private boolean allowMoreSessions = true;
- private final AgentForwardSupport agentForward;
- private final X11ForwardSupport x11Forward;
-
- private List<NamedFactory<UserAuth>> userAuthFactories;
- private List<List<String>> authMethods;
- private String authUserName;
- private String authMethod;
- private String authService;
- private UserAuth currentAuth;
public ServerSession(ServerFactoryManager server, IoSession ioSession) throws Exception {
super(server, ioSession);
- maxAuthRequests = getIntProperty(ServerFactoryManager.MAX_AUTH_REQUESTS, maxAuthRequests);
authTimeoutMs = getIntProperty(ServerFactoryManager.AUTH_TIMEOUT, authTimeoutMs);
+ authTimeoutTimestamp = System.currentTimeMillis() + authTimeoutMs;
idleTimeoutMs = getIntProperty(ServerFactoryManager.IDLE_TIMEOUT, idleTimeoutMs);
- agentForward = new AgentForwardSupport(this);
- x11Forward = new X11ForwardSupport(this);
log.info("Session created from {}", ioSession.getRemoteAddress());
sendServerIdentification();
sendKexInit();
}
- @Override
- public CloseFuture close(boolean immediately) {
- agentForward.close();
- x11Forward.close();
- return super.close(immediately);
- }
-
public String getNegociated(int index) {
return negociated[index];
}
@@ -174,31 +155,29 @@ public class ServerSession extends AbstractSession {
}
log.debug("Received SSH_MSG_NEWKEYS");
receiveNewKeys(true);
- setState(State.WaitForAuth);
- resetAuthTimeout();
+ setState(State.WaitForServiceRequest);
break;
- case WaitForAuth:
+ case WaitForServiceRequest:
if (cmd != SshConstants.Message.SSH_MSG_SERVICE_REQUEST) {
log.debug("Expecting a {}, but received {}", SshConstants.Message.SSH_MSG_SERVICE_REQUEST, cmd);
notImplemented();
} else {
- String request = buffer.getString();
- log.debug("Received SSH_MSG_SERVICE_REQUEST '{}'", request);
- if ("ssh-userauth".equals(request)) {
- userAuth(buffer, null);
- } else {
- disconnect(SshConstants.SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE, "Bad service request: " + request);
+ String service = buffer.getString();
+ log.debug("Received SSH_MSG_SERVICE_REQUEST '{}'", service);
+ try {
+ startService(service);
+ } catch (Exception e) {
+ log.debug("Service " + service + " rejected", e);
+ disconnect(SshConstants.SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE, "Bad service request: " + service);
+ break;
}
+ log.debug("Accepted service {}", service);
+ Buffer response = createBuffer(SshConstants.Message.SSH_MSG_SERVICE_ACCEPT, 0);
+ response.putString(service);
+ writePacket(response);
+ setState(State.Running);
}
break;
- case UserAuth:
- if (cmd != SshConstants.Message.SSH_MSG_USERAUTH_REQUEST && currentAuth == null) {
- disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Protocol error: expected packet " + SshConstants.Message.SSH_MSG_USERAUTH_REQUEST + ", got " + cmd);
- return;
- }
- log.debug("Received " + cmd);
- userAuth(buffer, cmd);
- break;
case Running:
running(cmd, buffer);
resetIdleTimeout();
@@ -209,41 +188,12 @@ public class ServerSession extends AbstractSession {
}
}
+ public void startService(String name) throws Exception {
+ currentService = ServiceFactory.Utils.create(getFactoryManager().getServiceFactories(), name, this);
+ }
+
private void running(SshConstants.Message cmd, Buffer buffer) throws Exception {
switch (cmd) {
- case SSH_MSG_SERVICE_REQUEST:
- serviceRequest(buffer);
- break;
- case SSH_MSG_CHANNEL_OPEN:
- channelOpen(buffer);
- break;
- case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
- channelOpenConfirmation(buffer);
- break;
- case SSH_MSG_CHANNEL_OPEN_FAILURE:
- channelOpenFailure(buffer);
- break;
- case SSH_MSG_CHANNEL_REQUEST:
- channelRequest(buffer);
- break;
- case SSH_MSG_CHANNEL_DATA:
- channelData(buffer);
- break;
- case SSH_MSG_CHANNEL_EXTENDED_DATA:
- channelExtendedData(buffer);
- break;
- case SSH_MSG_CHANNEL_WINDOW_ADJUST:
- channelWindowAdjust(buffer);
- break;
- case SSH_MSG_CHANNEL_EOF:
- channelEof(buffer);
- break;
- case SSH_MSG_CHANNEL_CLOSE:
- channelClose(buffer);
- break;
- case SSH_MSG_GLOBAL_REQUEST:
- globalRequest(buffer);
- break;
case SSH_MSG_KEXINIT:
receiveKexInit(buffer);
sendKexInit();
@@ -261,7 +211,8 @@ public class ServerSession extends AbstractSession {
receiveNewKeys(true);
break;
default:
- throw new IllegalStateException("Unsupported command: " + cmd);
+ currentService.process(cmd, buffer);
+ break;
}
}
@@ -274,21 +225,16 @@ public class ServerSession extends AbstractSession {
protected void checkForTimeouts() throws IOException {
if (getState() != State.Closed) {
long now = System.currentTimeMillis();
- if (!authed && authTimeoutTimestamp > 0 && now > authTimeoutTimestamp) {
- disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "User authentication has timed out after " + authTimeoutMs + " ms.");
+ if (!authed && now > authTimeoutTimestamp) {
+ disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Session has timed out waiting for authentication after " + authTimeoutMs + " ms.");
}
-
if (idleTimeoutTimestamp > 0 && now > idleTimeoutTimestamp) {
- disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "User session has timed out after " + idleTimeoutMs + " ms.");
+ disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "User session has timed out idling after " + idleTimeoutMs + " ms.");
}
}
}
- private void resetAuthTimeout() {
- this.authTimeoutTimestamp = System.currentTimeMillis() + authTimeoutMs;
- }
-
- private void resetIdleTimeout() {
+ public void resetIdleTimeout() {
this.idleTimeoutTimestamp = System.currentTimeMillis() + idleTimeoutMs;
}
@@ -324,184 +270,6 @@ public class ServerSession extends AbstractSession {
I_C = receiveKexInit(buffer, clientProposal);
}
- private void serviceRequest(Buffer buffer) throws Exception {
- String request = buffer.getString();
- log.debug("Received SSH_MSG_SERVICE_REQUEST '{}'", request);
- // TODO: handle service requests
- disconnect(SshConstants.SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE, "Unsupported service request: " + request);
- }
-
- private void userAuth(Buffer buffer, SshConstants.Message cmd) throws Exception {
- if (getState() == State.WaitForAuth) {
- log.debug("Accepting user authentication request");
- buffer = createBuffer(SshConstants.Message.SSH_MSG_SERVICE_ACCEPT, 0);
- buffer.putString("ssh-userauth");
- writePacket(buffer);
- userAuthFactories = new ArrayList<NamedFactory<UserAuth>>(getServerFactoryManager().getUserAuthFactories());
- // Get authentication methods
- authMethods = new ArrayList<List<String>>();
- String mths = getServerFactoryManager().getProperties().get(SshServer.AUTH_METHODS);
- if (mths == null) {
- for (NamedFactory<UserAuth> uaf : getServerFactoryManager().getUserAuthFactories()) {
- authMethods.add(new ArrayList<String>(Collections.singletonList(uaf.getName())));
- }
- } else {
- for (String mthl : mths.split("\\s")) {
- authMethods.add(new ArrayList<String>(Arrays.asList(mthl.split(","))));
- }
- }
- // Verify all required methods are supported
- for (List<String> l : authMethods) {
- for (String m : l) {
- if (NamedFactory.Utils.get(userAuthFactories, m) == null) {
- throw new SshException("Configured method is not supported: " + m);
- }
- }
- }
- log.debug("Authorized authentication methods: {}", NamedFactory.Utils.getNames(userAuthFactories));
- setState(State.UserAuth);
-
- } else {
-
- Boolean authed = Boolean.FALSE;
-
- if (cmd == SshConstants.Message.SSH_MSG_USERAUTH_REQUEST) {
- if (this.currentAuth != null) {
- this.currentAuth.destroy();
- this.currentAuth = null;
- }
-
- String username = buffer.getString();
- String service = buffer.getString();
- String method = buffer.getString();
- if (this.authUserName == null || this.authService == null) {
- this.authUserName = username;
- this.authService = service;
- } else if (!this.authUserName.equals(username) || !this.authService.equals(service)) {
- disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR,
- "Change of username or service is not allowed (" + this.authUserName + ", " + this.authService + ") -> ("
- + username + ", " + service + ")");
- return;
- }
- this.authMethod = method;
- if (nbAuthRequests++ > maxAuthRequests) {
- disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Too many authentication failures");
- return;
- }
-
- log.debug("Authenticating user '{}' with service '{}' and method '{}'", new Object[] { username, service, method });
- NamedFactory<UserAuth> factory = NamedFactory.Utils.get(userAuthFactories, method);
- if (factory != null) {
- currentAuth = factory.create();
- try {
- authed = currentAuth.auth(this, username, service, buffer);
- } catch (Exception e) {
- // Continue
- log.debug("Authentication failed: {}", e.getMessage());
- }
- }
- } else {
- if (this.currentAuth == null) {
- // This should not happen
- throw new IllegalStateException();
- }
- buffer.rpos(buffer.rpos() - 1);
- try {
- authed = currentAuth.next(buffer);
- } catch (Exception e) {
- // Continue
- log.debug("Authentication failed: {}", e.getMessage());
- }
- }
-
- if (authed == null) {
- // authentication is still ongoing
- log.debug("Authentication not finished");
- } else if (authed) {
- log.debug("Authentication succeeded");
- username = currentAuth.getUserName();
-
- boolean success = false;
- for (List<String> l : authMethods) {
- if (!l.isEmpty() && l.get(0).equals(authMethod)) {
- l.remove(0);
- success |= l.isEmpty();
- }
- }
- if (success) {
- if (getFactoryManager().getProperties() != null) {
- String maxSessionCountAsString = getFactoryManager().getProperties().get(ServerFactoryManager.MAX_CONCURRENT_SESSIONS);
- if (maxSessionCountAsString != null) {
- int maxSessionCount = Integer.parseInt(maxSessionCountAsString);
- int currentSessionCount = getActiveSessionCountForUser(username);
- if (currentSessionCount >= maxSessionCount) {
- disconnect(SshConstants.SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE, "Too many concurrent connections");
- return;
- }
- }
- }
-
- String welcomeBanner = factoryManager.getProperties().get(ServerFactoryManager.WELCOME_BANNER);
- if (welcomeBanner != null) {
- buffer = createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_BANNER, 0);
- buffer.putString(welcomeBanner);
- buffer.putString("en");
- writePacket(buffer);
- }
-
- buffer = createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_SUCCESS, 0);
- writePacket(buffer);
- this.authed = true;
- setState(State.Running);
- resetIdleTimeout();
- log.info("Session {}@{} authenticated", getUsername(), getIoSession().getRemoteAddress());
-
- } else {
- buffer = createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_FAILURE, 0);
- StringBuilder sb = new StringBuilder();
- for (List<String> l : authMethods) {
- if (!l.isEmpty()) {
- if (sb.length() > 0) {
- sb.append(",");
- }
- sb.append(l.get(0));
- }
- }
- buffer.putString(sb.toString());
- buffer.putByte((byte) 1);
- writePacket(buffer);
- }
-
- currentAuth.destroy();
- currentAuth = null;
- } else {
- log.debug("Authentication failed");
-
- buffer = createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_FAILURE, 0);
- StringBuilder sb = new StringBuilder();
- for (List<String> l : authMethods) {
- if (!l.isEmpty()) {
- String m = l.get(0);
- if (!"none".equals(m)) {
- if (sb.length() > 0) {
- sb.append(",");
- }
- sb.append(l.get(0));
- }
- }
- }
- buffer.putString(sb.toString());
- buffer.putByte((byte) 0);
- writePacket(buffer);
-
- if (currentAuth != null) {
- currentAuth.destroy();
- currentAuth = null;
- }
- }
- }
- }
-
public KeyPair getHostKey() {
return factoryManager.getKeyPairProvider().loadKey(negociated[SshConstants.PROPOSAL_SERVER_HOST_KEY_ALGS]);
}
@@ -524,131 +292,6 @@ public class ServerSession extends AbstractSession {
return totalCount;
}
- private void channelOpen(Buffer buffer) throws Exception {
- String type = buffer.getString();
- final int id = buffer.getInt();
- final int rwsize = buffer.getInt();
- final int rmpsize = buffer.getInt();
-
- log.debug("Received SSH_MSG_CHANNEL_OPEN {}", type);
-
- if (closing) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
- buf.putInt(id);
- buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
- buf.putString("SSH server is shutting down: " + type);
- buf.putString("");
- writePacket(buf);
- return;
- }
- if (!allowMoreSessions) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
- buf.putInt(id);
- buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
- buf.putString("additional sessions disabled");
- buf.putString("");
- writePacket(buf);
- return;
- }
-
- final Channel channel = NamedFactory.Utils.create(getServerFactoryManager().getChannelFactories(), type);
- if (channel == null) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
- buf.putInt(id);
- buf.putInt(SshConstants.SSH_OPEN_UNKNOWN_CHANNEL_TYPE);
- buf.putString("Unsupported channel type: " + type);
- buf.putString("");
- writePacket(buf);
- return;
- }
-
- final int channelId = getNextChannelId();
- channels.put(channelId, channel);
- channel.init(this, channelId);
- channel.open(id, rwsize, rmpsize, buffer).addListener(new SshFutureListener<OpenFuture>() {
- public void operationComplete(OpenFuture future) {
- try {
- if (future.isOpened()) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 0);
- buf.putInt(id);
- buf.putInt(channelId);
- buf.putInt(channel.getLocalWindow().getSize());
- buf.putInt(channel.getLocalWindow().getPacketSize());
- writePacket(buf);
- } else if (future.getException() != null) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
- buf.putInt(id);
- if (future.getException() instanceof OpenChannelException) {
- buf.putInt(((OpenChannelException) future.getException()).getReasonCode());
- buf.putString(future.getException().getMessage());
- } else {
- buf.putInt(0);
- buf.putString("Error opening channel: " + future.getException().getMessage());
- }
- buf.putString("");
- writePacket(buf);
- }
- } catch (IOException e) {
- exceptionCaught(e);
- }
- }
- });
- }
-
- private void globalRequest(Buffer buffer) throws Exception {
- String req = buffer.getString();
- boolean wantReply = buffer.getBoolean();
- log.debug("Received global request {}", req);
- if (req.startsWith("keepalive@")) {
- // Relatively standard KeepAlive directive, just wants failure
- } else if (req.equals("no-more-sessions@openssh.com")) {
- allowMoreSessions = false;
- } else if (req.equals("tcpip-forward")) {
- String address = buffer.getString();
- int port = buffer.getInt();
- try {
- SshdSocketAddress bound = getTcpipForwarder().localPortForwardingRequested(new SshdSocketAddress(address, port));
- port = bound.getPort();
- if (wantReply){
- buffer = createBuffer(SshConstants.Message.SSH_MSG_REQUEST_SUCCESS, 0);
- buffer.putInt(port);
- writePacket(buffer);
- }
- } catch (Exception e) {
- log.debug("Error starting tcpip forward", e);
- if (wantReply) {
- buffer = createBuffer(SshConstants.Message.SSH_MSG_REQUEST_FAILURE, 0);
- writePacket(buffer);
- }
- }
- return;
- } else if (req.equals("cancel-tcpip-forward")) {
- String address = buffer.getString();
- int port = buffer.getInt();
- getTcpipForwarder().localPortForwardingCancelled(new SshdSocketAddress(address, port));
- if (wantReply){
- buffer = createBuffer(SshConstants.Message.SSH_MSG_REQUEST_SUCCESS, 0);
- writePacket(buffer);
- }
- return;
- } else {
- log.debug("Received SSH_MSG_GLOBAL_REQUEST {}", req);
- log.warn("Unknown global request: {}", req);
- }
- if (wantReply) {
- buffer = createBuffer(SshConstants.Message.SSH_MSG_REQUEST_FAILURE, 0);
- writePacket(buffer);
- }
- }
-
- public String initAgentForward() throws IOException {
- return agentForward.initialize();
- }
-
- public String createX11Display(boolean singleConnection, String authenticationProtocol, String authenticationCookie, int screen) throws IOException {
- return x11Forward.createDisplay(singleConnection, authenticationProtocol, authenticationCookie, screen);
- }
-
/**
* Returns the session id.
*
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
new file mode 100644
index 0000000..37a4e2e
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.server.session;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.sshd.SshServer;
+import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.ServiceFactory;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.DefaultCloseFuture;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.server.ServerFactoryManager;
+import org.apache.sshd.server.UserAuth;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ServerUserAuthService implements Service {
+
+ public static class Factory implements ServiceFactory {
+
+ public String getName() {
+ return "ssh-userauth";
+ }
+
+ public Service create(Session session) throws IOException {
+ return new ServerUserAuthService(session);
+ }
+ }
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private final ServerSession session;
+ private List<NamedFactory<UserAuth>> userAuthFactories;
+ private List<List<String>> authMethods;
+ private String authUserName;
+ private String authMethod;
+ private String authService;
+ private UserAuth currentAuth;
+
+ private int maxAuthRequests = 20;
+ private int nbAuthRequests;
+
+ public ServerUserAuthService(Session s) throws SshException {
+ if (!(s instanceof ServerSession)) {
+ throw new IllegalStateException("Server side service used on client side");
+ }
+ this.session = (ServerSession) s;
+ if (session.isAuthenticated()) {
+ throw new SshException("Session already authenticated");
+ }
+ maxAuthRequests = session.getIntProperty(ServerFactoryManager.MAX_AUTH_REQUESTS, maxAuthRequests);
+
+ userAuthFactories = new ArrayList<NamedFactory<UserAuth>>(getFactoryManager().getUserAuthFactories());
+ // Get authentication methods
+ authMethods = new ArrayList<List<String>>();
+ String mths = getFactoryManager().getProperties().get(SshServer.AUTH_METHODS);
+ if (mths == null) {
+ for (NamedFactory<UserAuth> uaf : getFactoryManager().getUserAuthFactories()) {
+ authMethods.add(new ArrayList<String>(Collections.singletonList(uaf.getName())));
+ }
+ } else {
+ for (String mthl : mths.split("\\s")) {
+ authMethods.add(new ArrayList<String>(Arrays.asList(mthl.split(","))));
+ }
+ }
+ // Verify all required methods are supported
+ for (List<String> l : authMethods) {
+ for (String m : l) {
+ if (NamedFactory.Utils.get(userAuthFactories, m) == null) {
+ throw new SshException("Configured method is not supported: " + m);
+ }
+ }
+ }
+ log.debug("Authorized authentication methods: {}", NamedFactory.Utils.getNames(userAuthFactories));
+ }
+
+ public void start() {
+ }
+
+ public ServerSession getSession() {
+ return session;
+ }
+
+ public void process(SshConstants.Message cmd, Buffer buffer) throws Exception {
+ Boolean authed = Boolean.FALSE;
+
+ if (cmd == SshConstants.Message.SSH_MSG_USERAUTH_REQUEST) {
+ if (this.currentAuth != null) {
+ this.currentAuth.destroy();
+ this.currentAuth = null;
+ }
+
+ String username = buffer.getString();
+ String service = buffer.getString();
+ String method = buffer.getString();
+ if (this.authUserName == null || this.authService == null) {
+ this.authUserName = username;
+ this.authService = service;
+ } else if (!this.authUserName.equals(username) || !this.authService.equals(service)) {
+ session.disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR,
+ "Change of username or service is not allowed (" + this.authUserName + ", " + this.authService + ") -> ("
+ + username + ", " + service + ")");
+ return;
+ }
+ this.authMethod = method;
+ if (nbAuthRequests++ > maxAuthRequests) {
+ session.disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Too many authentication failures");
+ return;
+ }
+
+ log.debug("Authenticating user '{}' with service '{}' and method '{}'", new Object[] { username, service, method });
+ NamedFactory<UserAuth> factory = NamedFactory.Utils.get(userAuthFactories, method);
+ if (factory != null) {
+ currentAuth = factory.create();
+ try {
+ authed = currentAuth.auth(session, username, service, buffer);
+ } catch (Exception e) {
+ // Continue
+ log.debug("Authentication failed: {}", e.getMessage());
+ }
+ }
+ } else {
+ if (this.currentAuth == null) {
+ // This should not happen
+ throw new IllegalStateException();
+ }
+ buffer.rpos(buffer.rpos() - 1);
+ try {
+ authed = currentAuth.next(buffer);
+ } catch (Exception e) {
+ // Continue
+ log.debug("Authentication failed: {}", e.getMessage());
+ }
+ }
+
+ if (authed == null) {
+ // authentication is still ongoing
+ log.debug("Authentication not finished");
+ } else if (authed) {
+ log.debug("Authentication succeeded");
+ String username = currentAuth.getUserName();
+
+ boolean success = false;
+ for (List<String> l : authMethods) {
+ if (!l.isEmpty() && l.get(0).equals(authMethod)) {
+ l.remove(0);
+ success |= l.isEmpty();
+ }
+ }
+ if (success) {
+ if (getFactoryManager().getProperties() != null) {
+ String maxSessionCountAsString = getFactoryManager().getProperties().get(ServerFactoryManager.MAX_CONCURRENT_SESSIONS);
+ if (maxSessionCountAsString != null) {
+ int maxSessionCount = Integer.parseInt(maxSessionCountAsString);
+ int currentSessionCount = session.getActiveSessionCountForUser(username);
+ if (currentSessionCount >= maxSessionCount) {
+ session.disconnect(SshConstants.SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE, "Too many concurrent connections");
+ return;
+ }
+ }
+ }
+
+ String welcomeBanner = getFactoryManager().getProperties().get(ServerFactoryManager.WELCOME_BANNER);
+ if (welcomeBanner != null) {
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_BANNER, 0);
+ buffer.putString(welcomeBanner);
+ buffer.putString("en");
+ session.writePacket(buffer);
+ }
+
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_SUCCESS, 0);
+ session.writePacket(buffer);
+ session.setAuthenticated(username);
+ session.startService(authService);
+ session.resetIdleTimeout();
+ log.info("Session {}@{} authenticated", username, session.getIoSession().getRemoteAddress());
+
+ } else {
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_FAILURE, 0);
+ StringBuilder sb = new StringBuilder();
+ for (List<String> l : authMethods) {
+ if (!l.isEmpty()) {
+ if (sb.length() > 0) {
+ sb.append(",");
+ }
+ sb.append(l.get(0));
+ }
+ }
+ buffer.putString(sb.toString());
+ buffer.putByte((byte) 1);
+ session.writePacket(buffer);
+ }
+
+ currentAuth.destroy();
+ currentAuth = null;
+ } else {
+ log.debug("Authentication failed");
+
+ buffer = session.createBuffer(SshConstants.Message.SSH_MSG_USERAUTH_FAILURE, 0);
+ StringBuilder sb = new StringBuilder();
+ for (List<String> l : authMethods) {
+ if (!l.isEmpty()) {
+ String m = l.get(0);
+ if (!"none".equals(m)) {
+ if (sb.length() > 0) {
+ sb.append(",");
+ }
+ sb.append(l.get(0));
+ }
+ }
+ }
+ buffer.putString(sb.toString());
+ buffer.putByte((byte) 0);
+ session.writePacket(buffer);
+
+ if (currentAuth != null) {
+ currentAuth.destroy();
+ currentAuth = null;
+ }
+ }
+ }
+
+ public CloseFuture close(boolean immediately) {
+ CloseFuture future = new DefaultCloseFuture(this);
+ future.setClosed();
+ return future;
+ }
+
+ private ServerFactoryManager getFactoryManager() {
+ return session.getServerFactoryManager();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/server/x11/X11ForwardSupport.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/x11/X11ForwardSupport.java b/sshd-core/src/main/java/org/apache/sshd/server/x11/X11ForwardSupport.java
index 0fb907f..7b5de22 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/x11/X11ForwardSupport.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/x11/X11ForwardSupport.java
@@ -35,6 +35,7 @@ import org.apache.sshd.common.io.IoAcceptor;
import org.apache.sshd.common.io.IoCloseFuture;
import org.apache.sshd.common.io.IoHandler;
import org.apache.sshd.common.io.IoSession;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.common.util.Readable;
import org.apache.sshd.server.session.ServerSession;
@@ -58,18 +59,18 @@ public class X11ForwardSupport implements IoHandler {
protected final Logger log = LoggerFactory.getLogger(getClass());
- private final ServerSession session;
+ private final ConnectionService service;
private IoAcceptor acceptor;
- public X11ForwardSupport(ServerSession session) {
+ public X11ForwardSupport(ConnectionService service) {
super();
- this.session = session;
+ this.service = service;
}
public synchronized void initialize() {
if (this.acceptor == null) {
- this.acceptor = session.getFactoryManager().getIoServiceFactory()
- .createAcceptor(session.getFactoryManager(), this);
+ this.acceptor = service.getSession().getFactoryManager().getIoServiceFactory()
+ .createAcceptor(service.getSession().getFactoryManager(), this);
}
}
@@ -132,7 +133,7 @@ public class X11ForwardSupport implements IoHandler {
public void sessionCreated(IoSession session) throws Exception {
ChannelForwardedX11 channel = new ChannelForwardedX11(session);
session.setAttribute(ChannelForwardedX11.class, channel);
- this.session.registerChannel(channel);
+ this.service.registerChannel(channel);
OpenFuture future = channel.open().await();
Throwable t = future.getException();
if (t instanceof Exception) {
[5/5] git commit: [SSHD-282] Abstract the SSH Service to make it more
pluggable
Posted by gn...@apache.org.
[SSHD-282] Abstract the SSH Service to make it more pluggable
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/03aa3979
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/03aa3979
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/03aa3979
Branch: refs/heads/master
Commit: 03aa3979d47b92ad7b01fcfe1e2833a050b7118d
Parents: 1ea3dfe
Author: Guillaume Nodet <gn...@apache.org>
Authored: Wed Jan 29 12:01:53 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Wed Jan 29 12:01:53 2014 +0100
----------------------------------------------------------------------
.../main/java/org/apache/sshd/SshClient.java | 8 +
.../main/java/org/apache/sshd/SshServer.java | 8 +
.../org/apache/sshd/agent/SshAgentFactory.java | 11 +-
.../sshd/agent/common/AgentForwardSupport.java | 9 +-
.../sshd/agent/local/AgentServerProxy.java | 9 +-
.../agent/local/ChannelAgentForwarding.java | 2 +-
.../sshd/agent/local/LocalAgentFactory.java | 6 +-
.../sshd/agent/local/ProxyAgentFactory.java | 11 +-
.../sshd/agent/unix/AgentServerProxy.java | 9 +-
.../sshd/agent/unix/UnixAgentFactory.java | 11 +-
.../apache/sshd/client/auth/UserAuthAgent.java | 5 +-
.../client/session/ClientConnectionService.java | 209 +++++++++
.../sshd/client/session/ClientSessionImpl.java | 387 ++++-------------
.../client/session/ClientUserAuthService.java | 201 +++++++++
.../sshd/common/AbstractFactoryManager.java | 8 +
.../java/org/apache/sshd/common/Channel.java | 3 +-
.../org/apache/sshd/common/FactoryManager.java | 7 +
.../java/org/apache/sshd/common/Service.java | 53 +++
.../org/apache/sshd/common/ServiceFactory.java | 58 +++
.../java/org/apache/sshd/common/Session.java | 27 +-
.../sshd/common/TcpipForwarderFactory.java | 6 +-
.../sshd/common/channel/AbstractChannel.java | 7 +-
.../common/forward/DefaultTcpipForwarder.java | 11 +-
.../forward/DefaultTcpipForwarderFactory.java | 5 +-
.../sshd/common/forward/TcpipServerChannel.java | 2 +-
.../session/AbstractConnectionService.java | 271 ++++++++++++
.../sshd/common/session/AbstractSession.java | 133 ++----
.../sshd/common/session/ConnectionService.java | 63 +++
.../sshd/server/channel/ChannelSession.java | 4 +-
.../server/session/ServerConnectionService.java | 232 ++++++++++
.../sshd/server/session/ServerSession.java | 419 ++-----------------
.../server/session/ServerUserAuthService.java | 261 ++++++++++++
.../sshd/server/x11/X11ForwardSupport.java | 13 +-
33 files changed, 1618 insertions(+), 851 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/SshClient.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshClient.java b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
index 410ae51..8d4e169 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshClient.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshClient.java
@@ -51,7 +51,9 @@ import org.apache.sshd.client.kex.ECDHP256;
import org.apache.sshd.client.kex.ECDHP384;
import org.apache.sshd.client.kex.ECDHP521;
import org.apache.sshd.client.keyverifier.AcceptAllServerKeyVerifier;
+import org.apache.sshd.client.session.ClientConnectionService;
import org.apache.sshd.client.session.ClientSessionImpl;
+import org.apache.sshd.client.session.ClientUserAuthService;
import org.apache.sshd.common.AbstractFactoryManager;
import org.apache.sshd.common.Channel;
import org.apache.sshd.common.Cipher;
@@ -216,6 +218,12 @@ public class SshClient extends AbstractFactoryManager implements ClientFactoryMa
if (getIoServiceFactory() == null) {
setIoServiceFactory(new DefaultIoServiceFactory());
}
+ if (getServiceFactories() == null) {
+ setServiceFactories(Arrays.asList(
+ new ClientUserAuthService.Factory(),
+ new ClientConnectionService.Factory()
+ ));
+ }
}
public void start() {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/SshServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
index eaf27ea..56e84cd 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
@@ -105,7 +105,9 @@ import org.apache.sshd.server.kex.ECDHP384;
import org.apache.sshd.server.kex.ECDHP521;
import org.apache.sshd.server.keyprovider.PEMGeneratorHostKeyProvider;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
+import org.apache.sshd.server.session.ServerConnectionService;
import org.apache.sshd.server.session.ServerSession;
+import org.apache.sshd.server.session.ServerUserAuthService;
import org.apache.sshd.server.session.SessionFactory;
import org.apache.sshd.server.sftp.SftpSubsystem;
import org.apache.sshd.server.session.ServerSessionTimeoutListener;
@@ -298,6 +300,12 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
if (getIoServiceFactory() == null) {
setIoServiceFactory(new DefaultIoServiceFactory());
}
+ if (getServiceFactories() == null) {
+ setServiceFactories(Arrays.asList(
+ new ServerUserAuthService.Factory(),
+ new ServerConnectionService.Factory()
+ ));
+ }
}
/**
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentFactory.java
index d169d47..ff50ac5 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/SshAgentFactory.java
@@ -21,8 +21,10 @@ package org.apache.sshd.agent;
import java.io.IOException;
import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
+import org.apache.sshd.common.session.ConnectionService;
/**
* The <code>SshAgentFactory</code> is used to communicate with an SshAgent.
@@ -41,19 +43,20 @@ public interface SshAgentFactory {
/**
* Create an SshAgent that can be used on the client side by the authentication
* process to send possible keys.
- * @param session
+ *
+ * @param manager
* @return
*/
- SshAgent createClient(Session session) throws IOException;
+ SshAgent createClient(FactoryManager manager) throws IOException;
/**
* Create the server side that will be used by other SSH clients.
* It will usually create a channel that will forward the requests
* to the original client.
*
- * @param session
+ * @param service
* @return
*/
- SshAgentServer createServer(Session session) throws IOException;
+ SshAgentServer createServer(ConnectionService service) throws IOException;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java b/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
index 0692b7e..cd879e1 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.server.session.ServerSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,18 +34,18 @@ public class AgentForwardSupport {
private static final Logger log = LoggerFactory.getLogger(AgentForwardSupport.class);
- private final ServerSession session;
+ private final ConnectionService service;
private String agentId;
private SshAgentServer agentServer;
- public AgentForwardSupport(ServerSession session) {
- this.session = session;
+ public AgentForwardSupport(ConnectionService service) {
+ this.service = service;
}
public String initialize() throws IOException {
try {
if (agentId == null) {
- agentServer = session.getFactoryManager().getAgentFactory().createServer(session);
+ agentServer = service.getSession().getFactoryManager().getAgentFactory().createServer(service);
agentId = agentServer.getId();
}
return agentId;
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentServerProxy.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentServerProxy.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentServerProxy.java
index 2630faf..15c23b2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentServerProxy.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/AgentServerProxy.java
@@ -24,6 +24,7 @@ import java.util.UUID;
import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.server.session.ServerSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,18 +36,18 @@ public class AgentServerProxy implements SshAgentServer {
private static final Logger LOG = LoggerFactory.getLogger(AgentServerProxy.class);
- private final ServerSession session;
+ private final ConnectionService service;
private String id;
- public AgentServerProxy(ServerSession session) throws IOException {
- this.session = session;
+ public AgentServerProxy(ConnectionService service) throws IOException {
+ this.service = service;
this.id = UUID.randomUUID().toString();
}
public SshAgent createClient() throws IOException {
try {
AgentForwardedChannel channel = new AgentForwardedChannel();
- this.session.registerChannel(channel);
+ this.service.registerChannel(channel);
OpenFuture future = channel.open().await();
Throwable t = future.getException();
if (t instanceof Exception) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
index 4903315..bdd5165 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
@@ -66,7 +66,7 @@ public class ChannelAgentForwarding extends AbstractServerChannel {
final OpenFuture f = new DefaultOpenFuture(this);
try {
out = new ChannelOutputStream(this, remoteWindow, log, SshConstants.Message.SSH_MSG_CHANNEL_DATA);
- agent = session.getFactoryManager().getAgentFactory().createClient(session);
+ agent = session.getFactoryManager().getAgentFactory().createClient(session.getFactoryManager());
client = new AgentClient();
f.setOpened();
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/local/LocalAgentFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/LocalAgentFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/LocalAgentFactory.java
index 014206f..15c494a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/LocalAgentFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/LocalAgentFactory.java
@@ -25,8 +25,10 @@ import org.apache.sshd.agent.SshAgentFactory;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.agent.common.AgentDelegate;
import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
+import org.apache.sshd.common.session.ConnectionService;
public class LocalAgentFactory implements SshAgentFactory {
@@ -48,11 +50,11 @@ public class LocalAgentFactory implements SshAgentFactory {
return new ChannelAgentForwarding.Factory();
}
- public SshAgent createClient(Session session) throws IOException {
+ public SshAgent createClient(FactoryManager manager) throws IOException {
return new AgentDelegate(agent);
}
- public SshAgentServer createServer(Session session) throws IOException {
+ public SshAgentServer createServer(ConnectionService service) throws IOException {
return null;
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
index 2ae8223..fd918c0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/ProxyAgentFactory.java
@@ -26,8 +26,10 @@ import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.SshAgentFactory;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.server.session.ServerSession;
public class ProxyAgentFactory implements SshAgentFactory {
@@ -38,8 +40,8 @@ public class ProxyAgentFactory implements SshAgentFactory {
return new ChannelAgentForwarding.Factory();
}
- public SshAgent createClient(Session session) throws IOException {
- String proxyId = session.getFactoryManager().getProperties().get(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
+ public SshAgent createClient(FactoryManager manager) throws IOException {
+ String proxyId = manager.getProperties().get(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
if (proxyId == null) {
throw new IllegalStateException("No " + SshAgent.SSH_AUTHSOCKET_ENV_NAME + " environment variable set");
}
@@ -50,11 +52,12 @@ public class ProxyAgentFactory implements SshAgentFactory {
return proxy.createClient();
}
- public SshAgentServer createServer(Session session) throws IOException {
+ public SshAgentServer createServer(ConnectionService service) throws IOException {
+ Session session = service.getSession();
if (!(session instanceof ServerSession)) {
throw new IllegalStateException("The session used to create an agent server proxy must be a server session");
}
- final AgentServerProxy proxy = new AgentServerProxy((ServerSession) session);
+ final AgentServerProxy proxy = new AgentServerProxy(service);
proxies.put(proxy.getId(), proxy);
return new SshAgentServer() {
public String getId() {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentServerProxy.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentServerProxy.java b/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentServerProxy.java
index f773237..f358740 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentServerProxy.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentServerProxy.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.client.future.OpenFuture;
import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.server.session.ServerSession;
import org.apache.tomcat.jni.Local;
import org.apache.tomcat.jni.Pool;
@@ -38,15 +39,15 @@ public class AgentServerProxy implements SshAgentServer {
private static final Logger LOG = LoggerFactory.getLogger(AgentServerProxy.class);
- private final ServerSession session;
+ private final ConnectionService service;
private String authSocket;
private long pool;
private long handle;
private Thread thread;
private boolean closed;
- public AgentServerProxy(ServerSession session) throws IOException {
- this.session = session;
+ public AgentServerProxy(ConnectionService service) throws IOException {
+ this.service = service;
try {
String authSocket = AprLibrary.createLocalSocketAddress();
pool = Pool.create(AprLibrary.getInstance().getRootPool());
@@ -70,7 +71,7 @@ public class AgentServerProxy implements SshAgentServer {
}
Socket.timeoutSet(clientSock, 10000000);
AgentForwardedChannel channel = new AgentForwardedChannel(clientSock);
- AgentServerProxy.this.session.registerChannel(channel);
+ AgentServerProxy.this.service.registerChannel(channel);
OpenFuture future = channel.open().await();
Throwable t = future.getException();
if (t instanceof Exception) {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/agent/unix/UnixAgentFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/unix/UnixAgentFactory.java b/sshd-core/src/main/java/org/apache/sshd/agent/unix/UnixAgentFactory.java
index f82c95f..87797d3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/unix/UnixAgentFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/unix/UnixAgentFactory.java
@@ -24,8 +24,10 @@ import org.apache.sshd.agent.SshAgent;
import org.apache.sshd.agent.SshAgentFactory;
import org.apache.sshd.agent.SshAgentServer;
import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.FactoryManager;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.common.Session;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.server.session.ServerSession;
public class UnixAgentFactory implements SshAgentFactory {
@@ -34,16 +36,17 @@ public class UnixAgentFactory implements SshAgentFactory {
return new ChannelAgentForwarding.Factory();
}
- public SshAgent createClient(Session session) throws IOException {
- String authSocket = session.getFactoryManager().getProperties().get(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
+ public SshAgent createClient(FactoryManager manager) throws IOException {
+ String authSocket = manager.getProperties().get(SshAgent.SSH_AUTHSOCKET_ENV_NAME);
SshAgent agent = new AgentClient(authSocket);
return agent;
}
- public SshAgentServer createServer(Session session) throws IOException {
+ public SshAgentServer createServer(ConnectionService service) throws IOException {
+ Session session = service.getSession();
if (!(session instanceof ServerSession)) {
throw new IllegalStateException("The session used to create an agent server proxy must be a server session");
}
- return new AgentServerProxy((ServerSession) session);
+ return new AgentServerProxy(service);
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
index fa68ff9..5fe5926 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/auth/UserAuthAgent.java
@@ -39,7 +39,10 @@ public class UserAuthAgent extends AbstractUserAuth {
public UserAuthAgent(ClientSessionImpl session, String service, String username) throws IOException {
super(session, service, username);
- this.agent = session.getFactoryManager().getAgentFactory().createClient(session);
+ if (session.getFactoryManager().getAgentFactory() == null) {
+ throw new IllegalStateException("No ssh agent factory has been configured");
+ }
+ this.agent = session.getFactoryManager().getAgentFactory().createClient(session.getFactoryManager());
this.keys = agent.getIdentities().iterator();
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
new file mode 100644
index 0000000..bc9e316
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientConnectionService.java
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.client.session;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.sshd.client.ClientFactoryManager;
+import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.common.Channel;
+import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.ServiceFactory;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.future.SshFutureListener;
+import org.apache.sshd.common.session.AbstractConnectionService;
+import org.apache.sshd.common.util.Buffer;
+import org.apache.sshd.server.channel.OpenChannelException;
+
+/**
+ * Client side <code>ssh-connection</code> service.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ClientConnectionService extends AbstractConnectionService {
+
+ public static class Factory implements ServiceFactory {
+
+ public String getName() {
+ return "ssh-connection";
+ }
+
+ public Service create(Session session) throws IOException {
+ return new ClientConnectionService(session);
+ }
+ }
+
+ public ClientConnectionService(Session s) throws SshException {
+ super(s);
+ if (!(s instanceof ClientSessionImpl)) {
+ throw new IllegalStateException("Client side service used on server side");
+ }
+ }
+
+ @Override
+ public void start() {
+ if (!((ClientSessionImpl) session).isAuthenticated()) {
+ throw new IllegalStateException("Session is not authenticated");
+ }
+ startHeartBeat();
+ }
+
+ protected void startHeartBeat() {
+ String intervalStr = session.getFactoryManager().getProperties().get(ClientFactoryManager.HEARTBEAT_INTERVAL);
+ try {
+ int interval = intervalStr != null ? Integer.parseInt(intervalStr) : 0;
+ if (interval > 0) {
+ session.getFactoryManager().getScheduledExecutorService().scheduleAtFixedRate(new Runnable() {
+ public void run() {
+ sendHeartBeat();
+ }
+ }, interval, interval, TimeUnit.MILLISECONDS);
+ }
+ } catch (NumberFormatException e) {
+ log.warn("Ignoring bad heartbeat interval: {}", intervalStr);
+ }
+ }
+
+ protected void sendHeartBeat() {
+ try {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_GLOBAL_REQUEST, 0);
+ String request = session.getFactoryManager().getProperties().get(ClientFactoryManager.HEARTBEAT_REQUEST);
+ if (request == null) {
+ request = "keepalive@sshd.apache.org";
+ }
+ buf.putString(request);
+ buf.putBoolean(false);
+ session.writePacket(buf);
+ } catch (IOException e) {
+ log.info("Error sending keepalive message", e);
+ }
+ }
+
+ public void process(SshConstants.Message cmd, Buffer buffer) throws Exception {
+ switch (cmd) {
+ case SSH_MSG_CHANNEL_OPEN:
+ channelOpen(buffer);
+ break;
+ case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
+ channelOpenConfirmation(buffer);
+ break;
+ case SSH_MSG_CHANNEL_OPEN_FAILURE:
+ channelOpenFailure(buffer);
+ break;
+ case SSH_MSG_CHANNEL_REQUEST:
+ channelRequest(buffer);
+ break;
+ case SSH_MSG_CHANNEL_DATA:
+ channelData(buffer);
+ break;
+ case SSH_MSG_CHANNEL_EXTENDED_DATA:
+ channelExtendedData(buffer);
+ break;
+ case SSH_MSG_CHANNEL_FAILURE:
+ channelFailure(buffer);
+ break;
+ case SSH_MSG_CHANNEL_WINDOW_ADJUST:
+ channelWindowAdjust(buffer);
+ break;
+ case SSH_MSG_CHANNEL_EOF:
+ channelEof(buffer);
+ break;
+ case SSH_MSG_CHANNEL_CLOSE:
+ channelClose(buffer);
+ break;
+ default:
+ throw new IllegalStateException("Unsupported command: " + cmd);
+ }
+ }
+
+ // TODO: remove from interface
+ public String initAgentForward() throws IOException {
+ throw new IllegalStateException("Server side operation");
+ }
+
+ // TODO: remove from interface
+ public String createX11Display(boolean singleConnection, String authenticationProtocol, String authenticationCookie, int screen) throws IOException {
+ throw new IllegalStateException("Server side operation");
+ }
+
+ private void channelOpen(Buffer buffer) throws Exception {
+ String type = buffer.getString();
+ final int id = buffer.getInt();
+ final int rwsize = buffer.getInt();
+ final int rmpsize = buffer.getInt();
+
+ log.info("Received SSH_MSG_CHANNEL_OPEN {}", type);
+
+ if (closing) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+ buf.putInt(id);
+ buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
+ buf.putString("SSH server is shutting down: " + type);
+ buf.putString("");
+ session.writePacket(buf);
+ return;
+ }
+
+ final Channel channel = NamedFactory.Utils.create(getSession().getFactoryManager().getChannelFactories(), type);
+ if (channel == null) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+ buf.putInt(id);
+ buf.putInt(SshConstants.SSH_OPEN_UNKNOWN_CHANNEL_TYPE);
+ buf.putString("Unsupported channel type: " + type);
+ buf.putString("");
+ session.writePacket(buf);
+ return;
+ }
+
+ final int channelId = registerChannel(channel);
+ channel.open(id, rwsize, rmpsize, buffer).addListener(new SshFutureListener<OpenFuture>() {
+ public void operationComplete(OpenFuture future) {
+ try {
+ if (future.isOpened()) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 0);
+ buf.putInt(id);
+ buf.putInt(channelId);
+ buf.putInt(channel.getLocalWindow().getSize());
+ buf.putInt(channel.getLocalWindow().getPacketSize());
+ session.writePacket(buf);
+ } else if (future.getException() != null) {
+ Buffer buf = session.createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
+ buf.putInt(id);
+ if (future.getException() instanceof OpenChannelException) {
+ buf.putInt(((OpenChannelException)future.getException()).getReasonCode());
+ buf.putString(future.getException().getMessage());
+ } else {
+ buf.putInt(0);
+ buf.putString("Error opening channel: " + future.getException().getMessage());
+ }
+ buf.putString("");
+ session.writePacket(buf);
+ }
+ } catch (IOException e) {
+ session.exceptionCaught(e);
+ }
+ }
+ });
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
index 2d4e68c..ce3e030 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientSessionImpl.java
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.net.SocketAddress;
import java.security.KeyPair;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@@ -32,7 +33,6 @@ import org.apache.sshd.client.ScpClient;
import org.apache.sshd.client.ServerKeyVerifier;
import org.apache.sshd.client.SftpClient;
import org.apache.sshd.client.UserAuth;
-import org.apache.sshd.client.UserInteraction;
import org.apache.sshd.client.auth.UserAuthAgent;
import org.apache.sshd.client.auth.UserAuthKeyboardInteractive;
import org.apache.sshd.client.auth.UserAuthPassword;
@@ -43,22 +43,19 @@ import org.apache.sshd.client.channel.ChannelShell;
import org.apache.sshd.client.channel.ChannelSubsystem;
import org.apache.sshd.client.future.AuthFuture;
import org.apache.sshd.client.future.DefaultAuthFuture;
-import org.apache.sshd.client.future.OpenFuture;
import org.apache.sshd.client.scp.DefaultScpClient;
import org.apache.sshd.client.sftp.DefaultSftpClient;
-import org.apache.sshd.common.Channel;
-import org.apache.sshd.common.KeyExchange;
import org.apache.sshd.common.KeyPairProvider;
import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.ServiceFactory;
import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.SshException;
import org.apache.sshd.common.SshdSocketAddress;
-import org.apache.sshd.common.future.CloseFuture;
-import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoSession;
import org.apache.sshd.common.session.AbstractSession;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.util.Buffer;
-import org.apache.sshd.server.channel.OpenChannelException;
/**
* TODO Add javadoc
@@ -67,149 +64,83 @@ import org.apache.sshd.server.channel.OpenChannelException;
*/
public class ClientSessionImpl extends AbstractSession implements ClientSession {
- private static final String AUTHENTICATION_SERVICE = "ssh-connection";
-
- private UserAuth userAuth;
- /**
- * The AuthFuture that is being used by the current auth request. This encodes the state.
- * isSuccess -> authenticated, else if isDone -> server waiting for user auth, else authenticating.
- */
- private volatile AuthFuture authFuture;
-
/**
* For clients to store their own metadata
*/
private Map<Object, Object> metadataMap = new HashMap<Object, Object>();
+ private ServiceFactory currentServiceFactory;
+
+ private Service nextService;
+ private ServiceFactory nextServiceFactory;
+
+ protected AuthFuture authFuture;
+
public ClientSessionImpl(ClientFactoryManager client, IoSession session) throws Exception {
super(client, session);
log.info("Session created...");
+ // Need to set the initial service early as calling code likes to start trying to
+ // manipulate it before the connection has even been established. For instance, to
+ // set the authPassword.
+ List<ServiceFactory> factories = client.getServiceFactories();
+ if (factories == null || factories.isEmpty() || factories.size() > 2) {
+ throw new IllegalArgumentException("One or two services must be configured");
+ }
+ currentServiceFactory = factories.get(0);
+ currentService = currentServiceFactory.create(this);
+ if (factories.size() > 1) {
+ nextServiceFactory = factories.get(1);
+ nextService = nextServiceFactory.create(this);
+ } else {
+ nextServiceFactory = null;
+ }
+ authFuture = new DefaultAuthFuture(lock);
+ authFuture.setAuthed(false);
sendClientIdentification();
sendKexInit();
- // Maintain the current auth status in the authFuture.
- authFuture = new DefaultAuthFuture(lock);
}
public ClientFactoryManager getClientFactoryManager() {
return (ClientFactoryManager) factoryManager;
}
- /**
- * return true if/when ready for auth; false if never ready.
- * @return server is ready and waiting for auth
- */
- private boolean readyForAuth() {
- // isDone indicates that the last auth finished and a new one can commence.
- while (!this.authFuture.isDone()) {
- log.debug("waiting to send authentication");
- try {
- this.authFuture.await();
- } catch (InterruptedException e) {
- log.debug("Unexpected interrupt", e);
- throw new RuntimeException(e);
- }
- }
- if (this.authFuture.isSuccess()) {
- log.debug("already authenticated");
- throw new IllegalStateException("Already authenticated");
- }
- if (this.authFuture.getException() != null) {
- log.debug("probably closed", this.authFuture.getException());
- return false;
- }
- if (!this.authFuture.isFailure()) {
- log.debug("unexpected state");
- throw new IllegalStateException("Unexpected authentication state");
- }
- if (this.userAuth != null) {
- log.debug("authentication already in progress");
- throw new IllegalStateException("Authentication already in progress?");
- }
- log.debug("ready to try authentication with new lock");
- // The new future !isDone() - i.e., in progress blocking out other waits.
- this.authFuture = new DefaultAuthFuture(lock);
- return true;
- }
-
- /**
- * execute one step in user authentication.
- * @param buffer
- * @throws IOException
- */
- private void processUserAuth(Buffer buffer) throws IOException {
- log.debug("processing {}", userAuth);
- switch (userAuth.next(buffer)) {
- case Success:
- log.debug("succeeded with {}", userAuth);
- this.authed = true;
- this.username = userAuth.getUsername();
- setState(State.Running);
- // Will wake up anyone sitting in waitFor
- authFuture.setAuthed(true);
- startHeartBeat();
- break;
- case Failure:
- log.debug("failed with {}", userAuth);
- this.userAuth = null;
- setState(State.WaitForAuth);
- // Will wake up anyone sitting in waitFor
- this.authFuture.setAuthed(false);
- break;
- case Continued:
- // Will wake up anyone sitting in waitFor
- setState(State.UserAuth);
- log.debug("continuing with {}", userAuth);
- break;
- }
- }
-
public AuthFuture authAgent(String user) throws IOException {
- log.debug("Trying agent authentication");
- if (getFactoryManager().getAgentFactory() == null) {
- throw new IllegalStateException("No ssh agent factory has been configured");
- }
- synchronized (lock) {
- if (readyForAuth()) {
- userAuth = new UserAuthAgent(this, AUTHENTICATION_SERVICE, user);
- processUserAuth(null);
- }
- return authFuture;
- }
+ return tryAuth(new UserAuthAgent(this, nextServiceName(), user));
}
public AuthFuture authPassword(String user, String password) throws IOException {
- log.debug("Trying password authentication");
- synchronized (lock) {
- if (readyForAuth()) {
- userAuth = new UserAuthPassword(this, AUTHENTICATION_SERVICE, user, password);
- processUserAuth(null);
- }
- return authFuture;
- }
+ return tryAuth(new UserAuthPassword(this, nextServiceName(), user, password));
}
public AuthFuture authInteractive(String user, String password) throws IOException {
- log.debug("Trying keyboard-interactive authentication");
- synchronized (lock) {
- if (readyForAuth()) {
- userAuth = new UserAuthKeyboardInteractive(this, AUTHENTICATION_SERVICE, user, password);
- processUserAuth(null);
- }
- return authFuture;
- }
+ return tryAuth(new UserAuthKeyboardInteractive(this, nextServiceName(), user, password));
}
public AuthFuture authPublicKey(String user, KeyPair key) throws IOException {
- log.debug("Trying publickey authentication");
+ return tryAuth(new UserAuthPublicKey(this, nextServiceName(), user, key));
+ }
+
+ private AuthFuture tryAuth(UserAuth auth) throws IOException {
synchronized (lock) {
- if (readyForAuth()) {
- userAuth = new UserAuthPublicKey(this, AUTHENTICATION_SERVICE, user, key);
- processUserAuth(null);
- }
- return authFuture;
+ return authFuture = getUserAuthService().auth(auth);
}
}
+ private String nextServiceName() {
+ return nextServiceFactory.getName();
+ }
+
+ protected void switchToNextService() throws IOException {
+ if (nextService == null) {
+ throw new IllegalStateException("No service available");
+ }
+ currentServiceFactory = nextServiceFactory;
+ currentService = nextService;
+ nextServiceFactory = null;
+ nextService = null;
+ currentService.start();
+ }
+
public ClientChannel createChannel(String type) throws IOException {
return createChannel(type, null);
}
@@ -228,28 +159,46 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
public ChannelShell createShellChannel() throws IOException {
ChannelShell channel = new ChannelShell();
- registerChannel(channel);
+ getConnectionService().registerChannel(channel);
return channel;
}
public ChannelExec createExecChannel(String command) throws IOException {
ChannelExec channel = new ChannelExec(command);
- registerChannel(channel);
+ getConnectionService().registerChannel(channel);
return channel;
}
public ChannelSubsystem createSubsystemChannel(String subsystem) throws IOException {
ChannelSubsystem channel = new ChannelSubsystem(subsystem);
- registerChannel(channel);
+ getConnectionService().registerChannel(channel);
return channel;
}
public ChannelDirectTcpip createDirectTcpipChannel(SshdSocketAddress local, SshdSocketAddress remote) throws IOException {
ChannelDirectTcpip channel = new ChannelDirectTcpip(local, remote);
- registerChannel(channel);
+ getConnectionService().registerChannel(channel);
return channel;
}
+ private ClientUserAuthService getUserAuthService() {
+ return findService(ClientUserAuthService.class);
+ }
+
+ private ConnectionService getConnectionService() {
+ return findService(ConnectionService.class);
+ }
+
+ private <T> T findService(Class<T> clazz) {
+ if (clazz.isInstance(currentService)) {
+ return clazz.cast(currentService);
+ }
+ if (clazz.isInstance(nextService)) {
+ return clazz.cast(nextService);
+ }
+ throw new IllegalStateException("Attempted to access unknown service " + clazz.getSimpleName());
+ }
+
public ScpClient createScpClient() {
return new DefaultScpClient(this);
}
@@ -259,29 +208,19 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
public SshdSocketAddress startLocalPortForwarding(SshdSocketAddress local, SshdSocketAddress remote) throws IOException {
- return getTcpipForwarder().startLocalPortForwarding(local, remote);
+ return getConnectionService().getTcpipForwarder().startLocalPortForwarding(local, remote);
}
public void stopLocalPortForwarding(SshdSocketAddress local) throws IOException {
- getTcpipForwarder().stopLocalPortForwarding(local);
+ getConnectionService().getTcpipForwarder().stopLocalPortForwarding(local);
}
public SshdSocketAddress startRemotePortForwarding(SshdSocketAddress remote, SshdSocketAddress local) throws IOException {
- return getTcpipForwarder().startRemotePortForwarding(remote, local);
+ return getConnectionService().getTcpipForwarder().startRemotePortForwarding(remote, local);
}
public void stopRemotePortForwarding(SshdSocketAddress remote) throws IOException {
- getTcpipForwarder().stopRemotePortForwarding(remote);
- }
-
- @Override
- public CloseFuture close(boolean immediately) {
- synchronized (lock) {
- if (!authFuture.isDone()) {
- authFuture.setException(new SshException("Session is closed"));
- }
- return super.close(immediately);
- }
+ getConnectionService().getTcpipForwarder().stopRemotePortForwarding(remote);
}
protected void handleMessage(Buffer buffer) throws Exception {
@@ -344,37 +283,24 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
log.info("Received SSH_MSG_NEWKEYS");
receiveNewKeys(false);
- sendAuthRequest();
- setState(State.AuthRequestSent);
+ log.info("Send SSH_MSG_SERVICE_REQUEST for {}", currentServiceFactory.getName());
+ Buffer request = createBuffer(SshConstants.Message.SSH_MSG_SERVICE_REQUEST, 0);
+ request.putString(currentServiceFactory.getName());
+ writePacket(request);
+ setState(State.ServiceRequestSent);
+ // Assuming that MINA-SSHD only implements "explicit server authentication" it is permissible
+ // for the client's service to start sending data before the service-accept has been received.
+ // If "implicit authentication" were to ever be supported, then this would need to be
+ // called after service-accept comes back. See SSH-TRANSPORT.
+ currentService.start();
break;
- case AuthRequestSent:
+ case ServiceRequestSent:
if (cmd != SshConstants.Message.SSH_MSG_SERVICE_ACCEPT) {
disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Protocol error: expected packet SSH_MSG_SERVICE_ACCEPT, got " + cmd);
return;
}
- authFuture.setAuthed(false);
- setState(State.WaitForAuth);
- break;
- case WaitForAuth:
- // We're waiting for the client to send an authentication request
- // TODO: handle unexpected incoming packets
- break;
- case UserAuth:
- if (userAuth == null) {
- throw new IllegalStateException("State is userAuth, but no user auth pending!!!");
- }
- if (cmd == SshConstants.Message.SSH_MSG_USERAUTH_BANNER) {
- String welcome = buffer.getString();
- String lang = buffer.getString();
- log.debug("Welcome banner: {}", welcome);
- UserInteraction ui = getClientFactoryManager().getUserInteraction();
- if (ui != null) {
- ui.welcome(welcome);
- }
- } else {
- buffer.rpos(buffer.rpos() - 1);
- processUserAuth(buffer);
- }
+ log.info("Received SSH_MSG_SERVICE_ACCEPT");
+ setState(State.Running);
break;
case Running:
switch (cmd) {
@@ -384,38 +310,9 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
case SSH_MSG_REQUEST_FAILURE:
requestFailure(buffer);
break;
- case SSH_MSG_CHANNEL_OPEN:
- channelOpen(buffer);
- break;
- case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
- channelOpenConfirmation(buffer);
- break;
- case SSH_MSG_CHANNEL_OPEN_FAILURE:
- channelOpenFailure(buffer);
- break;
- case SSH_MSG_CHANNEL_REQUEST:
- channelRequest(buffer);
- break;
- case SSH_MSG_CHANNEL_DATA:
- channelData(buffer);
- break;
- case SSH_MSG_CHANNEL_EXTENDED_DATA:
- channelExtendedData(buffer);
- break;
- case SSH_MSG_CHANNEL_FAILURE:
- channelFailure(buffer);
- break;
- case SSH_MSG_CHANNEL_WINDOW_ADJUST:
- channelWindowAdjust(buffer);
- break;
- case SSH_MSG_CHANNEL_EOF:
- channelEof(buffer);
- break;
- case SSH_MSG_CHANNEL_CLOSE:
- channelClose(buffer);
- break;
default:
- throw new IllegalStateException("Unsupported command: " + cmd);
+ currentService.process(cmd, buffer);
+ break;
}
break;
default:
@@ -472,37 +369,6 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
}
- protected void startHeartBeat() {
- String intervalStr = getClientFactoryManager().getProperties().get(ClientFactoryManager.HEARTBEAT_INTERVAL);
- try {
- int interval = intervalStr != null ? Integer.parseInt(intervalStr) : 0;
- if (interval > 0) {
- getClientFactoryManager().getScheduledExecutorService().scheduleAtFixedRate(new Runnable() {
- public void run() {
- sendHeartBeat();
- }
- }, interval, interval, TimeUnit.MILLISECONDS);
- }
- } catch (NumberFormatException e) {
- log.warn("Ignoring bad heartbeat interval: {}", intervalStr);
- }
- }
-
- protected void sendHeartBeat() {
- try {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_GLOBAL_REQUEST, 0);
- String request = getClientFactoryManager().getProperties().get(ClientFactoryManager.HEARTBEAT_REQUEST);
- if (request == null) {
- request = "keepalive@sshd.apache.org";
- }
- buf.putString(request);
- buf.putBoolean(false);
- writePacket(buf);
- } catch (IOException e) {
- log.info("Error sending keepalive message", e);
- }
- }
-
protected boolean readIdentification(Buffer buffer) throws IOException {
serverVersion = doReadIdentification(buffer);
if (serverVersion == null) {
@@ -540,75 +406,6 @@ public class ClientSessionImpl extends AbstractSession implements ClientSession
}
}
- private void sendAuthRequest() throws Exception {
- log.info("Send SSH_MSG_SERVICE_REQUEST for ssh-userauth");
- Buffer buffer = createBuffer(SshConstants.Message.SSH_MSG_SERVICE_REQUEST, 0);
- buffer.putString("ssh-userauth");
- writePacket(buffer);
- }
-
- private void channelOpen(Buffer buffer) throws Exception {
- String type = buffer.getString();
- final int id = buffer.getInt();
- final int rwsize = buffer.getInt();
- final int rmpsize = buffer.getInt();
-
- log.info("Received SSH_MSG_CHANNEL_OPEN {}", type);
-
- if (closing) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
- buf.putInt(id);
- buf.putInt(SshConstants.SSH_OPEN_CONNECT_FAILED);
- buf.putString("SSH server is shutting down: " + type);
- buf.putString("");
- writePacket(buf);
- return;
- }
-
- final Channel channel = NamedFactory.Utils.create(getFactoryManager().getChannelFactories(), type);
- if (channel == null) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
- buf.putInt(id);
- buf.putInt(SshConstants.SSH_OPEN_UNKNOWN_CHANNEL_TYPE);
- buf.putString("Unsupported channel type: " + type);
- buf.putString("");
- writePacket(buf);
- return;
- }
-
- final int channelId = getNextChannelId();
- channels.put(channelId, channel);
- channel.init(this, channelId);
- channel.open(id, rwsize, rmpsize, buffer).addListener(new SshFutureListener<OpenFuture>() {
- public void operationComplete(OpenFuture future) {
- try {
- if (future.isOpened()) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_CONFIRMATION, 0);
- buf.putInt(id);
- buf.putInt(channelId);
- buf.putInt(channel.getLocalWindow().getSize());
- buf.putInt(channel.getLocalWindow().getPacketSize());
- writePacket(buf);
- } else if (future.getException() != null) {
- Buffer buf = createBuffer(SshConstants.Message.SSH_MSG_CHANNEL_OPEN_FAILURE, 0);
- buf.putInt(id);
- if (future.getException() instanceof OpenChannelException) {
- buf.putInt(((OpenChannelException)future.getException()).getReasonCode());
- buf.putString(future.getException().getMessage());
- } else {
- buf.putInt(0);
- buf.putString("Error opening channel: " + future.getException().getMessage());
- }
- buf.putString("");
- writePacket(buf);
- }
- } catch (IOException e) {
- exceptionCaught(e);
- }
- }
- });
- }
-
public Map<Object, Object> getMetadataMap() {
return metadataMap;
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
new file mode 100644
index 0000000..9527d34
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.client.session;
+
+import java.io.IOException;
+
+import org.apache.sshd.client.UserAuth;
+import org.apache.sshd.client.UserInteraction;
+import org.apache.sshd.client.future.AuthFuture;
+import org.apache.sshd.client.future.DefaultAuthFuture;
+import org.apache.sshd.common.Service;
+import org.apache.sshd.common.ServiceFactory;
+import org.apache.sshd.common.Session;
+import org.apache.sshd.common.SshConstants;
+import org.apache.sshd.common.SshException;
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.DefaultCloseFuture;
+import org.apache.sshd.common.util.Buffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Client side <code>ssh-auth</code> service.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public class ClientUserAuthService implements Service {
+
+ public static class Factory implements ServiceFactory {
+
+ public String getName() {
+ return "ssh-userauth";
+ }
+
+ public Service create(Session session) throws IOException {
+ return new ClientUserAuthService(session);
+ }
+ }
+
+ /** Our logger */
+ protected final Logger log = LoggerFactory.getLogger(getClass());
+
+ /**
+ * When !authFuture.isDone() the current authentication
+ */
+ private UserAuth userAuth;
+
+ /**
+ * The AuthFuture that is being used by the current auth request. This encodes the state.
+ * isSuccess -> authenticated, else if isDone -> server waiting for user auth, else authenticating.
+ */
+ private volatile AuthFuture authFuture;
+
+ protected final ClientSessionImpl session;
+ protected final Object lock;
+
+ public ClientUserAuthService(Session s) {
+ if (!(s instanceof ClientSessionImpl)) {
+ throw new IllegalStateException("Client side service used on server side");
+ }
+ session = (ClientSessionImpl) s;
+ lock = session.getLock();
+ // Maintain the current auth status in the authFuture.
+ authFuture = new DefaultAuthFuture(lock);
+ }
+
+ public ClientSessionImpl getSession() {
+ return session;
+ }
+
+ public void start() {
+ synchronized (lock) {
+ log.debug("accepted");
+ // kick start the authentication process by failing the pending auth.
+ this.authFuture.setAuthed(false);
+ }
+ }
+
+ public void process(SshConstants.Message cmd, Buffer buffer) throws Exception {
+ if (this.authFuture.isSuccess()) {
+ throw new IllegalStateException("UserAuth message delivered to authenticated client");
+ } else if (this.authFuture.isDone()) {
+ log.debug("Ignoring random message");
+ // ignore for now; TODO: random packets
+ } else if (cmd == SshConstants.Message.SSH_MSG_USERAUTH_BANNER) {
+ String welcome = buffer.getString();
+ String lang = buffer.getString();
+ log.debug("Welcome banner: {}", welcome);
+ UserInteraction ui = session.getClientFactoryManager().getUserInteraction();
+ if (ui != null) {
+ ui.welcome(welcome);
+ }
+ } else {
+ buffer.rpos(buffer.rpos() - 1);
+ processUserAuth(buffer);
+ }
+ }
+
+ /**
+ * return true if/when ready for auth; false if never ready.
+ * @return server is ready and waiting for auth
+ */
+ private boolean readyForAuth(UserAuth userAuth) {
+ // isDone indicates that the last auth finished and a new one can commence.
+ while (!this.authFuture.isDone()) {
+ log.debug("waiting to send authentication");
+ try {
+ this.authFuture.await();
+ } catch (InterruptedException e) {
+ log.debug("Unexpected interrupt", e);
+ throw new RuntimeException(e);
+ }
+ }
+ if (this.authFuture.isSuccess()) {
+ log.debug("already authenticated");
+ throw new IllegalStateException("Already authenticated");
+ }
+ if (this.authFuture.getException() != null) {
+ log.debug("probably closed", this.authFuture.getException());
+ return false;
+ }
+ if (!this.authFuture.isFailure()) {
+ log.debug("unexpected state");
+ throw new IllegalStateException("Unexpected authentication state");
+ }
+ if (this.userAuth != null) {
+ log.debug("authentication already in progress");
+ throw new IllegalStateException("Authentication already in progress?");
+ }
+ // Set up the next round of authentication. Each round gets a new lock.
+ this.userAuth = userAuth;
+ // The new future !isDone() - i.e., in progress blocking out other waits.
+ this.authFuture = new DefaultAuthFuture(lock);
+ log.debug("ready to try authentication with new lock");
+ return true;
+ }
+
+ /**
+ * execute one step in user authentication.
+ * @param buffer
+ * @throws IOException
+ */
+ private void processUserAuth(Buffer buffer) throws IOException {
+ log.debug("processing {}", userAuth);
+ switch (userAuth.next(buffer)) {
+ case Success:
+ log.debug("succeeded with {}", userAuth);
+ session.setAuthenticated(userAuth.getUsername());
+ session.switchToNextService();
+ // Will wake up anyone sitting in waitFor
+ authFuture.setAuthed(true);
+ break;
+ case Failure:
+ log.debug("failed with {}", userAuth);
+ this.userAuth = null;
+ // Will wake up anyone sitting in waitFor
+ this.authFuture.setAuthed(false);
+ break;
+ case Continued:
+ // Will wake up anyone sitting in waitFor
+ log.debug("continuing with {}", userAuth);
+ break;
+ }
+ }
+
+ public CloseFuture close(boolean immediately) {
+ if (!authFuture.isDone()) {
+ authFuture.setException(new SshException("Session is closed"));
+ }
+ CloseFuture future = new DefaultCloseFuture(lock);
+ future.setClosed();
+ return future;
+ }
+
+ public AuthFuture auth(UserAuth userAuth) throws IOException {
+ log.debug("Trying authentication with {}", userAuth);
+ synchronized (lock) {
+ if (readyForAuth(userAuth)) {
+ processUserAuth(null);
+ }
+ return authFuture;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
index eaa1088..450dce4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
@@ -59,6 +59,7 @@ public abstract class AbstractFactoryManager implements FactoryManager {
protected TcpipForwarderFactory tcpipForwarderFactory;
protected ForwardingFilter tcpipForwardingFilter;
protected FileSystemFactory fileSystemFactory;
+ protected List<ServiceFactory> serviceFactories;
protected AbstractFactoryManager() {
loadVersion();
@@ -228,4 +229,11 @@ public abstract class AbstractFactoryManager implements FactoryManager {
this.fileSystemFactory = fileSystemFactory;
}
+ public List<ServiceFactory> getServiceFactories() {
+ return serviceFactories;
+ }
+
+ public void setServiceFactories(List<ServiceFactory> serviceFactories) {
+ this.serviceFactories = serviceFactories;
+ }
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/Channel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Channel.java b/sshd-core/src/main/java/org/apache/sshd/common/Channel.java
index 6e2c030..aceaef3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/Channel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/Channel.java
@@ -23,6 +23,7 @@ import java.io.IOException;
import org.apache.sshd.client.future.OpenFuture;
import org.apache.sshd.common.channel.Window;
import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.util.Buffer;
/**
@@ -58,7 +59,7 @@ public interface Channel {
CloseFuture close(boolean immediately);
- void init(Session session, int id) throws IOException;
+ void init(ConnectionService service, Session session, int id) throws IOException;
/**
* For a server channel, this method will actually open the channel
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
index f5bc47c..86e0155 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/FactoryManager.java
@@ -177,4 +177,11 @@ public interface FactoryManager {
*/
FileSystemFactory getFileSystemFactory();
+ /**
+ * Retrieve the list of SSH <code>Service</code> factories.
+ *
+ * @return a list of named <code>Service</code> factories, never <code>null</code>
+ */
+ List<ServiceFactory> getServiceFactories();
+
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/Service.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Service.java b/sshd-core/src/main/java/org/apache/sshd/common/Service.java
new file mode 100644
index 0000000..e3f60b3
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/Service.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.io.IOException;
+
+import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.util.Buffer;
+
+/**
+ * See RFC 4253 [SSH-TRANS] and the SSH_MSG_SERVICE_REQUEST packet. Examples include ssh-userauth
+ * and ssh-connection but developers are also free to implement their own custom service.
+ *
+ * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
+ */
+public interface Service {
+
+ Session getSession();
+
+ // TODO: this is specific to clients
+ void start();
+
+ /**
+ * Service the request.
+ * @param buffer
+ * @throws Exception
+ */
+ void process(SshConstants.Message cmd, Buffer buffer) throws Exception;
+
+ /**
+ * Close the service.
+ * @param immediately
+ *
+ */
+ CloseFuture close(boolean immediately);
+
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java
new file mode 100644
index 0000000..b70b963
--- /dev/null
+++ b/sshd-core/src/main/java/org/apache/sshd/common/ServiceFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sshd.common;
+
+import java.io.IOException;
+import java.util.List;
+
+public interface ServiceFactory {
+
+ /**
+ * Name of this factory
+ * @return
+ */
+ String getName();
+
+ Service create(Session session) throws IOException;
+
+ /**
+ * Utility class to help using NamedFactories
+ */
+ public static class Utils {
+
+ /**
+ * Create an instance of the specified name by looking up the needed factory
+ * in the list.
+ *
+ * @param factories list of available factories
+ * @param name the factory name to use
+ * @return a newly created object or <code>null</code> if the factory is not in the list
+ */
+ public static Service create(List<ServiceFactory> factories, String name, Session session) throws IOException {
+ if (factories != null) {
+ for (ServiceFactory f : factories) {
+ if (f.getName().equals(name)) {
+ return f.create(session);
+ }
+ }
+ }
+ return null;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/Session.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Session.java b/sshd-core/src/main/java/org/apache/sshd/common/Session.java
index 52be5cf..cc968e3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/Session.java
@@ -31,7 +31,7 @@ import org.apache.sshd.common.util.Buffer;
public interface Session {
public enum State {
- ReceiveKexInit, Kex, ReceiveNewKeys, AuthRequestSent, WaitForAuth, UserAuth, Running, Closed
+ ReceiveKexInit, Kex, ReceiveNewKeys, ServiceRequestSent, WaitForServiceRequest, Running, Closed
}
/**
@@ -135,27 +135,10 @@ public interface Session {
* {@link org.apache.sshd.common.SshException}.
*
* @param t the exception to process
- * @throws IOException
*/
void exceptionCaught(Throwable t);
/**
- * Register a newly created channel with a new unique identifier
- *
- * @param channel the channel to register
- * @return the id of this channel
- * @throws Exception
- */
- int registerChannel(Channel channel) throws Exception;
-
- /**
- * Remove this channel from the list of managed channels
- *
- * @param channel the channel
- */
- void unregisterChannel(Channel channel);
-
- /**
* Add a session |listener|.
*
* @param listener the session listener to add
@@ -170,12 +153,6 @@ public interface Session {
void removeListener(SessionListener listener);
/**
- * Retrieve the tcpip forwarder
- * @return
- */
- TcpipForwarder getTcpipForwarder();
-
- /**
* Type safe key for storage within the user attributes of {@link org.apache.sshd.common.session.AbstractSession}.
* Typically it is used as a static variable that is shared between the producer
* and the consumer. To further restrict access the setting or getting it from
@@ -191,7 +168,7 @@ public interface Session {
* s.setAttribute(MY_KEY, value);
* }
*
- * @param T type of value stored in the attribute.
+ * @param <T> type of value stored in the attribute.
*
* @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
*/
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/TcpipForwarderFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/TcpipForwarderFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/TcpipForwarderFactory.java
index c19fb5f..1bf6a45 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/TcpipForwarderFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/TcpipForwarderFactory.java
@@ -18,6 +18,8 @@
*/
package org.apache.sshd.common;
+import org.apache.sshd.common.session.ConnectionService;
+
/**
* A factory for creating TcpipForwarder objects for client Port forwarding
*/
@@ -27,9 +29,9 @@ public interface TcpipForwarderFactory {
* Creates the TcpipForwarder to be used for TCP/IP port forwards for
* this ClientSession.
*
- * @param session the Session the connections are forwarded through
+ * @param service the service the connections are forwarded through
* @return the TcpipForwarder that will listen for connections and set up forwarding
*/
- public TcpipForwarder create(Session session);
+ public TcpipForwarder create(ConnectionService service);
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
index 95ca72f..05b633a 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
@@ -29,6 +29,7 @@ import org.apache.sshd.common.future.CloseFuture;
import org.apache.sshd.common.future.DefaultCloseFuture;
import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoWriteFuture;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.common.util.BufferUtils;
import org.slf4j.Logger;
@@ -48,6 +49,7 @@ public abstract class AbstractChannel implements Channel {
protected final Object lock = new Object();
protected final Window localWindow = new Window(this, null, getClass().getName().contains(".client."), true);
protected final Window remoteWindow = new Window(this, null, getClass().getName().contains(".client."), false);
+ protected ConnectionService service;
protected Session session;
protected int id;
protected int recipient;
@@ -80,7 +82,8 @@ public abstract class AbstractChannel implements Channel {
throw new IllegalStateException();
}
- public void init(Session session, int id) {
+ public void init(ConnectionService service, Session session, int id) {
+ this.service = service;
this.session = session;
this.id = id;
configureWindow();
@@ -101,7 +104,7 @@ public abstract class AbstractChannel implements Channel {
postClose();
closeFuture.setClosed();
notifyStateChanged();
- session.unregisterChannel(AbstractChannel.this);
+ service.unregisterChannel(AbstractChannel.this);
}
});
} else {
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
index 640e1a2..45d8612 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
@@ -38,6 +38,7 @@ import org.apache.sshd.common.future.SshFutureListener;
import org.apache.sshd.common.io.IoAcceptor;
import org.apache.sshd.common.io.IoHandler;
import org.apache.sshd.common.io.IoSession;
+import org.apache.sshd.common.session.ConnectionService;
import org.apache.sshd.common.util.Buffer;
import org.apache.sshd.common.util.Readable;
import org.slf4j.Logger;
@@ -52,14 +53,16 @@ public class DefaultTcpipForwarder implements TcpipForwarder, IoHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultTcpipForwarder.class);
+ private final ConnectionService service;
private final Session session;
private final Map<Integer, SshdSocketAddress> localToRemote = new HashMap<Integer, SshdSocketAddress>();
private final Map<Integer, SshdSocketAddress> remoteToLocal = new HashMap<Integer, SshdSocketAddress>();
private final Set<SshdSocketAddress> localForwards = new HashSet<SshdSocketAddress>();
protected IoAcceptor acceptor;
- public DefaultTcpipForwarder(Session session) {
- this.session = session;
+ public DefaultTcpipForwarder(ConnectionService service) {
+ this.service = service;
+ this.session = service.getSession();
}
//
@@ -174,12 +177,12 @@ public class DefaultTcpipForwarder implements TcpipForwarder, IoHandler {
channel = new TcpipClientChannel(TcpipClientChannel.Type.Forwarded, session, null);
}
session.setAttribute(TcpipClientChannel.class, channel);
- this.session.registerChannel(channel);
+ this.service.registerChannel(channel);
channel.open().addListener(new SshFutureListener<OpenFuture>() {
public void operationComplete(OpenFuture future) {
Throwable t = future.getException();
if (t != null) {
- DefaultTcpipForwarder.this.session.unregisterChannel(channel);
+ DefaultTcpipForwarder.this.service.unregisterChannel(channel);
channel.close(false);
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarderFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarderFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarderFactory.java
index 9de1d4a..a732d7e 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarderFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarderFactory.java
@@ -21,6 +21,7 @@ package org.apache.sshd.common.forward;
import org.apache.sshd.common.Session;
import org.apache.sshd.common.TcpipForwarder;
import org.apache.sshd.common.TcpipForwarderFactory;
+import org.apache.sshd.common.session.ConnectionService;
/**
* The default {link TcpipForwarderFactory} implementation.
@@ -30,8 +31,8 @@ import org.apache.sshd.common.TcpipForwarderFactory;
*/
public class DefaultTcpipForwarderFactory implements TcpipForwarderFactory
{
- public TcpipForwarder create( Session session )
+ public TcpipForwarder create( ConnectionService service )
{
- return new DefaultTcpipForwarder( session );
+ return new DefaultTcpipForwarder( service );
}
}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/03aa3979/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
index 6ba0e7d..2e98811 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipServerChannel.java
@@ -98,7 +98,7 @@ public class TcpipServerChannel extends AbstractServerChannel {
SshdSocketAddress address = null;
switch (type) {
case Direct: address = new SshdSocketAddress(hostToConnect, portToConnect); break;
- case Forwarded: address = getSession().getTcpipForwarder().getForwardedPort(portToConnect); break;
+ case Forwarded: address = service.getTcpipForwarder().getForwardedPort(portToConnect); break;
}
final ForwardingFilter filter = getSession().getFactoryManager().getTcpipForwardingFilter();
if (address == null || filter == null || !filter.canConnect(address, getSession())) {
[3/5] git commit: Add more moduli for DHGEX
Posted by gn...@apache.org.
Add more moduli for DHGEX
Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/1ea3dfe2
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/1ea3dfe2
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/1ea3dfe2
Branch: refs/heads/master
Commit: 1ea3dfe251d08017c393e52cb98e5db76b1d9b78
Parents: 1d800d3
Author: Guillaume Nodet <gn...@apache.org>
Authored: Wed Jan 29 10:16:46 2014 +0100
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Wed Jan 29 10:16:46 2014 +0100
----------------------------------------------------------------------
.../filtered-resources/org/apache/sshd/moduli | 64 +++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)
----------------------------------------------------------------------