FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
caddy/caddyhttp/httpserver/https.go at master · CUjamin/caddy · GitHub
CUjamin
/
caddy
Public
forked from
caddyserver/caddy
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
caddy
/
caddyhttp
/
httpserver
/
https.go
Copy path
More file actions
More file actions
Latest commit
History
History
History
213 lines (188 loc) · 7.13 KB
Breadcrumbs
caddy
/
caddyhttp
/
httpserver
/
https.go
Copy path
File metadata and controls
213 lines (188 loc) · 7.13 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
// Copyright 2015 Light Code Labs, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package
httpserver
import
(
"fmt"
"net"
"net/http"
"github.com/mholt/caddy"
"github.com/mholt/caddy/caddytls"
)
func
activateHTTPS
(
cctx
caddy.
Context
)
error
{
operatorPresent
:=
!
caddy
.
Started
()
if
!
caddy
.
Quiet
&&
operatorPresent
{
fmt
.
Print
(
"Activating privacy features... "
)
}
ctx
:=
cctx
.(
*
httpContext
)
// pre-screen each config and earmark the ones that qualify for managed TLS
markQualifiedForAutoHTTPS
(
ctx
.
siteConfigs
)
// place certificates and keys on disk
for
_
,
c
:=
range
ctx
.
siteConfigs
{
if
c
.
TLS
.
OnDemand
{
continue
// obtain these certificates on-demand instead
}
err
:=
c
.
TLS
.
ObtainCert
(
c
.
TLS
.
Hostname
,
operatorPresent
)
if
err
!=
nil
{
return
err
}
}
// update TLS configurations
err
:=
enableAutoHTTPS
(
ctx
.
siteConfigs
,
true
)
if
err
!=
nil
{
return
err
}
// set up redirects
ctx
.
siteConfigs
=
makePlaintextRedirects
(
ctx
.
siteConfigs
)
// renew all relevant certificates that need renewal. this is important
// to do right away so we guarantee that renewals aren't missed, and
// also the user can respond to any potential errors that occur.
// (skip if upgrading, because the parent process is likely already listening
// on the ports we'd need to do ACME before we finish starting; parent process
// already running renewal ticker, so renewal won't be missed anyway.)
if
!
caddy
.
IsUpgrade
() {
err
=
caddytls
.
RenewManagedCertificates
(
true
)
if
err
!=
nil
{
return
err
}
}
if
!
caddy
.
Quiet
&&
operatorPresent
{
fmt
.
Println
(
"done."
)
}
return
nil
}
// markQualifiedForAutoHTTPS scans each config and, if it
// qualifies for managed TLS, it sets the Managed field of
// the TLS config to true.
func
markQualifiedForAutoHTTPS
(
configs
[]
*
SiteConfig
) {
for
_
,
cfg
:=
range
configs
{
if
caddytls
.
QualifiesForManagedTLS
(
cfg
)
&&
cfg
.
Addr
.
Scheme
!=
"http"
{
cfg
.
TLS
.
Managed
=
true
}
}
}
// enableAutoHTTPS configures each config to use TLS according to default settings.
// It will only change configs that are marked as managed but not on-demand, and
// assumes that certificates and keys are already on disk. If loadCertificates is
// true, the certificates will be loaded from disk into the cache for this process
// to use. If false, TLS will still be enabled and configured with default settings,
// but no certificates will be parsed loaded into the cache, and the returned error
// value will always be nil.
func
enableAutoHTTPS
(
configs
[]
*
SiteConfig
,
loadCertificates
bool
)
error
{
for
_
,
cfg
:=
range
configs
{
if
cfg
==
nil
||
cfg
.
TLS
==
nil
||
!
cfg
.
TLS
.
Managed
||
cfg
.
TLS
.
OnDemand
{
continue
}
cfg
.
TLS
.
Enabled
=
true
cfg
.
Addr
.
Scheme
=
"https"
if
loadCertificates
&&
caddytls
.
HostQualifies
(
cfg
.
TLS
.
Hostname
) {
_
,
err
:=
cfg
.
TLS
.
CacheManagedCertificate
(
cfg
.
TLS
.
Hostname
)
if
err
!=
nil
{
return
err
}
}
// Make sure any config values not explicitly set are set to default
caddytls
.
SetDefaultTLSParams
(
cfg
.
TLS
)
// Set default port of 443 if not explicitly set
if
cfg
.
Addr
.
Port
==
""
&&
cfg
.
TLS
.
Enabled
&&
(
!
cfg
.
TLS
.
Manual
||
cfg
.
TLS
.
OnDemand
)
&&
cfg
.
Addr
.
Host
!=
"localhost"
{
cfg
.
Addr
.
Port
=
HTTPSPort
}
}
return
nil
}
// makePlaintextRedirects sets up redirects from port 80 to the relevant HTTPS
// hosts. You must pass in all configs, not just configs that qualify, since
// we must know whether the same host already exists on port 80, and those would
// not be in a list of configs that qualify for automatic HTTPS. This function will
// only set up redirects for configs that qualify. It returns the updated list of
// all configs.
func
makePlaintextRedirects
(
allConfigs
[]
*
SiteConfig
) []
*
SiteConfig
{
for
i
,
cfg
:=
range
allConfigs
{
if
cfg
.
TLS
.
Managed
&&
!
hostHasOtherPort
(
allConfigs
,
i
,
HTTPPort
)
&&
(
cfg
.
Addr
.
Port
==
HTTPSPort
||
!
hostHasOtherPort
(
allConfigs
,
i
,
HTTPSPort
)) {
allConfigs
=
append
(
allConfigs
,
redirPlaintextHost
(
cfg
))
}
}
return
allConfigs
}
// hostHasOtherPort returns true if there is another config in the list with the same
// hostname that has port otherPort, or false otherwise. All the configs are checked
// against the hostname of allConfigs[thisConfigIdx].
func
hostHasOtherPort
(
allConfigs
[]
*
SiteConfig
,
thisConfigIdx
int
,
otherPort
string
)
bool
{
for
i
,
otherCfg
:=
range
allConfigs
{
if
i
==
thisConfigIdx
{
continue
// has to be a config OTHER than the one we're comparing against
}
if
otherCfg
.
Addr
.
Host
==
allConfigs
[
thisConfigIdx
].
Addr
.
Host
&&
otherCfg
.
Addr
.
Port
==
otherPort
{
return
true
}
}
return
false
}
// redirPlaintextHost returns a new plaintext HTTP configuration for
// a virtualHost that simply redirects to cfg, which is assumed to
// be the HTTPS configuration. The returned configuration is set
// to listen on HTTPPort. The TLS field of cfg must not be nil.
func
redirPlaintextHost
(
cfg
*
SiteConfig
)
*
SiteConfig
{
redirPort
:=
cfg
.
Addr
.
Port
if
redirPort
==
HTTPSPort
{
// By default, HTTPSPort should be DefaultHTTPSPort,
// which of course doesn't need to be explicitly stated
// in the Location header. Even if HTTPSPort is changed
// so that it is no longer DefaultHTTPSPort, we shouldn't
// append it to the URL in the Location because changing
// the HTTPS port is assumed to be an internal-only change
// (in other words, we assume port forwarding is going on);
// but redirects go back to a presumably-external client.
// (If redirect clients are also internal, that is more
// advanced, and the user should configure HTTP->HTTPS
// redirects themselves.)
redirPort
=
""
}
redirMiddleware
:=
func
(
next
Handler
)
Handler
{
return
HandlerFunc
(
func
(
w
http.
ResponseWriter
,
r
*
http.
Request
) (
int
,
error
) {
// Construct the URL to which to redirect. Note that the Host in a
// request might contain a port, but we just need the hostname from
// it; and we'll set the port if needed.
toURL
:=
"https://"
requestHost
,
_
,
err
:=
net
.
SplitHostPort
(
r
.
Host
)
if
err
!=
nil
{
requestHost
=
r
.
Host
// Host did not contain a port, so use the whole value
}
if
redirPort
==
""
{
toURL
+=
requestHost
}
else
{
toURL
+=
net
.
JoinHostPort
(
requestHost
,
redirPort
)
}
toURL
+=
r
.
URL
.
RequestURI
()
w
.
Header
().
Set
(
"Connection"
,
"close"
)
http
.
Redirect
(
w
,
r
,
toURL
,
http
.
StatusMovedPermanently
)
return
0
,
nil
})
}
host
:=
cfg
.
Addr
.
Host
port
:=
HTTPPort
addr
:=
net
.
JoinHostPort
(
host
,
port
)
return
&
SiteConfig
{
Addr
:
Address
{
Original
:
addr
,
Host
:
host
,
Port
:
port
},
ListenHost
:
cfg
.
ListenHost
,
middleware
: []
Middleware
{
redirMiddleware
},
TLS
:
&
caddytls.
Config
{
AltHTTPPort
:
cfg
.
TLS
.
AltHTTPPort
,
AltTLSSNIPort
:
cfg
.
TLS
.
AltTLSSNIPort
},
Timeouts
:
cfg
.
Timeouts
,
}
}
Back
|
FazBrowse Home
|
New Git URL