From 1564e9ff8117d04ab3e53e1c83dea7061a9ab176 Mon Sep 17 00:00:00 2001 From: Gang Zhuo Date: Sat, 19 Sep 2015 11:06:15 +0800 Subject: [PATCH] support onetime auth --- shadowsocks-csharp/Controller/Service/TCPRelay.cs | 2 +- shadowsocks-csharp/Data/cn.txt | 1 + shadowsocks-csharp/Data/libsscrypto2.dll.gz | Bin 0 -> 45874 bytes shadowsocks-csharp/Encryption/EncryptorBase.cs | 4 +- shadowsocks-csharp/Encryption/EncryptorFactory.cs | 6 +- shadowsocks-csharp/Encryption/IVEncryptor.cs | 68 ++++++++++++- shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs | 4 +- shadowsocks-csharp/Encryption/Sodium.cs | 37 ++++++- shadowsocks-csharp/Encryption/SodiumEncryptor.cs | 4 +- shadowsocks-csharp/Encryption/TableEncryptor.cs | 4 +- shadowsocks-csharp/Model/Server.cs | 5 + .../Properties/Resources.Designer.cs | 106 +++++++++++---------- shadowsocks-csharp/Properties/Resources.resx | 3 + shadowsocks-csharp/View/ConfigForm.Designer.cs | 53 +++++++---- shadowsocks-csharp/View/ConfigForm.cs | 5 +- shadowsocks-csharp/shadowsocks-csharp.csproj | 1 + 16 files changed, 219 insertions(+), 84 deletions(-) create mode 100644 shadowsocks-csharp/Data/libsscrypto2.dll.gz diff --git a/shadowsocks-csharp/Controller/Service/TCPRelay.cs b/shadowsocks-csharp/Controller/Service/TCPRelay.cs index bf0497d4..c1b39a04 100644 --- a/shadowsocks-csharp/Controller/Service/TCPRelay.cs +++ b/shadowsocks-csharp/Controller/Service/TCPRelay.cs @@ -124,7 +124,7 @@ namespace Shadowsocks.Controller { throw new ArgumentException("No server configured"); } - this.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password); + this.encryptor = EncryptorFactory.GetEncryptor(server.method, server.password, server.one_time_auth); this.server = server; } diff --git a/shadowsocks-csharp/Data/cn.txt b/shadowsocks-csharp/Data/cn.txt index 81022f99..813578b7 100644 --- a/shadowsocks-csharp/Data/cn.txt +++ b/shadowsocks-csharp/Data/cn.txt @@ -39,6 +39,7 @@ Password=密码 Encryption=加密 Proxy Port=代理端口 Remarks=备注 +One-time authorization=一次性授权 OK=确定 Cancel=取消 New server=未配置的服务器 diff --git a/shadowsocks-csharp/Data/libsscrypto2.dll.gz b/shadowsocks-csharp/Data/libsscrypto2.dll.gz new file mode 100644 index 0000000000000000000000000000000000000000..83f7aab1186c37fedb817114cf895fad08b7100b GIT binary patch literal 45874 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 literal 0 KcmV+b0RR6000031 diff --git a/shadowsocks-csharp/Encryption/EncryptorBase.cs b/shadowsocks-csharp/Encryption/EncryptorBase.cs index 8b5cd61a..b92233ec 100644 --- a/shadowsocks-csharp/Encryption/EncryptorBase.cs +++ b/shadowsocks-csharp/Encryption/EncryptorBase.cs @@ -8,14 +8,16 @@ namespace Shadowsocks.Encryption { public const int MAX_INPUT_SIZE = 32768; - protected EncryptorBase(string method, string password) + protected EncryptorBase(string method, string password, bool onetimeauth) { Method = method; Password = password; + OnetimeAuth = onetimeauth; } protected string Method; protected string Password; + protected bool OnetimeAuth; protected byte[] GetPasswordHash() { diff --git a/shadowsocks-csharp/Encryption/EncryptorFactory.cs b/shadowsocks-csharp/Encryption/EncryptorFactory.cs index d5ff15e3..120bd53c 100644 --- a/shadowsocks-csharp/Encryption/EncryptorFactory.cs +++ b/shadowsocks-csharp/Encryption/EncryptorFactory.cs @@ -8,7 +8,7 @@ namespace Shadowsocks.Encryption { private static Dictionary _registeredEncryptors; - private static Type[] _constructorTypes = new Type[] { typeof(string), typeof(string) }; + private static Type[] _constructorTypes = new Type[] { typeof(string), typeof(string), typeof(bool) }; static EncryptorFactory() { @@ -27,7 +27,7 @@ namespace Shadowsocks.Encryption } } - public static IEncryptor GetEncryptor(string method, string password) + public static IEncryptor GetEncryptor(string method, string password, bool onetimeauth = false) { if (string.IsNullOrEmpty(method)) { @@ -36,7 +36,7 @@ namespace Shadowsocks.Encryption method = method.ToLowerInvariant(); Type t = _registeredEncryptors[method]; ConstructorInfo c = t.GetConstructor(_constructorTypes); - IEncryptor result = (IEncryptor)c.Invoke(new object[] { method, password }); + IEncryptor result = (IEncryptor)c.Invoke(new object[] { method, password, onetimeauth }); return result; } } diff --git a/shadowsocks-csharp/Encryption/IVEncryptor.cs b/shadowsocks-csharp/Encryption/IVEncryptor.cs index b82d3adf..869cdb58 100755 --- a/shadowsocks-csharp/Encryption/IVEncryptor.cs +++ b/shadowsocks-csharp/Encryption/IVEncryptor.cs @@ -2,12 +2,19 @@ using System.Collections.Generic; using System.Security.Cryptography; using System.Text; +using System.Net; namespace Shadowsocks.Encryption { public abstract class IVEncryptor : EncryptorBase { + public const int ONETIMEAUTH_FLAG = 0x10; + public const int ADDRTYPE_MASK = 0xF; + public const int ONETIMEAUTH_BYTES = 16; + public const int CRC_BUF_LEN = 128; + public const int CRC_BYTES = 2; + protected static byte[] tempbuf = new byte[MAX_INPUT_SIZE]; protected Dictionary ciphers; @@ -25,11 +32,17 @@ namespace Shadowsocks.Encryption protected byte[] _key; protected int keyLen; protected int ivLen; + protected byte[] crc_buf; + protected int crc_idx = 0; - public IVEncryptor(string method, string password) - : base(method, password) + public IVEncryptor(string method, string password, bool onetimeauth) + : base(method, password, onetimeauth) { InitKey(method, password); + if (OnetimeAuth) + { + crc_buf = new byte[CRC_BUF_LEN]; + } } protected abstract Dictionary getCiphers(); @@ -112,6 +125,28 @@ namespace Shadowsocks.Encryption protected abstract void cipherUpdate(bool isCipher, int length, byte[] buf, byte[] outbuf); + protected int GetSSHeadLength(byte[] buf, int length) + { + int len = 0; + int atyp = length > 0 ? (buf[0] & ADDRTYPE_MASK) : 0; + if (atyp == 1) + { + len = 7; // atyp (1 bytes) + ipv4 (4 bytes) + port (2 bytes) + } + else if (atyp == 3 && length > 1) + { + int nameLen = buf[1]; + len = 4 + nameLen; // atyp (1 bytes) + name length (1 bytes) + name (n bytes) + port (2 bytes) + } + else if (atyp == 4) + { + len = 19; // atyp (1 bytes) + ipv6 (16 bytes) + port (2 bytes) + } + if (len == 0 || len > length) + throw new Exception($"invalid header with addr type {atyp}"); + return len; + } + public override void Encrypt(byte[] buf, int length, byte[] outbuf, out int outlength) { if (!_encryptIVSent) @@ -122,6 +157,24 @@ namespace Shadowsocks.Encryption outlength = length + ivLen; lock (tempbuf) { + if (OnetimeAuth) + { + lock(crc_buf) + { + int headLen = GetSSHeadLength(buf, length); + int data_len = length - headLen; + Buffer.BlockCopy(buf, headLen, buf, headLen + ONETIMEAUTH_BYTES, data_len); + buf[0] |= ONETIMEAUTH_FLAG; + byte[] auth = new byte[ONETIMEAUTH_BYTES]; + Sodium.ss_onetimeauth(auth, buf, headLen, _encryptIV, ivLen, _key, keyLen); + Buffer.BlockCopy(auth, 0, buf, headLen, ONETIMEAUTH_BYTES); + int buf_offset = headLen + ONETIMEAUTH_BYTES; + int rc = Sodium.ss_gen_crc(buf, ref buf_offset, ref data_len, crc_buf, ref crc_idx, buf.Length); + if (rc != 0) + throw new Exception("failed to generate crc"); + length = headLen + ONETIMEAUTH_BYTES + data_len; + } + } cipherUpdate(true, length, buf, tempbuf); outlength = length + ivLen; Buffer.BlockCopy(tempbuf, 0, outbuf, ivLen, length); @@ -129,6 +182,16 @@ namespace Shadowsocks.Encryption } else { + if (OnetimeAuth) + { + lock(crc_buf) + { + int buf_offset = 0; + int rc = Sodium.ss_gen_crc(buf, ref buf_offset, ref length, crc_buf, ref crc_idx, buf.Length); + if (rc != 0) + throw new Exception("failed to generate crc"); + } + } outlength = length; cipherUpdate(true, length, buf, outbuf); } @@ -154,5 +217,6 @@ namespace Shadowsocks.Encryption cipherUpdate(false, length, buf, outbuf); } } + } } diff --git a/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs b/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs index 6216c24d..3aca3f72 100755 --- a/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs +++ b/shadowsocks-csharp/Encryption/PolarSSLEncryptor.cs @@ -16,8 +16,8 @@ namespace Shadowsocks.Encryption private IntPtr _encryptCtx = IntPtr.Zero; private IntPtr _decryptCtx = IntPtr.Zero; - public PolarSSLEncryptor(string method, string password) - : base(method, password) + public PolarSSLEncryptor(string method, string password, bool onetimeauth) + : base(method, password, onetimeauth) { InitKey(method, password); } diff --git a/shadowsocks-csharp/Encryption/Sodium.cs b/shadowsocks-csharp/Encryption/Sodium.cs index 564aaeda..14403267 100755 --- a/shadowsocks-csharp/Encryption/Sodium.cs +++ b/shadowsocks-csharp/Encryption/Sodium.cs @@ -12,9 +12,16 @@ namespace Shadowsocks.Encryption public class Sodium { const string DLLNAME = "libsscrypto"; + const string DLLNAME2 = "libsscrypto2"; static Sodium() { + LoadSSCryptoLibrary(); + LoadSSCrypto2Library(); + } + + static void LoadSSCryptoLibrary() + { string tempPath = Utils.GetTempPath(); string dllPath = tempPath + "/libsscrypto.dll"; try @@ -29,7 +36,24 @@ namespace Shadowsocks.Encryption { Console.WriteLine(e.ToString()); } - LoadLibrary(dllPath); + } + + static void LoadSSCrypto2Library() + { + string tempPath = Utils.GetTempPath(); + string dllPath = tempPath + "/libsscrypto2.dll"; + try + { + FileManager.UncompressFile(dllPath, Resources.libsscrypto2_dll); + LoadLibrary(dllPath); + } + catch (IOException) + { + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + } } [DllImport("Kernel32.dll")] @@ -40,5 +64,16 @@ namespace Shadowsocks.Encryption [DllImport(DLLNAME, CallingConvention = CallingConvention.Cdecl)] public extern static void crypto_stream_chacha20_xor_ic(byte[] c, byte[] m, ulong mlen, byte[] n, ulong ic, byte[] k); + + [DllImport(DLLNAME2, CallingConvention = CallingConvention.Cdecl)] + public extern static int ss_gen_crc(byte[] buf, ref int buf_offset, ref int data_len, + byte[] crc_buf, ref int crc_idx, int buf_size); + + [DllImport(DLLNAME2, CallingConvention = CallingConvention.Cdecl)] + public extern static int ss_onetimeauth(byte[] auth, + byte[] msg, int msg_len, + byte[] iv, int iv_len, + byte[] key, int key_len); } } + diff --git a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs index af51d0ac..8ab8e255 100755 --- a/shadowsocks-csharp/Encryption/SodiumEncryptor.cs +++ b/shadowsocks-csharp/Encryption/SodiumEncryptor.cs @@ -20,8 +20,8 @@ namespace Shadowsocks.Encryption protected ulong _encryptIC; protected ulong _decryptIC; - public SodiumEncryptor(string method, string password) - : base(method, password) + public SodiumEncryptor(string method, string password, bool onetimeauth) + : base(method, password, onetimeauth) { InitKey(method, password); } diff --git a/shadowsocks-csharp/Encryption/TableEncryptor.cs b/shadowsocks-csharp/Encryption/TableEncryptor.cs index db0a7db0..3de625a6 100644 --- a/shadowsocks-csharp/Encryption/TableEncryptor.cs +++ b/shadowsocks-csharp/Encryption/TableEncryptor.cs @@ -6,8 +6,8 @@ namespace Shadowsocks.Encryption public class TableEncryptor : EncryptorBase { - public TableEncryptor(string method, string password) - : base(method, password) + public TableEncryptor(string method, string password, bool onetimeauth) + : base(method, password, onetimeauth) { byte[] hash = GetPasswordHash(); // TODO endian diff --git a/shadowsocks-csharp/Model/Server.cs b/shadowsocks-csharp/Model/Server.cs index 24dd1162..55134335 100755 --- a/shadowsocks-csharp/Model/Server.cs +++ b/shadowsocks-csharp/Model/Server.cs @@ -17,6 +17,7 @@ namespace Shadowsocks.Model public string password; public string method; public string remarks; + public bool one_time_auth; public override int GetHashCode() { @@ -52,6 +53,7 @@ namespace Shadowsocks.Model this.method = "aes-256-cfb"; this.password = ""; this.remarks = ""; + this.one_time_auth = false; } public Server(string ssURL) : this() @@ -88,6 +90,9 @@ namespace Shadowsocks.Model string[] parts = beforeAt.Split(new[] { ':' }); this.method = parts[0]; this.password = parts[1]; + + //TODO: read one_time_auth + } catch (IndexOutOfRangeException) { diff --git a/shadowsocks-csharp/Properties/Resources.Designer.cs b/shadowsocks-csharp/Properties/Resources.Designer.cs index 198e9f48..a5891002 100644 --- a/shadowsocks-csharp/Properties/Resources.Designer.cs +++ b/shadowsocks-csharp/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ @@ -13,12 +13,12 @@ namespace Shadowsocks.Properties { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// 一个强类型的资源类,用于查找本地化的字符串等。 /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] @@ -33,7 +33,7 @@ namespace Shadowsocks.Properties { } /// - /// Returns the cached ResourceManager instance used by this class. + /// 返回此类使用的缓存的 ResourceManager 实例。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ namespace Shadowsocks.Properties { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// 使用此强类型资源类,为所有资源查找 + /// 重写当前线程的 CurrentUICulture 属性。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] abp_js { get { @@ -71,30 +71,28 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to # translation for Simplified Chinese - /// - ///Shadowsocks=Shadowsocks - /// - ///# Menu items - /// - ///Enable System Proxy=启用系统代理 - ///Mode=系统代理模式 - ///PAC=PAC 模式 - ///Global=全局模式 - ///Servers=服务器 - ///Edit Servers...=编辑服务器... - ///Start on Boot=开机启动 - ///Allow Clients from LAN=允许来自局域网的连接 - ///Local PAC=使用本地 PAC - ///Online PAC=使用在线 PAC - ///Edit Local PAC File...=编辑本地 PAC 文件... - ///Update Local PAC from GFWList=从 GFWList 更新本地 PAC - ///Edit User Rule for GFWList...=编辑 GFWList 的用户规则... - ///Show QRCode...=显示二维码... - ///Scan QRCode from Screen...=扫描屏幕上的二维码... - ///Show Logs...=显示日志... - ///About...=关于... - ///Quit=退出 [rest of string was truncated]";. + /// 查找类似 # translation for Simplified Chinese + /// + ///Shadowsocks=Shadowsocks + /// + ///# Menu items + /// + ///Enable System Proxy=启用系统代理 + ///Mode=系统代理模式 + ///PAC=PAC 模式 + ///Global=全局模式 + ///Servers=服务器 + ///Edit Servers...=编辑服务器... + ///Start on Boot=开机启动 + ///Allow Clients from LAN=允许来自局域网的连接 + ///Local PAC=使用本地 PAC + ///Online PAC=使用在线 PAC + ///Edit Local PAC File...=编辑本地 PAC 文件... + ///Update Local PAC from GFWList=从 GFWList 更新本地 PAC + ///Edit User Rule for GFWList...=编辑 GFWList 的用户规则... + ///Show QRCode...=显示二维码... + ///Scan QRCode from Screen...=扫描屏幕上的二维码... + ///Availability Statistic [字符串的其余部分被截断]"; 的本地化字符串。 /// internal static string cn { get { @@ -103,7 +101,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] libsscrypto_dll { get { @@ -113,7 +111,17 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 + /// + internal static byte[] libsscrypto2_dll { + get { + object obj = ResourceManager.GetObject("libsscrypto2_dll", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] mgwz_dll { get { @@ -123,11 +131,11 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to listen-address __POLIPO_BIND_IP__:8123 + /// 查找类似 listen-address __POLIPO_BIND_IP__:8123 ///show-on-task-bar 0 ///activity-animation 0 ///forward-socks5 / 127.0.0.1:__SOCKS_PORT__ . - ///hide-console. + ///hide-console 的本地化字符串。 /// internal static string privoxy_conf { get { @@ -136,7 +144,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] privoxy_exe { get { @@ -146,7 +154,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Byte[]. + /// 查找 System.Byte[] 类型的本地化资源。 /// internal static byte[] proxy_pac_txt { get { @@ -156,7 +164,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ss16 { get { @@ -166,7 +174,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ss20 { get { @@ -176,7 +184,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ss24 { get { @@ -186,7 +194,7 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// 查找 System.Drawing.Bitmap 类型的本地化资源。 /// internal static System.Drawing.Bitmap ssw128 { get { @@ -196,9 +204,9 @@ namespace Shadowsocks.Properties { } /// - /// Looks up a localized string similar to ! Put user rules line by line in this file. + /// 查找类似 ! Put user rules line by line in this file. ///! See https://adblockplus.org/en/filter-cheatsheet - ///. + /// 的本地化字符串。 /// internal static string user_rule { get { diff --git a/shadowsocks-csharp/Properties/Resources.resx b/shadowsocks-csharp/Properties/Resources.resx index aa0c2f63..36dc1386 100755 --- a/shadowsocks-csharp/Properties/Resources.resx +++ b/shadowsocks-csharp/Properties/Resources.resx @@ -124,6 +124,9 @@ ..\data\cn.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8 + + ..\Data\libsscrypto2.dll.gz;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + ..\data\libsscrypto.dll.gz;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 diff --git a/shadowsocks-csharp/View/ConfigForm.Designer.cs b/shadowsocks-csharp/View/ConfigForm.Designer.cs index f8b5940a..e985937e 100755 --- a/shadowsocks-csharp/View/ConfigForm.Designer.cs +++ b/shadowsocks-csharp/View/ConfigForm.Designer.cs @@ -55,6 +55,7 @@ this.ProxyPortLabel = new System.Windows.Forms.Label(); this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); + this.OneTimeAuth = new System.Windows.Forms.CheckBox(); this.tableLayoutPanel1.SuspendLayout(); this.ServerGroupBox.SuspendLayout(); this.tableLayoutPanel2.SuspendLayout(); @@ -81,18 +82,20 @@ this.tableLayoutPanel1.Controls.Add(this.PasswordTextBox, 1, 2); this.tableLayoutPanel1.Controls.Add(this.EncryptionLabel, 0, 3); this.tableLayoutPanel1.Controls.Add(this.EncryptionSelect, 1, 3); + this.tableLayoutPanel1.Controls.Add(this.OneTimeAuth, 1, 6); this.tableLayoutPanel1.Location = new System.Drawing.Point(8, 21); this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.Padding = new System.Windows.Forms.Padding(3); - this.tableLayoutPanel1.RowCount = 6; + this.tableLayoutPanel1.RowCount = 7; this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.Size = new System.Drawing.Size(238, 137); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + this.tableLayoutPanel1.Size = new System.Drawing.Size(238, 160); this.tableLayoutPanel1.TabIndex = 0; // // RemarksTextBox @@ -102,7 +105,7 @@ this.RemarksTextBox.MaxLength = 32; this.RemarksTextBox.Name = "RemarksTextBox"; this.RemarksTextBox.Size = new System.Drawing.Size(160, 20); - this.RemarksTextBox.TabIndex = 10; + this.RemarksTextBox.TabIndex = 4; this.RemarksTextBox.WordWrap = false; // // RemarksLabel @@ -188,7 +191,7 @@ // // EncryptionSelect // - this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.EncryptionSelect.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.EncryptionSelect.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.EncryptionSelect.FormattingEnabled = true; @@ -226,7 +229,7 @@ this.OKButton.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0); this.OKButton.Name = "OKButton"; this.OKButton.Size = new System.Drawing.Size(75, 23); - this.OKButton.TabIndex = 8; + this.OKButton.TabIndex = 12; this.OKButton.Text = "OK"; this.OKButton.UseVisualStyleBackColor = true; this.OKButton.Click += new System.EventHandler(this.OKButton_Click); @@ -239,7 +242,7 @@ this.MyCancelButton.Margin = new System.Windows.Forms.Padding(3, 3, 0, 0); this.MyCancelButton.Name = "MyCancelButton"; this.MyCancelButton.Size = new System.Drawing.Size(75, 23); - this.MyCancelButton.TabIndex = 9; + this.MyCancelButton.TabIndex = 13; this.MyCancelButton.Text = "Cancel"; this.MyCancelButton.UseVisualStyleBackColor = true; this.MyCancelButton.Click += new System.EventHandler(this.CancelButton_Click); @@ -251,7 +254,7 @@ this.DeleteButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3); this.DeleteButton.Name = "DeleteButton"; this.DeleteButton.Size = new System.Drawing.Size(80, 23); - this.DeleteButton.TabIndex = 7; + this.DeleteButton.TabIndex = 9; this.DeleteButton.Text = "&Delete"; this.DeleteButton.UseVisualStyleBackColor = true; this.DeleteButton.Click += new System.EventHandler(this.DeleteButton_Click); @@ -263,7 +266,7 @@ this.AddButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3); this.AddButton.Name = "AddButton"; this.AddButton.Size = new System.Drawing.Size(80, 23); - this.AddButton.TabIndex = 6; + this.AddButton.TabIndex = 8; this.AddButton.Text = "&Add"; this.AddButton.UseVisualStyleBackColor = true; this.AddButton.Click += new System.EventHandler(this.AddButton_Click); @@ -276,8 +279,8 @@ this.ServerGroupBox.Location = new System.Drawing.Point(178, 0); this.ServerGroupBox.Margin = new System.Windows.Forms.Padding(12, 0, 0, 0); this.ServerGroupBox.Name = "ServerGroupBox"; - this.ServerGroupBox.Size = new System.Drawing.Size(249, 174); - this.ServerGroupBox.TabIndex = 6; + this.ServerGroupBox.Size = new System.Drawing.Size(249, 197); + this.ServerGroupBox.TabIndex = 0; this.ServerGroupBox.TabStop = false; this.ServerGroupBox.Text = "Server"; // @@ -285,12 +288,11 @@ // this.ServersListBox.FormattingEnabled = true; this.ServersListBox.IntegralHeight = false; - this.ServersListBox.ItemHeight = 12; this.ServersListBox.Location = new System.Drawing.Point(0, 0); this.ServersListBox.Margin = new System.Windows.Forms.Padding(0); this.ServersListBox.Name = "ServersListBox"; this.ServersListBox.Size = new System.Drawing.Size(166, 148); - this.ServersListBox.TabIndex = 5; + this.ServersListBox.TabIndex = 7; this.ServersListBox.SelectedIndexChanged += new System.EventHandler(this.ServersListBox_SelectedIndexChanged); // // tableLayoutPanel2 @@ -313,7 +315,7 @@ this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel2.Size = new System.Drawing.Size(427, 238); + this.tableLayoutPanel2.Size = new System.Drawing.Size(427, 261); this.tableLayoutPanel2.TabIndex = 7; // // tableLayoutPanel6 @@ -326,7 +328,7 @@ this.tableLayoutPanel6.Controls.Add(this.MoveDownButton, 1, 0); this.tableLayoutPanel6.Controls.Add(this.MoveUpButton, 0, 0); this.tableLayoutPanel6.Dock = System.Windows.Forms.DockStyle.Top; - this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 211); + this.tableLayoutPanel6.Location = new System.Drawing.Point(0, 229); this.tableLayoutPanel6.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel6.Name = "tableLayoutPanel6"; this.tableLayoutPanel6.RowCount = 1; @@ -341,7 +343,7 @@ this.MoveDownButton.Margin = new System.Windows.Forms.Padding(3, 6, 0, 3); this.MoveDownButton.Name = "MoveDownButton"; this.MoveDownButton.Size = new System.Drawing.Size(80, 23); - this.MoveDownButton.TabIndex = 7; + this.MoveDownButton.TabIndex = 11; this.MoveDownButton.Text = "Move D&own"; this.MoveDownButton.UseVisualStyleBackColor = true; this.MoveDownButton.Click += new System.EventHandler(this.MoveDownButton_Click); @@ -353,7 +355,7 @@ this.MoveUpButton.Margin = new System.Windows.Forms.Padding(0, 6, 3, 3); this.MoveUpButton.Name = "MoveUpButton"; this.MoveUpButton.Size = new System.Drawing.Size(80, 23); - this.MoveUpButton.TabIndex = 6; + this.MoveUpButton.TabIndex = 10; this.MoveUpButton.Text = "Move &Up"; this.MoveUpButton.UseVisualStyleBackColor = true; this.MoveUpButton.Click += new System.EventHandler(this.MoveUpButton_Click); @@ -369,7 +371,7 @@ this.tableLayoutPanel5.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.tableLayoutPanel5.Controls.Add(this.ProxyPortTextBox, 1, 0); this.tableLayoutPanel5.Controls.Add(this.ProxyPortLabel, 0, 0); - this.tableLayoutPanel5.Location = new System.Drawing.Point(241, 174); + this.tableLayoutPanel5.Location = new System.Drawing.Point(241, 197); this.tableLayoutPanel5.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel5.Name = "tableLayoutPanel5"; this.tableLayoutPanel5.Padding = new System.Windows.Forms.Padding(3); @@ -389,7 +391,7 @@ this.ProxyPortTextBox.MaxLength = 10; this.ProxyPortTextBox.Name = "ProxyPortTextBox"; this.ProxyPortTextBox.Size = new System.Drawing.Size(113, 20); - this.ProxyPortTextBox.TabIndex = 4; + this.ProxyPortTextBox.TabIndex = 6; this.ProxyPortTextBox.WordWrap = false; // // ProxyPortLabel @@ -413,7 +415,7 @@ this.tableLayoutPanel3.Controls.Add(this.MyCancelButton, 1, 0); this.tableLayoutPanel3.Controls.Add(this.OKButton, 0, 0); this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Right; - this.tableLayoutPanel3.Location = new System.Drawing.Point(268, 209); + this.tableLayoutPanel3.Location = new System.Drawing.Point(268, 232); this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(3, 3, 0, 3); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; this.tableLayoutPanel3.RowCount = 1; @@ -431,7 +433,7 @@ this.tableLayoutPanel4.Controls.Add(this.DeleteButton, 1, 0); this.tableLayoutPanel4.Controls.Add(this.AddButton, 0, 0); this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Top; - this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 174); + this.tableLayoutPanel4.Location = new System.Drawing.Point(0, 197); this.tableLayoutPanel4.Margin = new System.Windows.Forms.Padding(0); this.tableLayoutPanel4.Name = "tableLayoutPanel4"; this.tableLayoutPanel4.RowCount = 1; @@ -439,6 +441,16 @@ this.tableLayoutPanel4.Size = new System.Drawing.Size(166, 32); this.tableLayoutPanel4.TabIndex = 8; // + // OneTimeAuth + // + this.OneTimeAuth.AutoSize = true; + this.OneTimeAuth.Location = new System.Drawing.Point(72, 137); + this.OneTimeAuth.Name = "OneTimeAuth"; + this.OneTimeAuth.Size = new System.Drawing.Size(131, 17); + this.OneTimeAuth.TabIndex = 5; + this.OneTimeAuth.Text = "One-time authorization"; + this.OneTimeAuth.UseVisualStyleBackColor = true; + // // ConfigForm // this.AcceptButton = this.OKButton; @@ -505,6 +517,7 @@ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel6; private System.Windows.Forms.Button MoveDownButton; private System.Windows.Forms.Button MoveUpButton; + private System.Windows.Forms.CheckBox OneTimeAuth; } } diff --git a/shadowsocks-csharp/View/ConfigForm.cs b/shadowsocks-csharp/View/ConfigForm.cs index dc290249..b4b1b6bd 100755 --- a/shadowsocks-csharp/View/ConfigForm.cs +++ b/shadowsocks-csharp/View/ConfigForm.cs @@ -48,6 +48,7 @@ namespace Shadowsocks.View EncryptionLabel.Text = I18N.GetString("Encryption"); ProxyPortLabel.Text = I18N.GetString("Proxy Port"); RemarksLabel.Text = I18N.GetString("Remarks"); + OneTimeAuth.Text = I18N.GetString("One-time authorization"); ServerGroupBox.Text = I18N.GetString("Server"); OKButton.Text = I18N.GetString("OK"); MyCancelButton.Text = I18N.GetString("Cancel"); @@ -82,7 +83,8 @@ namespace Shadowsocks.View server_port = int.Parse(ServerPortTextBox.Text), password = PasswordTextBox.Text, method = EncryptionSelect.Text, - remarks = RemarksTextBox.Text + remarks = RemarksTextBox.Text, + one_time_auth = OneTimeAuth.Checked }; int localPort = int.Parse(ProxyPortTextBox.Text); Configuration.CheckServer(server); @@ -115,6 +117,7 @@ namespace Shadowsocks.View ProxyPortTextBox.Text = _modifiedConfiguration.localPort.ToString(); EncryptionSelect.Text = server.method ?? "aes-256-cfb"; RemarksTextBox.Text = server.remarks; + OneTimeAuth.Checked = server.one_time_auth; } } diff --git a/shadowsocks-csharp/shadowsocks-csharp.csproj b/shadowsocks-csharp/shadowsocks-csharp.csproj index 8200aa07..89389fab 100644 --- a/shadowsocks-csharp/shadowsocks-csharp.csproj +++ b/shadowsocks-csharp/shadowsocks-csharp.csproj @@ -205,6 +205,7 @@ +