File: preference.go

package info (click to toggle)
acmetool 0.2.2-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 792 kB
  • sloc: sh: 349; makefile: 105
file content (97 lines) | stat: -rw-r--r-- 2,330 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package solver

import (
	"gopkg.in/hlandau/acmeapi.v2"
	"sort"
)

// Any challenge having a preference at or below this value will never be used.
const NonviableThreshold int32 = -1000000

type sorter struct {
	authz       *acmeapi.Authorization
	order       []int
	preferencer Preferencer
}

func (s *sorter) Len() int {
	return len(s.order)
}

func (s *sorter) Swap(i, j int) {
	s.order[i], s.order[j] = s.order[j], s.order[i]
}

func (s *sorter) Less(i, j int) bool {
	pi := s.preference(&s.authz.Challenges[i])
	pj := s.preference(&s.authz.Challenges[j])
	return pi < pj
}

func (s *sorter) preference(ch *acmeapi.Challenge) int32 {
	v := s.preferencer.Preference(ch)
	if v <= NonviableThreshold {
		return NonviableThreshold
	}

	return v
}

// Returns a list of indices to authz.Challenges, sorted by preference, most
// preferred first.
func SortChallenges(authz *acmeapi.Authorization, preferencer Preferencer) (preferenceOrder []int) {
	preferenceOrder = make([]int, len(authz.Challenges))
	for i := 0; i < len(authz.Challenges); i++ {
		preferenceOrder[i] = i
	}

	s := sorter{
		authz:       authz,
		order:       preferenceOrder,
		preferencer: preferencer,
	}
	sort.Stable(sort.Reverse(&s))
	return
}

// TypePreferencer returns a preference according to the type of the challenge.
//
// Unknown challenge types are nonviable.
type TypePreferencer map[string]int32

// Implements Preferencer.
func (p TypePreferencer) Preference(ch *acmeapi.Challenge) int32 {
	v, ok := p[ch.Type]
	if !ok {
		return NonviableThreshold
	}
	return v
}

// Returns a copy of TypePreferencer, so that it can be mutated without
// changing the original.
func (p TypePreferencer) Copy() TypePreferencer {
	tp := TypePreferencer{}
	for k, v := range p {
		tp[k] = v
	}
	return tp
}

// PreferFast prefers fast types.
var PreferFast = TypePreferencer{
	"tls-sni-02": 2,
	"tls-sni-01": 1,
	"http-01":    0,

	// Disable DNS challenges for now. They're practically unusable and the Let's
	// Encrypt live server doesn't support them at this time anyway.
	"dns-01": -10,
}

// Determines the degree to which a challenge is preferred. Higher values are
// more preferred. Any value <= NonviableThreshold will never be used.
type Preferencer interface {
	// Get the preference for the given challenge.
	Preference(ch *acmeapi.Challenge) int32
}