From aa179b1fd7049ab6a7cf64367b1b3cc0f8e414d5 Mon Sep 17 00:00:00 2001 From: chchen7 Date: Sun, 28 Dec 2025 17:21:47 +0800 Subject: [PATCH 01/10] fix: validate supi format --- internal/sbi/api_ueauthentication.go | 14 ++++- internal/util/supi.go | 36 +++++++++++++ internal/util/supi_test.go | 76 ++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 internal/util/supi.go create mode 100644 internal/util/supi_test.go diff --git a/internal/sbi/api_ueauthentication.go b/internal/sbi/api_ueauthentication.go index f58795a4..ff55bafe 100644 --- a/internal/sbi/api_ueauthentication.go +++ b/internal/sbi/api_ueauthentication.go @@ -9,6 +9,7 @@ import ( "github.com/free5gc/openapi/models" "github.com/free5gc/udm/internal/logger" "github.com/free5gc/util/metrics/sbi" + "github.com/free5gc/udm/internal/util" ) func (s *Server) getUEAuthenticationRoutes() []Route { @@ -54,7 +55,18 @@ func (s *Server) HandleConfirmAuth(c *gin.Context) { } supi := c.Params.ByName("supi") - + if !util.IsValidSupi(supi) { + problemDetail := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: "Supi is invalid", + Cause: "INVALID_KEY", + } + logger.UeauLog.Errorln("Supi is invalid") + c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) + c.JSON(int(problemDetail.Status), problemDetail) + return + } logger.UeauLog.Infoln("Handle ConfirmAuthDataRequest") s.Processor().ConfirmAuthDataProcedure(c, authEvent, supi) diff --git a/internal/util/supi.go b/internal/util/supi.go new file mode 100644 index 00000000..6b006c42 --- /dev/null +++ b/internal/util/supi.go @@ -0,0 +1,36 @@ +package util + +import ( + "regexp" + "strings" +) + +// TS 29.571 & TS 23.003 SUPI format validation +var supiImsiRegex = regexp.MustCompile(`^imsi-[0-9]{5,15}$`) +// TS 29.571 & TS 23.003 NAI format validation +var supiNaiRegex = regexp.MustCompile(`^nai-.+@.+$`) +// TS 29.571 GCI/GLI format validation +var supiGciGliRegex = regexp.MustCompile(`^(gci|gli)-.+$`) + +// IsValidSupi checks if the given SUPI is valid according to 3GPP specifications +func IsValidSupi(supi string) bool { + if len(supi) == 0 { + return false + } + + if strings.HasPrefix(supi, "imsi-") { + return supiImsiRegex.MatchString(supi) + } + + if strings.HasPrefix(supi, "nai-") { + if strings.Contains(supi, "\x00") { + return false + } + return supiNaiRegex.MatchString(supi) + } + if strings.HasPrefix(supi, "gci-") || strings.HasPrefix(supi, "gli-") { + return supiGciGliRegex.MatchString(supi) + } + + return false +} \ No newline at end of file diff --git a/internal/util/supi_test.go b/internal/util/supi_test.go new file mode 100644 index 00000000..2167a011 --- /dev/null +++ b/internal/util/supi_test.go @@ -0,0 +1,76 @@ +package util + +import ( + "testing" +) + +func TestIsValidSupi(t *testing.T) { + type Args struct { + supi string + } + + type testCase struct { + name string + Args Args + Want bool + } + runTests := func(t *testing.T, tests []testCase) { + t.Helper() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsValidSupi(tt.Args.supi); got != tt.Want { + t.Errorf("IsValidSupi() = %v, Want %v (input: %q)", got, tt.Want, tt.Args.supi) + } + }) + } + } + // IMSI test + t.Run("Check_IMSI", func(t *testing.T) { + tests := []testCase{ + {"Valid IMSI (15 digits)", Args{"imsi-208930000000003"}, true}, + {"Valid IMSI (5 digits)", Args{"imsi-12345"}, true}, + {"Invalid IMSI (Too short)", Args{"imsi-1234"}, false}, + {"Invalid IMSI (Too long)", Args{"imsi-1234567890123456"}, false}, + {"Invalid IMSI (Non-digits)", Args{"imsi-20893abc000003"}, false}, + {"Invalid IMSI (Null Byte)", Args{"imsi-123\x00456"}, false}, + } + runTests(t, tests) + }) + + // NAI test + t.Run("Check_NAI", func(t *testing.T) { + tests := []testCase{ + {"Valid NAI (Standard)", Args{"nai-user@realm.com"}, true}, + {"Valid NAI (3GPP Style)", Args{"nai-type0.rid123.schid0.userid1@5gc.mnc001.mcc001.org"}, true}, + {"Invalid NAI (Missing @)", Args{"nai-userrealm.com"}, false}, + {"Invalid NAI (Missing Realm)", Args{"nai-user@"}, false}, + {"Invalid NAI (Missing User)", Args{"nai-@realm"}, false}, + {"Security: NAI with Null Byte", Args{"nai-user\x00@realm"}, false}, + } + runTests(t, tests) + }) + + // GCI/GLI test + t.Run("Check_GCI_GLI", func(t *testing.T) { + tests := []testCase{ + {"Valid GCI", Args{"gci-cable-mac-1234"}, true}, + {"Valid GLI", Args{"gli-fiber-line-5678"}, true}, + {"Invalid GCI (Empty body)", Args{"gci-"}, false}, + {"Invalid GLI (Empty body)", Args{"gli-"}, false}, + } + runTests(t, tests) + }) + + // General invalid test + t.Run("Check_General_Invalid", func(t *testing.T) { + tests := []testCase{ + {"Empty String", Args{""}, false}, + {"Unknown Prefix", Args{"unknown-12345"}, false}, + {"Just Prefix", Args{"imsi-"}, false}, + {"Security: Raw Null Bytes", Args{"\x00\x00\x00"}, false}, + {"Security: Garbage", Args{"fuzzing_payload"}, false}, + } + runTests(t, tests) + }) + +} \ No newline at end of file From ee9e07daa1276707b749283eac0757bff7c7f54f Mon Sep 17 00:00:00 2001 From: chchen7 Date: Sun, 28 Dec 2025 20:26:41 +0800 Subject: [PATCH 02/10] feat: add more information --- internal/util/supi.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/util/supi.go b/internal/util/supi.go index 6b006c42..e1789472 100644 --- a/internal/util/supi.go +++ b/internal/util/supi.go @@ -5,11 +5,14 @@ import ( "strings" ) -// TS 29.571 & TS 23.003 SUPI format validation +// TS 29.571 5.3.2 & TS 23.003 +// SUPI format validation var supiImsiRegex = regexp.MustCompile(`^imsi-[0-9]{5,15}$`) -// TS 29.571 & TS 23.003 NAI format validation +// TS 29.571 5.3.2 & TS 23.003 28.7.2 +// NAI format validation var supiNaiRegex = regexp.MustCompile(`^nai-.+@.+$`) -// TS 29.571 GCI/GLI format validation +// TS 29.571 5.3.2 & TS 23.003 28.15.2(gci) & TS 23.003 28.16.2(gli) +// GCI/GLI format validation var supiGciGliRegex = regexp.MustCompile(`^(gci|gli)-.+$`) // IsValidSupi checks if the given SUPI is valid according to 3GPP specifications From de1262c76dccc4798eb3ecd0d58018eb72a47d88 Mon Sep 17 00:00:00 2001 From: chchen7 Date: Mon, 29 Dec 2025 02:33:40 +0800 Subject: [PATCH 03/10] refactor: downgrade validation logs from Error to Warn --- internal/sbi/api_ueauthentication.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/sbi/api_ueauthentication.go b/internal/sbi/api_ueauthentication.go index ff55bafe..20113966 100644 --- a/internal/sbi/api_ueauthentication.go +++ b/internal/sbi/api_ueauthentication.go @@ -62,7 +62,7 @@ func (s *Server) HandleConfirmAuth(c *gin.Context) { Detail: "Supi is invalid", Cause: "INVALID_KEY", } - logger.UeauLog.Errorln("Supi is invalid") + logger.UeauLog.Warnln("Supi is invalid") c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) c.JSON(int(problemDetail.Status), problemDetail) return From 2854e1fdc45b64774471e8f14a22396fec2f01c5 Mon Sep 17 00:00:00 2001 From: chchen7 Date: Mon, 29 Dec 2025 03:14:56 +0800 Subject: [PATCH 04/10] feat: validate suci format --- internal/sbi/api_ueauthentication.go | 13 ++++ internal/util/suci.go | 45 +++++++++++ internal/util/suci_test.go | 109 +++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 internal/util/suci.go create mode 100644 internal/util/suci_test.go diff --git a/internal/sbi/api_ueauthentication.go b/internal/sbi/api_ueauthentication.go index 20113966..d9b9580b 100644 --- a/internal/sbi/api_ueauthentication.go +++ b/internal/sbi/api_ueauthentication.go @@ -107,6 +107,19 @@ func (s *Server) HandleGenerateAuthData(c *gin.Context) { logger.UeauLog.Infoln("Handle GenerateAuthDataRequest") supiOrSuci := c.Param("supiOrSuci") + if !util.IsValidSupi(supiOrSuci) && !util.IsValidSuci(supiOrSuci) { + problemDetail := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: "Supi or Suci is invalid", + Cause: "INVALID_KEY", + } + logger.UeauLog.Warnln("Supi or Suci is invalid") + c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) + c.JSON(int(problemDetail.Status), problemDetail) + return + } + logger.UeauLog.Infoln("Handle ConfirmAuthDataRequest") s.Processor().GenerateAuthDataProcedure(c, authInfoReq, supiOrSuci) } diff --git a/internal/util/suci.go b/internal/util/suci.go new file mode 100644 index 00000000..2b47887e --- /dev/null +++ b/internal/util/suci.go @@ -0,0 +1,45 @@ +package util + +import ( + "regexp" + "strings" +) + +// TS 29.571 5.3.2 & TS 23.003 Clause 6.3 +// Regex for IMSI-based SUCI (Type 0) +// Format: suci-0------ +// Example: suci-0-208-93-0-0-0-1234567890 (Null Scheme) +var suciImsiRegex = regexp.MustCompile(`^suci-0-[0-9]{3}-[0-9]{2,3}-[0-9a-fA-F]{1,4}-[0-9a-fA-F]{1,2}-[0-9a-fA-F]{1,2}-.+$`) + +// Regex for NAI-based SUCI (Type 1) +// Format: suci-1----- +var suciNaiRegex = regexp.MustCompile(`^suci-1-.+-[0-9a-fA-F]{1,4}-[0-9a-fA-F]{1,2}-[0-9a-fA-F]{1,2}-.+$`) + +// IsValidSuci checks if the given string is a valid SUCI +func IsValidSuci(suci string) bool { + if len(suci) == 0 { + return false + } + + // must start with "suci-" + if !strings.HasPrefix(suci, "suci-") { + return false + } + + // prevent null byte injection + if strings.Contains(suci, "\x00") { + return false + } + + // validate IMSI-based SUCI (Type 0) + if strings.HasPrefix(suci, "suci-0-") { + return suciImsiRegex.MatchString(suci) + } + + // validate NAI-based SUCI (Type 1) + if strings.HasPrefix(suci, "suci-1-") { + return suciNaiRegex.MatchString(suci) + } + + return false +} \ No newline at end of file diff --git a/internal/util/suci_test.go b/internal/util/suci_test.go new file mode 100644 index 00000000..5768dae5 --- /dev/null +++ b/internal/util/suci_test.go @@ -0,0 +1,109 @@ +package util + +import ( + "testing" +) + +func TestIsValidSuci(t *testing.T) { + type args struct { + suci string + } + type testCase struct { + name string + args args + want bool + } + + runTests := func(t *testing.T, tests []testCase) { + t.Helper() + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := IsValidSuci(tt.args.suci); got != tt.want { + t.Errorf("IsValidSuci() = %v, want %v (input: %q)", got, tt.want, tt.args.suci) + } + }) + } + } + + // ========================================== + // 1. IMSI-based SUCI (Type 0) + // Format: suci-0------ + // Source: TS 23.003 Clause 6.3 + // ========================================== + t.Run("Check_SUCI_Type0_IMSI", func(t *testing.T) { + tests := []testCase{ + // Happy Paths + { + "Valid Type 0 (Null Scheme)", + args{"suci-0-208-93-0-0-0-208930000000003"}, + true, + }, + { + "Valid Type 0 (Profile A, Long Routing)", + args{"suci-0-466-92-f001-1-1-ECCOutputHex..."}, + true, + }, + { + "Valid Type 0 (3-digit MNC)", + args{"suci-0-466-092-0-0-0-123456"}, + true, + }, + + // Format Errors + { + "Invalid Type 0 (Bad MCC)", + args{"suci-0-20A-93-0-0-0-123"}, // MCC must be digits + false, + }, + { + "Invalid Type 0 (Bad Routing Ind)", + args{"suci-0-208-93-GGGG-0-0-123"}, // Routing must be Hex + false, + }, + { + "Invalid Type 0 (Missing Parts)", + args{"suci-0-208-93-0-0-123"}, // Missing KeyId + false, + }, + } + runTests(t, tests) + }) + + // ========================================== + // 2. NAI-based SUCI (Type 1) + // Format: suci-1----- + // ========================================== + t.Run("Check_SUCI_Type1_NAI", func(t *testing.T) { + tests := []testCase{ + { + "Valid Type 1 (Standard)", + args{"suci-1-factory.local-0-0-0-user1"}, + true, + }, + { + "Invalid Type 1 (Bad Hex)", + args{"suci-1-domain-Z-0-0-output"}, // Routing must be Hex + false, + }, + } + runTests(t, tests) + }) + + // ========================================== + // 3. Security & Edge Cases + // ========================================== + t.Run("Check_Security_EdgeCases", func(t *testing.T) { + tests := []testCase{ + {"Empty String", args{""}, false}, + {"Wrong Prefix", args{"suciX-0-208-93-0-0-0-1"}, false}, + {"Unknown Type (Type 9)", args{"suci-9-208-93-0-0-0-1"}, false}, // Currently only 0 and 1 supported + + // [Security] Null Byte Injection + {"Null Byte Injection", args{"suci-0-208-93\x00-0-0-0-1"}, false}, + + // Fuzzing garbage + {"Garbage String", args{"suci-0-garbage-data"}, false}, + } + runTests(t, tests) + }) +} \ No newline at end of file From 0ff6b8b23b15fb4861f628cc4006f651a4a97d0f Mon Sep 17 00:00:00 2001 From: chchen7 Date: Mon, 29 Dec 2025 05:31:58 +0800 Subject: [PATCH 05/10] fix: ueau mandatory IE check --- internal/sbi/api_ueauthentication.go | 79 ++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/internal/sbi/api_ueauthentication.go b/internal/sbi/api_ueauthentication.go index d9b9580b..86fa8771 100644 --- a/internal/sbi/api_ueauthentication.go +++ b/internal/sbi/api_ueauthentication.go @@ -8,8 +8,8 @@ import ( "github.com/free5gc/openapi" "github.com/free5gc/openapi/models" "github.com/free5gc/udm/internal/logger" - "github.com/free5gc/util/metrics/sbi" "github.com/free5gc/udm/internal/util" + "github.com/free5gc/util/metrics/sbi" ) func (s *Server) getUEAuthenticationRoutes() []Route { @@ -26,6 +26,22 @@ func (s *Server) getUEAuthenticationRoutes() []Route { // ConfirmAuth - Create a new confirmation event func (s *Server) HandleConfirmAuth(c *gin.Context) { var authEvent models.AuthEvent + // TS 29.503 6.3.6.2.3 + // Validate SUPI format + supi := c.Params.ByName("supi") + if !util.IsValidSupi(supi) { + problemDetail := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: "Supi is invalid", + Cause: "INVALID_KEY", + } + logger.UeauLog.Warnln("Supi is invalid") + c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) + c.JSON(int(problemDetail.Status), problemDetail) + return + } + requestBody, err := c.GetRawData() if err != nil { problemDetail := models.ProblemDetails{ @@ -54,19 +70,31 @@ func (s *Server) HandleConfirmAuth(c *gin.Context) { return } - supi := c.Params.ByName("supi") - if !util.IsValidSupi(supi) { + // TS 29.503 6.3.6.2.7 requirements check + missingIE := "" + if authEvent.NfInstanceId == "" { + missingIE = "nfInstanceId" + } else if authEvent.TimeStamp == nil { + missingIE = "timestamp" + } else if authEvent.AuthType == "" { + missingIE = "authtype" + } else if authEvent.ServingNetworkName == "" { + missingIE = "servingNetworkName" + } + + if missingIE != "" { problemDetail := models.ProblemDetails{ - Title: "Malformed request syntax", + Title: "Missing or invalid parameter", Status: http.StatusBadRequest, - Detail: "Supi is invalid", - Cause: "INVALID_KEY", + Detail: "Mandatory IE " + missingIE + " is missing or invalid", + Cause: "MISSING_OR_INVALID_PARAMETER", } - logger.UeauLog.Warnln("Supi is invalid") + logger.UeauLog.Warnln("Mandatory IE " + missingIE + "is missing or invalid") c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) c.JSON(int(problemDetail.Status), problemDetail) return } + logger.UeauLog.Infoln("Handle ConfirmAuthDataRequest") s.Processor().ConfirmAuthDataProcedure(c, authEvent, supi) @@ -75,6 +103,21 @@ func (s *Server) HandleConfirmAuth(c *gin.Context) { // GenerateAuthData - Generate authentication data for the UE func (s *Server) HandleGenerateAuthData(c *gin.Context) { var authInfoReq models.AuthenticationInfoRequest + // TS 29.503 6.3.3.2.2 + // Validate SUPI or SUCI format + supiOrSuci := c.Param("supiOrSuci") + if !util.IsValidSupi(supiOrSuci) && !util.IsValidSuci(supiOrSuci) { + problemDetail := models.ProblemDetails{ + Title: "Malformed request syntax", + Status: http.StatusBadRequest, + Detail: "Supi or Suci is invalid", + Cause: "INVALID_KEY", + } + logger.UeauLog.Warnln("Supi or Suci is invalid") + c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) + c.JSON(int(problemDetail.Status), problemDetail) + return + } requestBody, err := c.GetRawData() if err != nil { @@ -104,22 +147,28 @@ func (s *Server) HandleGenerateAuthData(c *gin.Context) { return } - logger.UeauLog.Infoln("Handle GenerateAuthDataRequest") + // TS 29.503 6.3.6.2.2 requirements check + missingIE := "" + if authInfoReq.ServingNetworkName == "" { + missingIE = "servingNetworkName" + } else if authInfoReq.AusfInstanceId == "" { + missingIE = "ausfInstanceId" + } - supiOrSuci := c.Param("supiOrSuci") - if !util.IsValidSupi(supiOrSuci) && !util.IsValidSuci(supiOrSuci) { + if missingIE != "" { problemDetail := models.ProblemDetails{ - Title: "Malformed request syntax", + Title: "Missing or invalid parameter", Status: http.StatusBadRequest, - Detail: "Supi or Suci is invalid", - Cause: "INVALID_KEY", + Detail: "Mandatory IE " + missingIE + " is missing or invalid", + Cause: "MISSING_OR_INVALID_PARAMETER", } - logger.UeauLog.Warnln("Supi or Suci is invalid") + logger.UeauLog.Warnln("Mandatory IE " + missingIE + "is missing or invalid") c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) c.JSON(int(problemDetail.Status), problemDetail) return } - logger.UeauLog.Infoln("Handle ConfirmAuthDataRequest") + + logger.UeauLog.Infoln("Handle GenerateAuthDataRequest") s.Processor().GenerateAuthDataProcedure(c, authInfoReq, supiOrSuci) } From e7d84f6b6f26eb27d6ddbc683f577a94b8cacad2 Mon Sep 17 00:00:00 2001 From: chchen7 Date: Mon, 29 Dec 2025 05:32:27 +0800 Subject: [PATCH 06/10] chore: apply golangci-lint fixes --- internal/util/suci.go | 5 +++-- internal/util/suci_test.go | 8 ++++---- internal/util/supi.go | 10 ++++++---- internal/util/supi_test.go | 3 +-- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/internal/util/suci.go b/internal/util/suci.go index 2b47887e..93cecfea 100644 --- a/internal/util/suci.go +++ b/internal/util/suci.go @@ -9,7 +9,8 @@ import ( // Regex for IMSI-based SUCI (Type 0) // Format: suci-0------ // Example: suci-0-208-93-0-0-0-1234567890 (Null Scheme) -var suciImsiRegex = regexp.MustCompile(`^suci-0-[0-9]{3}-[0-9]{2,3}-[0-9a-fA-F]{1,4}-[0-9a-fA-F]{1,2}-[0-9a-fA-F]{1,2}-.+$`) +var suciImsiRegex = regexp.MustCompile(`^suci-0-[0-9]{3}-[0-9]{2,3}-[0-9a-fA-F]{1,4}-` + + `[0-9a-fA-F]{1,2}-[0-9a-fA-F]{1,2}-.+$`) // Regex for NAI-based SUCI (Type 1) // Format: suci-1----- @@ -42,4 +43,4 @@ func IsValidSuci(suci string) bool { } return false -} \ No newline at end of file +} diff --git a/internal/util/suci_test.go b/internal/util/suci_test.go index 5768dae5..5fd508cf 100644 --- a/internal/util/suci_test.go +++ b/internal/util/suci_test.go @@ -48,7 +48,7 @@ func TestIsValidSuci(t *testing.T) { args{"suci-0-466-092-0-0-0-123456"}, true, }, - + // Format Errors { "Invalid Type 0 (Bad MCC)", @@ -97,13 +97,13 @@ func TestIsValidSuci(t *testing.T) { {"Empty String", args{""}, false}, {"Wrong Prefix", args{"suciX-0-208-93-0-0-0-1"}, false}, {"Unknown Type (Type 9)", args{"suci-9-208-93-0-0-0-1"}, false}, // Currently only 0 and 1 supported - + // [Security] Null Byte Injection {"Null Byte Injection", args{"suci-0-208-93\x00-0-0-0-1"}, false}, - + // Fuzzing garbage {"Garbage String", args{"suci-0-garbage-data"}, false}, } runTests(t, tests) }) -} \ No newline at end of file +} diff --git a/internal/util/supi.go b/internal/util/supi.go index e1789472..cfaf0789 100644 --- a/internal/util/supi.go +++ b/internal/util/supi.go @@ -8,9 +8,11 @@ import ( // TS 29.571 5.3.2 & TS 23.003 // SUPI format validation var supiImsiRegex = regexp.MustCompile(`^imsi-[0-9]{5,15}$`) -// TS 29.571 5.3.2 & TS 23.003 28.7.2 + +// TS 29.571 5.3.2 & TS 23.003 28.7.2 // NAI format validation var supiNaiRegex = regexp.MustCompile(`^nai-.+@.+$`) + // TS 29.571 5.3.2 & TS 23.003 28.15.2(gci) & TS 23.003 28.16.2(gli) // GCI/GLI format validation var supiGciGliRegex = regexp.MustCompile(`^(gci|gli)-.+$`) @@ -27,8 +29,8 @@ func IsValidSupi(supi string) bool { if strings.HasPrefix(supi, "nai-") { if strings.Contains(supi, "\x00") { - return false - } + return false + } return supiNaiRegex.MatchString(supi) } if strings.HasPrefix(supi, "gci-") || strings.HasPrefix(supi, "gli-") { @@ -36,4 +38,4 @@ func IsValidSupi(supi string) bool { } return false -} \ No newline at end of file +} diff --git a/internal/util/supi_test.go b/internal/util/supi_test.go index 2167a011..fdb76278 100644 --- a/internal/util/supi_test.go +++ b/internal/util/supi_test.go @@ -72,5 +72,4 @@ func TestIsValidSupi(t *testing.T) { } runTests(t, tests) }) - -} \ No newline at end of file +} From 4704fca24bd4372a01f86bea831439a3350b4f7a Mon Sep 17 00:00:00 2001 From: chchen7 Date: Mon, 5 Jan 2026 02:47:00 +0800 Subject: [PATCH 07/10] fix: update cause --- internal/sbi/api_ueauthentication.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/sbi/api_ueauthentication.go b/internal/sbi/api_ueauthentication.go index 86fa8771..c40a3dd0 100644 --- a/internal/sbi/api_ueauthentication.go +++ b/internal/sbi/api_ueauthentication.go @@ -34,7 +34,7 @@ func (s *Server) HandleConfirmAuth(c *gin.Context) { Title: "Malformed request syntax", Status: http.StatusBadRequest, Detail: "Supi is invalid", - Cause: "INVALID_KEY", + Cause: "MANDATORY_IE_INCORRECT", } logger.UeauLog.Warnln("Supi is invalid") c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) @@ -87,7 +87,7 @@ func (s *Server) HandleConfirmAuth(c *gin.Context) { Title: "Missing or invalid parameter", Status: http.StatusBadRequest, Detail: "Mandatory IE " + missingIE + " is missing or invalid", - Cause: "MISSING_OR_INVALID_PARAMETER", + Cause: "MANDATORY_IE_MISSING", } logger.UeauLog.Warnln("Mandatory IE " + missingIE + "is missing or invalid") c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) @@ -111,7 +111,7 @@ func (s *Server) HandleGenerateAuthData(c *gin.Context) { Title: "Malformed request syntax", Status: http.StatusBadRequest, Detail: "Supi or Suci is invalid", - Cause: "INVALID_KEY", + Cause: "MANDATORY_IE_INCORRECT", } logger.UeauLog.Warnln("Supi or Suci is invalid") c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) @@ -160,7 +160,7 @@ func (s *Server) HandleGenerateAuthData(c *gin.Context) { Title: "Missing or invalid parameter", Status: http.StatusBadRequest, Detail: "Mandatory IE " + missingIE + " is missing or invalid", - Cause: "MISSING_OR_INVALID_PARAMETER", + Cause: "MANDATORY_IE_MISSING", } logger.UeauLog.Warnln("Mandatory IE " + missingIE + "is missing or invalid") c.Set(sbi.IN_PB_DETAILS_CTX_STR, http.StatusText(int(problemDetail.Status))) From de0c2bc701d42caf8f81ea6d53c2155f2197e4aa Mon Sep 17 00:00:00 2001 From: chchen7 Date: Wed, 7 Jan 2026 23:29:20 +0800 Subject: [PATCH 08/10] refactor: replace local util validator with github.com/free5gc/util/validator --- go.mod | 12 +-- go.sum | 12 +++ internal/sbi/api_ueauthentication.go | 6 +- internal/util/suci.go | 46 ----------- internal/util/suci_test.go | 109 --------------------------- internal/util/supi.go | 41 ---------- internal/util/supi_test.go | 75 ------------------ 7 files changed, 21 insertions(+), 280 deletions(-) delete mode 100644 internal/util/suci.go delete mode 100644 internal/util/suci_test.go delete mode 100644 internal/util/supi.go delete mode 100644 internal/util/supi_test.go diff --git a/go.mod b/go.mod index 8b919a9a..ea762841 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/free5gc/udm -go 1.24.0 +go 1.25.5 require ( github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d - github.com/free5gc/openapi v1.2.2 - github.com/free5gc/util v1.2.0 + github.com/free5gc/openapi v1.2.3 + github.com/free5gc/util v1.3.2-0.20260107090449-c09baaf75b11 github.com/gin-gonic/gin v1.10.0 github.com/google/uuid v1.3.0 github.com/h2non/gock v1.2.0 @@ -28,9 +28,9 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect - github.com/free5gc/aper v1.0.6-0.20250102035630-3ddc831eed6a // indirect - github.com/free5gc/nas v1.2.1 // indirect - github.com/free5gc/ngap v1.1.1 // indirect + github.com/free5gc/aper v1.1.0 // indirect + github.com/free5gc/nas v1.2.2 // indirect + github.com/free5gc/ngap v1.1.2 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-logr/logr v1.4.1 // indirect diff --git a/go.sum b/go.sum index 3a5acda3..5a78f507 100644 --- a/go.sum +++ b/go.sum @@ -21,14 +21,26 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/free5gc/aper v1.0.6-0.20250102035630-3ddc831eed6a h1:PRapMdjqo96T7y8PHShUlirRDI0EaJNVrmdfQaHxOKY= github.com/free5gc/aper v1.0.6-0.20250102035630-3ddc831eed6a/go.mod h1:L4d0BJpHVOgiOC49aCz44mF0Vja3l+bcVSAs7i3CZ8s= +github.com/free5gc/aper v1.1.0 h1:X36hts0PYQuN3d+VXpYsUZaibrokP8nbBVIQBVY2bNI= +github.com/free5gc/aper v1.1.0/go.mod h1:v7xVwA5XaD9lBnZDOzvDF0Nw6GOcn32IrL7tM6zHPyM= github.com/free5gc/nas v1.2.1 h1:jIXffRFXCuAEQs5j5NHlS+ugQBbReNe6q3NPxfrTZVo= github.com/free5gc/nas v1.2.1/go.mod h1:K14TWrOk7UXdLmZkP5uGCSf/0EYxrUOzpi/hlfJm40w= +github.com/free5gc/nas v1.2.2 h1:r2+9CHY1TRfTM/X2Pc+vBizeqweUJRuLo1DGub1vk5s= +github.com/free5gc/nas v1.2.2/go.mod h1:y3f4YCGsvQOqQx8h+4MH22k0C8XaopK2ZP/F7qAW98k= github.com/free5gc/ngap v1.1.1 h1:MBpB4bSYOE79T0XXBLY+lNKz77R5nCboLgiBKnBx4SY= github.com/free5gc/ngap v1.1.1/go.mod h1:L0FjR4QPpLrPyur9kiep8RSxeahK7HIBm4x9dybt1bA= +github.com/free5gc/ngap v1.1.2 h1:AA+s9+eaE8fSTnmBbh1xiD3VPaszonCd7AQJGKX5PHM= +github.com/free5gc/ngap v1.1.2/go.mod h1:4HYtB+msoTBc3cEPlSr4ZUUHn3BFZhdPuVASERMzVeI= github.com/free5gc/openapi v1.2.2 h1:SoWkuI/QOWA22UgNuqtkeoKeLEjThziJYGQFh/1gxSQ= github.com/free5gc/openapi v1.2.2/go.mod h1:5HbgGqlhaTBwcOrXQLCOmpbQoX/ogKSg6+TAsR1VxUM= +github.com/free5gc/openapi v1.2.3 h1:w4TmYBR8TUE4ZgKo7eiMZbyZPURSBFlMWiFeX+OsiA8= +github.com/free5gc/openapi v1.2.3/go.mod h1:fLvaBtUZrvrzkKrmn5Aza+JNbpWnp3kxKixu6kLSD3k= github.com/free5gc/util v1.2.0 h1:qA6EwiM7uAaE2SUSZDkUaMEa1DVEBoMN+wEWhRj8cYs= github.com/free5gc/util v1.2.0/go.mod h1:eFZg7JCMlG1G5eCBbw+Gfs0SOBSIZv1OeuB1Sh0H+zE= +github.com/free5gc/util v1.3.1 h1:5j5Exvp42Ow3zNP2aaAp68MSne6BcaCF4/cekXYUS6w= +github.com/free5gc/util v1.3.1/go.mod h1:qsv/ez8YhI+pO8bjNiZWXc2xmRE3XuEIa0EDTCPkSy0= +github.com/free5gc/util v1.3.2-0.20260107090449-c09baaf75b11 h1:/UZetXmPa5T/TKKxqU3Osw9x3+nIuACTXJxOU+gYGTU= +github.com/free5gc/util v1.3.2-0.20260107090449-c09baaf75b11/go.mod h1:qsv/ez8YhI+pO8bjNiZWXc2xmRE3XuEIa0EDTCPkSy0= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= diff --git a/internal/sbi/api_ueauthentication.go b/internal/sbi/api_ueauthentication.go index c40a3dd0..ccb27283 100644 --- a/internal/sbi/api_ueauthentication.go +++ b/internal/sbi/api_ueauthentication.go @@ -8,7 +8,7 @@ import ( "github.com/free5gc/openapi" "github.com/free5gc/openapi/models" "github.com/free5gc/udm/internal/logger" - "github.com/free5gc/udm/internal/util" + "github.com/free5gc/util/validator" "github.com/free5gc/util/metrics/sbi" ) @@ -29,7 +29,7 @@ func (s *Server) HandleConfirmAuth(c *gin.Context) { // TS 29.503 6.3.6.2.3 // Validate SUPI format supi := c.Params.ByName("supi") - if !util.IsValidSupi(supi) { + if !validator.IsValidSupi(supi) { problemDetail := models.ProblemDetails{ Title: "Malformed request syntax", Status: http.StatusBadRequest, @@ -106,7 +106,7 @@ func (s *Server) HandleGenerateAuthData(c *gin.Context) { // TS 29.503 6.3.3.2.2 // Validate SUPI or SUCI format supiOrSuci := c.Param("supiOrSuci") - if !util.IsValidSupi(supiOrSuci) && !util.IsValidSuci(supiOrSuci) { + if !validator.IsValidSupi(supiOrSuci) && !validator.IsValidSuci(supiOrSuci) { problemDetail := models.ProblemDetails{ Title: "Malformed request syntax", Status: http.StatusBadRequest, diff --git a/internal/util/suci.go b/internal/util/suci.go deleted file mode 100644 index 93cecfea..00000000 --- a/internal/util/suci.go +++ /dev/null @@ -1,46 +0,0 @@ -package util - -import ( - "regexp" - "strings" -) - -// TS 29.571 5.3.2 & TS 23.003 Clause 6.3 -// Regex for IMSI-based SUCI (Type 0) -// Format: suci-0------ -// Example: suci-0-208-93-0-0-0-1234567890 (Null Scheme) -var suciImsiRegex = regexp.MustCompile(`^suci-0-[0-9]{3}-[0-9]{2,3}-[0-9a-fA-F]{1,4}-` + - `[0-9a-fA-F]{1,2}-[0-9a-fA-F]{1,2}-.+$`) - -// Regex for NAI-based SUCI (Type 1) -// Format: suci-1----- -var suciNaiRegex = regexp.MustCompile(`^suci-1-.+-[0-9a-fA-F]{1,4}-[0-9a-fA-F]{1,2}-[0-9a-fA-F]{1,2}-.+$`) - -// IsValidSuci checks if the given string is a valid SUCI -func IsValidSuci(suci string) bool { - if len(suci) == 0 { - return false - } - - // must start with "suci-" - if !strings.HasPrefix(suci, "suci-") { - return false - } - - // prevent null byte injection - if strings.Contains(suci, "\x00") { - return false - } - - // validate IMSI-based SUCI (Type 0) - if strings.HasPrefix(suci, "suci-0-") { - return suciImsiRegex.MatchString(suci) - } - - // validate NAI-based SUCI (Type 1) - if strings.HasPrefix(suci, "suci-1-") { - return suciNaiRegex.MatchString(suci) - } - - return false -} diff --git a/internal/util/suci_test.go b/internal/util/suci_test.go deleted file mode 100644 index 5fd508cf..00000000 --- a/internal/util/suci_test.go +++ /dev/null @@ -1,109 +0,0 @@ -package util - -import ( - "testing" -) - -func TestIsValidSuci(t *testing.T) { - type args struct { - suci string - } - type testCase struct { - name string - args args - want bool - } - - runTests := func(t *testing.T, tests []testCase) { - t.Helper() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := IsValidSuci(tt.args.suci); got != tt.want { - t.Errorf("IsValidSuci() = %v, want %v (input: %q)", got, tt.want, tt.args.suci) - } - }) - } - } - - // ========================================== - // 1. IMSI-based SUCI (Type 0) - // Format: suci-0------ - // Source: TS 23.003 Clause 6.3 - // ========================================== - t.Run("Check_SUCI_Type0_IMSI", func(t *testing.T) { - tests := []testCase{ - // Happy Paths - { - "Valid Type 0 (Null Scheme)", - args{"suci-0-208-93-0-0-0-208930000000003"}, - true, - }, - { - "Valid Type 0 (Profile A, Long Routing)", - args{"suci-0-466-92-f001-1-1-ECCOutputHex..."}, - true, - }, - { - "Valid Type 0 (3-digit MNC)", - args{"suci-0-466-092-0-0-0-123456"}, - true, - }, - - // Format Errors - { - "Invalid Type 0 (Bad MCC)", - args{"suci-0-20A-93-0-0-0-123"}, // MCC must be digits - false, - }, - { - "Invalid Type 0 (Bad Routing Ind)", - args{"suci-0-208-93-GGGG-0-0-123"}, // Routing must be Hex - false, - }, - { - "Invalid Type 0 (Missing Parts)", - args{"suci-0-208-93-0-0-123"}, // Missing KeyId - false, - }, - } - runTests(t, tests) - }) - - // ========================================== - // 2. NAI-based SUCI (Type 1) - // Format: suci-1----- - // ========================================== - t.Run("Check_SUCI_Type1_NAI", func(t *testing.T) { - tests := []testCase{ - { - "Valid Type 1 (Standard)", - args{"suci-1-factory.local-0-0-0-user1"}, - true, - }, - { - "Invalid Type 1 (Bad Hex)", - args{"suci-1-domain-Z-0-0-output"}, // Routing must be Hex - false, - }, - } - runTests(t, tests) - }) - - // ========================================== - // 3. Security & Edge Cases - // ========================================== - t.Run("Check_Security_EdgeCases", func(t *testing.T) { - tests := []testCase{ - {"Empty String", args{""}, false}, - {"Wrong Prefix", args{"suciX-0-208-93-0-0-0-1"}, false}, - {"Unknown Type (Type 9)", args{"suci-9-208-93-0-0-0-1"}, false}, // Currently only 0 and 1 supported - - // [Security] Null Byte Injection - {"Null Byte Injection", args{"suci-0-208-93\x00-0-0-0-1"}, false}, - - // Fuzzing garbage - {"Garbage String", args{"suci-0-garbage-data"}, false}, - } - runTests(t, tests) - }) -} diff --git a/internal/util/supi.go b/internal/util/supi.go deleted file mode 100644 index cfaf0789..00000000 --- a/internal/util/supi.go +++ /dev/null @@ -1,41 +0,0 @@ -package util - -import ( - "regexp" - "strings" -) - -// TS 29.571 5.3.2 & TS 23.003 -// SUPI format validation -var supiImsiRegex = regexp.MustCompile(`^imsi-[0-9]{5,15}$`) - -// TS 29.571 5.3.2 & TS 23.003 28.7.2 -// NAI format validation -var supiNaiRegex = regexp.MustCompile(`^nai-.+@.+$`) - -// TS 29.571 5.3.2 & TS 23.003 28.15.2(gci) & TS 23.003 28.16.2(gli) -// GCI/GLI format validation -var supiGciGliRegex = regexp.MustCompile(`^(gci|gli)-.+$`) - -// IsValidSupi checks if the given SUPI is valid according to 3GPP specifications -func IsValidSupi(supi string) bool { - if len(supi) == 0 { - return false - } - - if strings.HasPrefix(supi, "imsi-") { - return supiImsiRegex.MatchString(supi) - } - - if strings.HasPrefix(supi, "nai-") { - if strings.Contains(supi, "\x00") { - return false - } - return supiNaiRegex.MatchString(supi) - } - if strings.HasPrefix(supi, "gci-") || strings.HasPrefix(supi, "gli-") { - return supiGciGliRegex.MatchString(supi) - } - - return false -} diff --git a/internal/util/supi_test.go b/internal/util/supi_test.go deleted file mode 100644 index fdb76278..00000000 --- a/internal/util/supi_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package util - -import ( - "testing" -) - -func TestIsValidSupi(t *testing.T) { - type Args struct { - supi string - } - - type testCase struct { - name string - Args Args - Want bool - } - runTests := func(t *testing.T, tests []testCase) { - t.Helper() - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := IsValidSupi(tt.Args.supi); got != tt.Want { - t.Errorf("IsValidSupi() = %v, Want %v (input: %q)", got, tt.Want, tt.Args.supi) - } - }) - } - } - // IMSI test - t.Run("Check_IMSI", func(t *testing.T) { - tests := []testCase{ - {"Valid IMSI (15 digits)", Args{"imsi-208930000000003"}, true}, - {"Valid IMSI (5 digits)", Args{"imsi-12345"}, true}, - {"Invalid IMSI (Too short)", Args{"imsi-1234"}, false}, - {"Invalid IMSI (Too long)", Args{"imsi-1234567890123456"}, false}, - {"Invalid IMSI (Non-digits)", Args{"imsi-20893abc000003"}, false}, - {"Invalid IMSI (Null Byte)", Args{"imsi-123\x00456"}, false}, - } - runTests(t, tests) - }) - - // NAI test - t.Run("Check_NAI", func(t *testing.T) { - tests := []testCase{ - {"Valid NAI (Standard)", Args{"nai-user@realm.com"}, true}, - {"Valid NAI (3GPP Style)", Args{"nai-type0.rid123.schid0.userid1@5gc.mnc001.mcc001.org"}, true}, - {"Invalid NAI (Missing @)", Args{"nai-userrealm.com"}, false}, - {"Invalid NAI (Missing Realm)", Args{"nai-user@"}, false}, - {"Invalid NAI (Missing User)", Args{"nai-@realm"}, false}, - {"Security: NAI with Null Byte", Args{"nai-user\x00@realm"}, false}, - } - runTests(t, tests) - }) - - // GCI/GLI test - t.Run("Check_GCI_GLI", func(t *testing.T) { - tests := []testCase{ - {"Valid GCI", Args{"gci-cable-mac-1234"}, true}, - {"Valid GLI", Args{"gli-fiber-line-5678"}, true}, - {"Invalid GCI (Empty body)", Args{"gci-"}, false}, - {"Invalid GLI (Empty body)", Args{"gli-"}, false}, - } - runTests(t, tests) - }) - - // General invalid test - t.Run("Check_General_Invalid", func(t *testing.T) { - tests := []testCase{ - {"Empty String", Args{""}, false}, - {"Unknown Prefix", Args{"unknown-12345"}, false}, - {"Just Prefix", Args{"imsi-"}, false}, - {"Security: Raw Null Bytes", Args{"\x00\x00\x00"}, false}, - {"Security: Garbage", Args{"fuzzing_payload"}, false}, - } - runTests(t, tests) - }) -} From be24b77c97e5965a3e3287cf6bc789c0c5c4fcb2 Mon Sep 17 00:00:00 2001 From: chchen7 Date: Sat, 10 Jan 2026 17:16:08 +0800 Subject: [PATCH 09/10] chore: update go.sum --- go.sum | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/go.sum b/go.sum index 5a78f507..a602c1b0 100644 --- a/go.sum +++ b/go.sum @@ -19,26 +19,14 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/free5gc/aper v1.0.6-0.20250102035630-3ddc831eed6a h1:PRapMdjqo96T7y8PHShUlirRDI0EaJNVrmdfQaHxOKY= -github.com/free5gc/aper v1.0.6-0.20250102035630-3ddc831eed6a/go.mod h1:L4d0BJpHVOgiOC49aCz44mF0Vja3l+bcVSAs7i3CZ8s= github.com/free5gc/aper v1.1.0 h1:X36hts0PYQuN3d+VXpYsUZaibrokP8nbBVIQBVY2bNI= github.com/free5gc/aper v1.1.0/go.mod h1:v7xVwA5XaD9lBnZDOzvDF0Nw6GOcn32IrL7tM6zHPyM= -github.com/free5gc/nas v1.2.1 h1:jIXffRFXCuAEQs5j5NHlS+ugQBbReNe6q3NPxfrTZVo= -github.com/free5gc/nas v1.2.1/go.mod h1:K14TWrOk7UXdLmZkP5uGCSf/0EYxrUOzpi/hlfJm40w= github.com/free5gc/nas v1.2.2 h1:r2+9CHY1TRfTM/X2Pc+vBizeqweUJRuLo1DGub1vk5s= github.com/free5gc/nas v1.2.2/go.mod h1:y3f4YCGsvQOqQx8h+4MH22k0C8XaopK2ZP/F7qAW98k= -github.com/free5gc/ngap v1.1.1 h1:MBpB4bSYOE79T0XXBLY+lNKz77R5nCboLgiBKnBx4SY= -github.com/free5gc/ngap v1.1.1/go.mod h1:L0FjR4QPpLrPyur9kiep8RSxeahK7HIBm4x9dybt1bA= github.com/free5gc/ngap v1.1.2 h1:AA+s9+eaE8fSTnmBbh1xiD3VPaszonCd7AQJGKX5PHM= github.com/free5gc/ngap v1.1.2/go.mod h1:4HYtB+msoTBc3cEPlSr4ZUUHn3BFZhdPuVASERMzVeI= -github.com/free5gc/openapi v1.2.2 h1:SoWkuI/QOWA22UgNuqtkeoKeLEjThziJYGQFh/1gxSQ= -github.com/free5gc/openapi v1.2.2/go.mod h1:5HbgGqlhaTBwcOrXQLCOmpbQoX/ogKSg6+TAsR1VxUM= github.com/free5gc/openapi v1.2.3 h1:w4TmYBR8TUE4ZgKo7eiMZbyZPURSBFlMWiFeX+OsiA8= github.com/free5gc/openapi v1.2.3/go.mod h1:fLvaBtUZrvrzkKrmn5Aza+JNbpWnp3kxKixu6kLSD3k= -github.com/free5gc/util v1.2.0 h1:qA6EwiM7uAaE2SUSZDkUaMEa1DVEBoMN+wEWhRj8cYs= -github.com/free5gc/util v1.2.0/go.mod h1:eFZg7JCMlG1G5eCBbw+Gfs0SOBSIZv1OeuB1Sh0H+zE= -github.com/free5gc/util v1.3.1 h1:5j5Exvp42Ow3zNP2aaAp68MSne6BcaCF4/cekXYUS6w= -github.com/free5gc/util v1.3.1/go.mod h1:qsv/ez8YhI+pO8bjNiZWXc2xmRE3XuEIa0EDTCPkSy0= github.com/free5gc/util v1.3.2-0.20260107090449-c09baaf75b11 h1:/UZetXmPa5T/TKKxqU3Osw9x3+nIuACTXJxOU+gYGTU= github.com/free5gc/util v1.3.2-0.20260107090449-c09baaf75b11/go.mod h1:qsv/ez8YhI+pO8bjNiZWXc2xmRE3XuEIa0EDTCPkSy0= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= From a4ed151e2177c300436c1ccbbcf00a9b90b2da83 Mon Sep 17 00:00:00 2001 From: chchen7 Date: Sun, 11 Jan 2026 20:25:01 +0800 Subject: [PATCH 10/10] fix: fix golangci-lint error --- internal/sbi/api_ueauthentication.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/sbi/api_ueauthentication.go b/internal/sbi/api_ueauthentication.go index ccb27283..17f0e152 100644 --- a/internal/sbi/api_ueauthentication.go +++ b/internal/sbi/api_ueauthentication.go @@ -8,8 +8,8 @@ import ( "github.com/free5gc/openapi" "github.com/free5gc/openapi/models" "github.com/free5gc/udm/internal/logger" - "github.com/free5gc/util/validator" "github.com/free5gc/util/metrics/sbi" + "github.com/free5gc/util/validator" ) func (s *Server) getUEAuthenticationRoutes() []Route {