diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index e865f54..a4f2e75 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -2362,6 +2362,36 @@ void FinishSend(void* user) std::thread(delay_cancel, ctx, 15).detach(); } +bool IsDateInRange(const std::string& startDate, const std::string& endDate) +{ + // 校验格式:必须是8位纯数字 + auto isValidDate = [](const std::string& date) -> bool { + if (date.length() != 8) + return false; + for (char c : date) { + if (c < '0' || c > '9') + return false; + } + int month = std::stoi(date.substr(4, 2)); + int day = std::stoi(date.substr(6, 2)); + return (month >= 1 && month <= 12 && day >= 1 && day <= 31); + }; + + if (!isValidDate(startDate) || !isValidDate(endDate)) + return false; + + if (startDate > endDate) + return false; + + SYSTEMTIME st; + GetLocalTime(&st); + + char today[9]; + sprintf_s(today, "%04d%02d%02d", st.wYear, st.wMonth, st.wDay); + + return (today >= startDate && today <= endDate); +} + BOOL CMy2015RemoteDlg::AuthorizeClient(const std::string& sn, const std::string& passcode, uint64_t hmac) { if (sn.empty() || passcode.empty() || hmac == 0) { @@ -2369,7 +2399,10 @@ BOOL CMy2015RemoteDlg::AuthorizeClient(const std::string& sn, const std::string& } static const char* superAdmin = getenv("YAMA_PWD"); std::string pwd = superAdmin ? superAdmin : m_superPass; - return VerifyMessage(pwd, (BYTE*)passcode.c_str(), passcode.length(), hmac); + BOOL b = VerifyMessage(pwd, (BYTE*)passcode.c_str(), passcode.length(), hmac); + if (!b) return FALSE; + auto list = StringToVector(passcode, '-', 2); + return IsDateInRange(list[0], list[1]); } VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject) diff --git a/server/go/Makefile b/server/go/Makefile new file mode 100644 index 0000000..565e2ac --- /dev/null +++ b/server/go/Makefile @@ -0,0 +1,95 @@ +# Makefile for SimpleRemoter Go Server +# Compatible with GnuWin32 make on Windows cmd + +# Binary name +BINARY_NAME=server + +# Build directory +BUILD_DIR=build + +# Main package path +MAIN_PACKAGE=./cmd + +# Go build flags (strip debug info for smaller binary) +LDFLAGS=-ldflags "-s -w" + +# Windows commands +MKDIR=if not exist $(BUILD_DIR) mkdir $(BUILD_DIR) +RMDIR=if exist $(BUILD_DIR) rmdir /s /q $(BUILD_DIR) + +.PHONY: all clean windows linux build help windows-386 linux-arm64 all-platforms test fmt deps + +# Default target +all: clean windows linux + +# Build for current platform +build: + @echo Building for current platform... + @$(MKDIR) + go build $(LDFLAGS) -o $(BUILD_DIR)\$(BINARY_NAME).exe $(MAIN_PACKAGE) + @echo Done + +# Build for Windows (amd64) +windows: + @echo Building for Windows amd64... + @$(MKDIR) + set GOOS=windows&& set GOARCH=amd64&& go build $(LDFLAGS) -o $(BUILD_DIR)\$(BINARY_NAME)_windows_amd64.exe $(MAIN_PACKAGE) + @echo Done: $(BUILD_DIR)\$(BINARY_NAME)_windows_amd64.exe + +# Build for Windows (386) +windows-386: + @echo Building for Windows 386... + @$(MKDIR) + set GOOS=windows&& set GOARCH=386&& go build $(LDFLAGS) -o $(BUILD_DIR)\$(BINARY_NAME)_windows_386.exe $(MAIN_PACKAGE) + @echo Done: $(BUILD_DIR)\$(BINARY_NAME)_windows_386.exe + +# Build for Linux (amd64) +linux: + @echo Building for Linux amd64... + @$(MKDIR) + set GOOS=linux&& set GOARCH=amd64&& go build $(LDFLAGS) -o $(BUILD_DIR)\$(BINARY_NAME)_linux_amd64 $(MAIN_PACKAGE) + @echo Done: $(BUILD_DIR)\$(BINARY_NAME)_linux_amd64 + +# Build for Linux (arm64) +linux-arm64: + @echo Building for Linux arm64... + @$(MKDIR) + set GOOS=linux&& set GOARCH=arm64&& go build $(LDFLAGS) -o $(BUILD_DIR)\$(BINARY_NAME)_linux_arm64 $(MAIN_PACKAGE) + @echo Done: $(BUILD_DIR)\$(BINARY_NAME)_linux_arm64 + +# Build all platforms +all-platforms: windows windows-386 linux linux-arm64 + +# Clean build artifacts +clean: + @echo Cleaning... + @$(RMDIR) + @echo Done + +# Run tests +test: + go test -v ./... + +# Format code +fmt: + go fmt ./... + +# Download dependencies +deps: + go mod download + go mod tidy + +# Show help +help: + @echo Available targets: + @echo all - Build for Windows and Linux amd64 + @echo build - Build for current platform + @echo windows - Build for Windows amd64 + @echo windows-386 - Build for Windows 386 + @echo linux - Build for Linux amd64 + @echo linux-arm64 - Build for Linux arm64 + @echo all-platforms - Build for all platforms + @echo clean - Clean build directory + @echo test - Run tests + @echo fmt - Format code + @echo deps - Download dependencies diff --git a/server/go/auth/auth.go b/server/go/auth/auth.go index 19889f1..76b3897 100644 --- a/server/go/auth/auth.go +++ b/server/go/auth/auth.go @@ -8,6 +8,7 @@ import ( "encoding/hex" "os" "strings" + "time" "golang.org/x/text/encoding/simplifiedchinese" "golang.org/x/text/transform" @@ -124,6 +125,12 @@ func (a *Authenticator) Authenticate(data []byte) *AuthResult { if superPass != "" && hmacSig != 0 { verified := VerifyMessage(superPass, []byte(passcode), hmacSig) if verified { + // HMAC verified, now check date range + // passcode format: YYYYMMDD-YYYYMMDD-xxx (first two parts are start and end dates) + if !isWithinDateRange(parts[0], parts[1]) { + result.Message = "授权已过期或尚未生效" + return result + } result.Valid = true result.Message = "此程序已获授权,请遵守授权协议,感谢合作" } @@ -136,6 +143,28 @@ func (a *Authenticator) Authenticate(data []byte) *AuthResult { return result } +// isWithinDateRange checks if current date is within the specified date range +// startDate and endDate are in YYYYMMDD format (e.g., "20251231") +func isWithinDateRange(startDate, endDate string) bool { + const dateFormat = "20060102" // Go reference time format for YYYYMMDD + + start, err := time.Parse(dateFormat, startDate) + if err != nil { + return false + } + + end, err := time.Parse(dateFormat, endDate) + if err != nil { + return false + } + + // Set end date to end of day (23:59:59) + end = end.Add(24*time.Hour - time.Second) + + now := time.Now() + return !now.Before(start) && !now.After(end) +} + // utf8ToGBK converts UTF-8 string to GBK encoded bytes func utf8ToGBK(s string) []byte { reader := transform.NewReader(bytes.NewReader([]byte(s)), simplifiedchinese.GBK.NewEncoder()) @@ -299,7 +328,11 @@ func (a *Authenticator) AuthenticateHeartbeat(data []byte) *HeartbeatAuthResult if superPass != "" { verified := VerifyMessage(superPass, []byte(passcode), pwdHmac) if verified { - result.Authorized = true + // HMAC verified, now check date range + // passcode format: YYYYMMDD-YYYYMMDD-xxx (first two parts are start and end dates) + if isWithinDateRange(parts[0], parts[1]) { + result.Authorized = true + } } }