diff --git a/lib/config/config_test.go b/lib/config/config_test.go index 5245f6eb2..9943280b9 100644 --- a/lib/config/config_test.go +++ b/lib/config/config_test.go @@ -869,3 +869,68 @@ func TestIssue4219(t *testing.T) { t.Error("Folder abcd123 should not be ignored") } } + +func TestInvalidDeviceIDRejected(t *testing.T) { + // This test verifies that we properly reject invalid device IDs when + // deserializing a JSON config from the API. + + cases := []struct { + id string + ok bool + }{ + // a genuine device ID + {"GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY", true}, + // incorrect check digit + {"GYRZZQB-IRNPV4A-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VAY", false}, + // missing digit + {"GYRZZQB-IRNPV4Z-T7TC52W-EQYJ3TT-FDQW6MW-DFLMU42-SSSU6EM-FBK2VA", false}, + // clearly broken + {"invalid", false}, + // accepted as the empty device ID for historical reasons... + {"", true}, + } + + for _, tc := range cases { + cfg := defaultConfigAsMap() + + // Change the device ID of the first device to "invalid". Fast and loose + // with the type assertions as we know what the JSON decoder does. + devs := cfg["devices"].([]interface{}) + dev0 := devs[0].(map[string]interface{}) + dev0["deviceID"] = tc.id + devs[0] = dev0 + + invalidJSON, err := json.Marshal(cfg) + if err != nil { + t.Fatal(err) + } + + _, err = ReadJSON(bytes.NewReader(invalidJSON), device1) + if tc.ok && err != nil { + if err != nil { + t.Errorf("unexpected error for device ID %q: %v", tc.id, err) + } + } else if !tc.ok && err == nil { + t.Errorf("device ID %q, expected error but got nil", tc.id) + } + } +} + +// defaultConfigAsMap returns a valid default config as a JSON-decoded +// map[string]interface{}. This is useful to override random elements and +// re-encode into JSON. +func defaultConfigAsMap() map[string]interface{} { + cfg := New(device1) + cfg.Devices = append(cfg.Devices, NewDeviceConfiguration(device2, "name")) + bs, err := json.Marshal(cfg) + if err != nil { + // can't happen + panic(err) + } + var tmp map[string]interface{} + if err := json.Unmarshal(bs, &tmp); err != nil { + // can't happen + panic(err) + } + return tmp +}