package utils import ( "fmt" "net/http" "strings" "fiskerinc.com/modules/logger" "fiskerinc.com/modules/validator" ) // ParseVINFromRequest retrieves VIN from "Ssl-Client-Subject-Dn" // // which is generated by NGINX through a cert on websocket request func ParseVINFromRequest(r *http.Request) (vin string, err error) { // Try SDK 1.2 format first: Ssl-Client-Subject-Dn header vin = retrieveCommonNameFromHeaderSSLClientSubject(r) if vin == "" { // Try SDK 1.4 format: Ssl header vin = retrieveCommonNameFromHeaderSSL(r) } ok := validator.ValidateVINSimple(vin) if ok { return vin, nil } // If neither header format contains a VIN, return error return "", fmt.Errorf("VIN not found in request headers: '%s' bad value", vin) } func retrieveCommonNameFromHeaderSSL(r *http.Request) (vin string) { sslHeader := r.Header.Get("Ssl") logger.Info().Str("SSL Header Value", sslHeader).Msg("CSDK 1.2 VIN Format Failed, trying 1.4") if sslHeader != "" { // Extract VIN from "CN=VIN_HERE" format if strings.HasPrefix(sslHeader, "CN=") { vin = strings.TrimPrefix(sslHeader, "CN=") } } return } func retrieveCommonNameFromHeaderSSLClientSubject(r *http.Request) string { dn := r.Header.Values("Ssl-Client-Subject-Dn") for _, d := range dn { fields := strings.Split(d, ",") for _, field := range fields { if len(field) > 3 && field[:3] == "CN=" { return field[3:] } } } return "" }