From d5205c74cfe8a66cf4fa176b86a249e5f55c8501 Mon Sep 17 00:00:00 2001
From: lanrenwo <lanrenwo@users.noreply.github.com>
Date: Thu, 12 Jan 2023 10:09:33 +0800
Subject: [PATCH 1/4] =?UTF-8?q?=E5=85=BC=E5=AE=B9=E7=BE=A4=E6=99=96LDAP=20?=
 =?UTF-8?q?Server=E7=9A=84=E5=81=9C=E7=94=A8=E8=B4=A6=E5=8F=B7=E5=8A=9F?=
 =?UTF-8?q?=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 server/dbdata/userauth_ldap.go | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/server/dbdata/userauth_ldap.go b/server/dbdata/userauth_ldap.go
index 1ade05f..9d25783 100644
--- a/server/dbdata/userauth_ldap.go
+++ b/server/dbdata/userauth_ldap.go
@@ -8,6 +8,7 @@ import (
 	"net"
 	"reflect"
 	"regexp"
+	"strconv"
 	"time"
 
 	"github.com/go-ldap/ldap"
@@ -117,6 +118,10 @@ func (auth AuthLdap) checkUser(name, pwd string, g *Group) error {
 		}
 		return fmt.Errorf("LDAP发现 %s 用户,存在多个账号", name)
 	}
