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 --- .../Controller/Service/TCPRelay.cs | 2 +- shadowsocks-csharp/Data/cn.txt | 1 + shadowsocks-csharp/Data/libsscrypto2.dll.gz | Bin 0 -> 45874 bytes .../Encryption/EncryptorBase.cs | 4 +- .../Encryption/EncryptorFactory.cs | 6 +- shadowsocks-csharp/Encryption/IVEncryptor.cs | 68 ++++++++++- .../Encryption/PolarSSLEncryptor.cs | 4 +- shadowsocks-csharp/Encryption/Sodium.cs | 37 +++++- .../Encryption/SodiumEncryptor.cs | 4 +- .../Encryption/TableEncryptor.cs | 4 +- shadowsocks-csharp/Model/Server.cs | 5 + .../Properties/Resources.Designer.cs | 106 ++++++++++-------- shadowsocks-csharp/Properties/Resources.resx | 3 + .../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 HcmV?d00001 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,8 +12,15 @@ 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"; @@ -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 @@ +