372
srv.AutoHTTPS.Skip = append(srv.AutoHTTPS.Skip, autoHTTPSQualifiedHosts...)
373
} else if cpVals, ok := sblock.pile["tls.connection_policy"]; ok {
374
// tls connection policies
375
+ var hasCatchAll bool
376
for _, cpVal := range cpVals {
377
cp := cpVal.Value.(*caddytls.ConnectionPolicy)
378
382
return nil, err
383
}
384
384
- // TODO: are matchers needed if every hostname of the config is matched?
385
+ // TODO: are matchers needed if every hostname of the resulting config is matched?
386
if len(hosts) > 0 {
387
cp.MatchersRaw = caddy.ModuleMap{
388
"sni": caddyconfig.JSON(hosts, warnings), // make sure to match all hosts, not just auto-HTTPS-qualified ones
389
}
390
+ } else {
391
+ hasCatchAll = true
392
}
393
+
394
srv.TLSConnPolicies = append(srv.TLSConnPolicies, cp)
395
}
396
+
397
+ // a catch-all is necessary to ensure TLS can be offered to
398
+ // all hostnames of the server; even though only one policy
399
+ // is needed to enable TLS for the server, that policy might
400
+ // apply to only certain TLS handshakes; but when using the
401
+ // Caddyfile, user would expect all handshakes to at least
402
+ // have a matching connection policy, so here we append a
403
+ // catch-all/default policy if there isn't one already (it's
404
+ // important that it goes at the end) - see issue #3004:
405
+ // https://github.com/caddyserver/caddy/issues/3004
406
+ if !hasCatchAll {
407
+ srv.TLSConnPolicies = append(srv.TLSConnPolicies, new(caddytls.ConnectionPolicy))
408
+ }
409
+
410
// TODO: consolidate equal conn policies
411
}
412
587
if j == i {
588
continue
589
}
572
- if reflect.DeepEqual(aps[i].ManagementRaw, aps[j].ManagementRaw) {
573
- aps[i].Hosts = append(aps[i].Hosts, aps[j].Hosts...)
590
+
591
+ // if they're exactly equal in every way, just keep one of them
592
+ if reflect.DeepEqual(aps[i], aps[j]) {
593
aps = append(aps[:j], aps[j+1:]...)
594
i--
595
break
596
}
597
+
598
+ // if the policy is the same, we can keep just one, but we have
599
+ // to be careful which one we keep; if only one has any hostnames
600
+ // defined, then we need to keep the one without any hostnames,
601
+ // otherwise the one without any hosts (a catch-all) would be
602
+ // eaten up by the one with hosts; and if both have hosts, we
603
+ // need to combine their lists
604
+ if reflect.DeepEqual(aps[i].ManagementRaw, aps[j].ManagementRaw) &&
605
+ aps[i].ManageSync == aps[j].ManageSync {
606
+ if len(aps[i].Hosts) == 0 && len(aps[j].Hosts) > 0 {
607
+ aps = append(aps[:j], aps[j+1:]...)
608
+ } else if len(aps[i].Hosts) > 0 && len(aps[j].Hosts) == 0 {
609
+ aps = append(aps[:i], aps[i+1:]...)
610
+ } else {
611
+ aps[i].Hosts = append(aps[i].Hosts, aps[j].Hosts...)
612
+ aps = append(aps[:j], aps[j+1:]...)
613
+ }
614
+ i--
615
+ break
616
+ }
617
}
618
}
619
+
620
+ // ensure any catch-all policies go last
621
+ sort.SliceStable(aps, func(i, j int) bool {
622
+ return len(aps[i].Hosts) > len(aps[j].Hosts)
623
+ })
624
+
625
return aps
626
}
627