+	err = parseEntries(sr)
+	if err != nil {
+		return fmt.Errorf("LDAP %s 用户 %s", name, err.Error())
+	}
 	userDN := sr.Entries[0].DN
 	err = l.Bind(userDN, pwd)
 	if err != nil {
@@ -125,6 +130,32 @@ func (auth AuthLdap) checkUser(name, pwd string, g *Group) error {
 	return nil
 }
 
+func parseEntries(sr *ldap.SearchResult) error {
+	for _, attr := range sr.Entries[0].Attributes {
+		switch attr.Name {
+		case "shadowExpire":
+			// -1 启用, 1 停用, >1 从1970-01-01至到期日的天数
+			val, _ := strconv.ParseInt(attr.Values[0], 10, 64)
+			if val == -1 {
+				return nil
+			}
+			if val == 1 {
+				return fmt.Errorf("账号已停用")
+			}
+			if val > 1 {
+				expireTime := time.Unix(val*86400, 0)
+				t := time.Date(expireTime.Year(), expireTime.Month(), expireTime.Day(), 23, 59, 59, 0, time.Local)
+				if t.Before(time.Now()) {
+					return fmt.Errorf("账号已过期(过期日期: %s)", t.Format("2006-01-02"))
+				}
+				return nil
+			}
+			return fmt.Errorf("账号shadowExpire值异常: %d", val)
+		}
+	}
+	return nil
+}
+
 func ValidateDomainPort(addr string) bool {
 	re := regexp.MustCompile(`^([a-zA-Z0-9][-a-zA-Z0-9]{0,62}\.)+[A-Za-z]{2,18}\:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$`)
 	return re.MatchString(addr)

From 710cfe4244a5991f290d24b1ea4a052738865531 Mon Sep 17 00:00:00 2001
From: lanrenwo <lanrenwo@users.noreply.github.com>
Date: Thu, 12 Jan 2023 10:25:07 +0800
Subject: [PATCH 2/4] =?UTF-8?q?=E4=BF=AE=E5=A4=8DsniNewParser=E5=88=87?=
 =?UTF-8?q?=E7=89=87=E8=B6=8A=E7=95=8C=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 server/handler/payload_tcp_parser.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/server/handler/payload_tcp_parser.go b/server/handler/payload_tcp_parser.go
index cd0e581..6d3c4cc 100644
--- a/server/handler/payload_tcp_parser.go
+++ b/server/handler/payload_tcp_parser.go
@@ -56,7 +56,7 @@ func sniNewParser(b []byte) (uint8, string) {
 	sessionIDLength := int(rest[current])
 	current += 1
 	current += sessionIDLength
-	if current >= restLen {
+	if current+1 >= restLen {
 		return acc_proto_https, ""
 	}
 	cipherSuiteLength := (int(rest[current]) << 8) + int(rest[current+1])

From 29953911da714c2c1795db952fcb9e993f76c2ee Mon Sep 17 00:00:00 2001
From: bjdgyc <bjdgyc@163.com>
Date: Fri, 13 Jan 2023 11:32:48 +0800
Subject: [PATCH 3/4] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dip=E5=88=86=E9=85=8D?=
 =?UTF-8?q?=E7=9A=84bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 server/sessdata/ip_pool.go | 131 +++++++++++++++++++++----------------
 1 file changed, 75 insertions(+), 56 deletions(-)

diff --git a/server/sessdata/ip_pool.go b/server/sessdata/ip_pool.go
index 170d58b..456a240 100644
--- a/server/sessdata/ip_pool.go
+++ b/server/sessdata/ip_pool.go
@@ -49,7 +49,7 @@ func initIpPool() {
 	IpPool.IpLongMax = utils.Ip2long(net.ParseIP(base.Cfg.Ipv4End))
 
 	// 获取IpLease数据
-	go cronIpLease()
+	//go cronIpLease()
 }
 
 func cronIpLease() {
@@ -84,65 +84,79 @@ func AcquireIp(username, macAddr string, uniqueMac bool) net.IP {
 	defer ipPoolMux.Unlock()
 
 	var (
-		err  error
-		tNow = time.Now()
-		sNow = time.Now().Add(-1 * time.Duration(base.Cfg.IpLease) * time.Second)
+		err       error
+		tNow      = time.Now()
+		leaseTime = time.Now().Add(-1 * time.Duration(base.Cfg.IpLease) * time.Second)
 	)
 
 	if uniqueMac {
 		// 判断是否已经分配过
 		mi := &dbdata.IpMap{}
 		err = dbdata.One("mac_addr", macAddr, mi)
+		// 查询报错
+		if err != nil {
+			if !dbdata.CheckErrNotFound(err) {
+				base.Error(err)
+				return nil
+			}
+		}
+
 		// 存在ip记录
-		if err == nil {
+		ipStr := mi.IpAddr
+		ip := net.ParseIP(ipStr)
+		// 跳过活跃连接
+		_, ok := ipActive[ipStr]
+		// 检测原有ip是否在新的ip池内
+		if IpPool.Ipv4IPNet.Contains(ip) && !ok &&
+			utils.Ip2long(ip) >= IpPool.IpLongMin &&
+			utils.Ip2long(ip) <= IpPool.IpLongMax {
+			mi.Username = username
+			mi.LastLogin = tNow
+			mi.UniqueMac = uniqueMac
+			// 回写db数据
+			_ = dbdata.Set(mi)
+			ipActive[ipStr] = true
+			return ip
+		}
+		_ = dbdata.Del(mi)
+
+	} else {
+		ipMaps := []dbdata.IpMap{}
+		err = dbdata.FindWhere(&ipMaps, 50, 1, "username=? and unique_mac=?", username, false)
+		// 查询报错
+		if err != nil {
+			if !dbdata.CheckErrNotFound(err) {
+				base.Error(err)
+				return nil
+			}
+		}
+
+		//遍历mac记录
+		for _, mi := range ipMaps {
 			ipStr := mi.IpAddr
 			ip := net.ParseIP(ipStr)
+
 			// 跳过活跃连接
-			_, ok := ipActive[ipStr]
-			// 检测原有ip是否在新的ip池内
-			if IpPool.Ipv4IPNet.Contains(ip) && !ok &&
+			if _, ok := ipActive[ipStr]; ok {
+				continue
+			}
+			//跳过保留ip
+			if mi.Keep {
+				continue
+			}
+
+			if IpPool.Ipv4IPNet.Contains(ip) &&
+				mi.LastLogin.Before(leaseTime) && // 说明已经超过租期,可以直接使用
 				utils.Ip2long(ip) >= IpPool.IpLongMin &&
 				utils.Ip2long(ip) <= IpPool.IpLongMax {
-				mi.Username = username
 				mi.LastLogin = tNow
+				mi.MacAddr = macAddr
 				mi.UniqueMac = uniqueMac
 				// 回写db数据
 				_ = dbdata.Set(mi)
 				ipActive[ipStr] = true
 				return ip
 			}
-			_ = dbdata.Del(mi)
-		}
-	} else {
-		ipMaps := []dbdata.IpMap{}
-		err = dbdata.FindWhere(&ipMaps, 50, 1, "username=? and unique_mac=?", username, false)
-		if err == nil {
-			//遍历mac记录
-			for _, mi := range ipMaps {
-				ipStr := mi.IpAddr
-				ip := net.ParseIP(ipStr)
-
-				// 跳过活跃连接
-				if _, ok := ipActive[ipStr]; ok {
-					continue
-				}
-				// 跳过ip租期内数据
-				if _, ok := ipLease[ipStr]; ok {
-					continue
-				}
-
-				if IpPool.Ipv4IPNet.Contains(ip) &&
-					utils.Ip2long(ip) >= IpPool.IpLongMin &&
-					utils.Ip2long(ip) <= IpPool.IpLongMax {
-					mi.LastLogin = tNow
-					mi.MacAddr = macAddr
-					mi.UniqueMac = uniqueMac
-					// 回写db数据
-					_ = dbdata.Set(mi)
-					ipActive[ipStr] = true
-					return ip
-				}
-			}
 		}
 	}
 
@@ -155,22 +169,24 @@ func AcquireIp(username, macAddr string, uniqueMac bool) net.IP {
 		if _, ok := ipActive[ipStr]; ok {
 			continue
 		}
-		// 跳过ip租期内数据
-		if _, ok := ipLease[ipStr]; ok {
-			continue
-		}
 
 		mi := &dbdata.IpMap{}
 		err = dbdata.One("ip_addr", ipStr, mi)
-		if err == nil && mi.LastLogin.Before(sNow) {
-			// 存在记录,说明已经超过租期,可以直接使用
-			mi.LastLogin = tNow
-			mi.MacAddr = macAddr
-			mi.UniqueMac = uniqueMac
-			// 回写db数据
-			_ = dbdata.Set(mi)
-			ipActive[ipStr] = true
-			return ip
+		if err == nil {
+			//跳过保留ip
+			if mi.Keep {
+				continue
+			}
+			if mi.LastLogin.Before(leaseTime) {
+				// 存在记录,说明已经超过租期,可以直接使用
+				mi.LastLogin = tNow
+				mi.MacAddr = macAddr
+				mi.UniqueMac = uniqueMac
+				// 回写db数据
+				_ = dbdata.Set(mi)
+				ipActive[ipStr] = true
+				return ip
+			}
 		}
 
 		if dbdata.CheckErrNotFound(err) {
@@ -180,9 +196,12 @@ func AcquireIp(username, macAddr string, uniqueMac bool) net.IP {
 			ipActive[ipStr] = true
 			return ip
 		}
+
 		// 查询报错
-		base.Error(err)
-		return nil
+		if err != nil {
+			base.Error(err)
+			return nil
+		}
 	}
 
 	base.Warn("no ip available, please see ip_map table row")

From 70c82b8baaeb58a992cce4c34a32fc27998e0813 Mon Sep 17 00:00:00 2001
From: bjdgyc <bjdgyc@163.com>
Date: Fri, 13 Jan 2023 11:43:12 +0800
Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dip=E5=88=86=E9=85=8D?=
 =?UTF-8?q?=E7=9A=84bug?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 server/base/app_ver.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/server/base/app_ver.go b/server/base/app_ver.go
index 2255685..e2e75b7 100644
--- a/server/base/app_ver.go
+++ b/server/base/app_ver.go
@@ -3,5 +3,5 @@ package base
 const (
 	APP_NAME = "AnyLink"
 	// app版本号
-	APP_VER = "0.9.2-beta1"
+	APP_VER = "0.9.2-beta2"
 )