Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
caddy
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
caddy
Commits
ddf4b1fd
Commit
ddf4b1fd
authored
Apr 15, 2016
by
W. Mark Kubacki
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #757 from mholt/extend-tls-client-auth
Extend tls client auth
parents
4e98cc30
69c2d78f
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
98 additions
and
28 deletions
+98
-28
caddy/https/setup.go
caddy/https/setup.go
+22
-2
caddy/https/setup_test.go
caddy/https/setup_test.go
+55
-20
server/config.go
server/config.go
+2
-0
server/server.go
server/server.go
+19
-6
No files found.
caddy/https/setup.go
View file @
ddf4b1fd
...
...
@@ -83,10 +83,30 @@ func Setup(c *setup.Controller) (middleware.Middleware, error) {
c
.
TLS
.
Ciphers
=
append
(
c
.
TLS
.
Ciphers
,
value
)
}
case
"clients"
:
c
.
TLS
.
ClientCerts
=
c
.
RemainingArgs
()
if
len
(
c
.
TLS
.
ClientCerts
)
==
0
{
c
lientCertList
:
=
c
.
RemainingArgs
()
if
len
(
c
lientCertList
)
==
0
{
return
nil
,
c
.
ArgErr
()
}
listStart
,
mustProvideCA
:=
1
,
true
switch
clientCertList
[
0
]
{
case
"request"
:
c
.
TLS
.
ClientAuth
=
tls
.
RequestClientCert
mustProvideCA
=
false
case
"require"
:
c
.
TLS
.
ClientAuth
=
tls
.
RequireAnyClientCert
mustProvideCA
=
false
case
"verify_if_given"
:
c
.
TLS
.
ClientAuth
=
tls
.
VerifyClientCertIfGiven
default
:
c
.
TLS
.
ClientAuth
=
tls
.
RequireAndVerifyClientCert
listStart
=
0
}
if
mustProvideCA
&&
len
(
clientCertList
)
<=
listStart
{
return
nil
,
c
.
ArgErr
()
}
c
.
TLS
.
ClientCerts
=
clientCertList
[
listStart
:
]
case
"load"
:
c
.
Args
(
&
loadDir
)
c
.
TLS
.
Manual
=
true
...
...
caddy/https/setup_test.go
View file @
ddf4b1fd
...
...
@@ -189,33 +189,68 @@ func TestSetupParseWithWrongOptionalParams(t *testing.T) {
}
func
TestSetupParseWithClientAuth
(
t
*
testing
.
T
)
{
// Test missing client cert file
params
:=
`tls `
+
certFile
+
` `
+
keyFile
+
` {
clients
client_ca.crt client2_ca.crt
clients
}`
c
:=
setup
.
NewTestController
(
params
)
_
,
err
:=
Setup
(
c
)
if
err
!
=
nil
{
t
.
Errorf
(
"Expected
no errors, got: %v"
,
err
)
if
err
=
=
nil
{
t
.
Errorf
(
"Expected
an error, but no error returned"
)
}
if
count
:=
len
(
c
.
TLS
.
ClientCerts
);
count
!=
2
{
t
.
Fatalf
(
"Expected two client certs, had %d"
,
count
)
noCAs
,
twoCAs
:=
[]
string
{},
[]
string
{
"client_ca.crt"
,
"client2_ca.crt"
}
for
caseNumber
,
caseData
:=
range
[]
struct
{
params
string
clientAuthType
tls
.
ClientAuthType
expectedErr
bool
expectedCAs
[]
string
}{
{
""
,
tls
.
NoClientCert
,
false
,
noCAs
},
{
`tls `
+
certFile
+
` `
+
keyFile
+
` {
clients client_ca.crt client2_ca.crt
}`
,
tls
.
RequireAndVerifyClientCert
,
false
,
twoCAs
},
// now come modifier
{
`tls `
+
certFile
+
` `
+
keyFile
+
` {
clients request
}`
,
tls
.
RequestClientCert
,
false
,
noCAs
},
{
`tls `
+
certFile
+
` `
+
keyFile
+
` {
clients require
}`
,
tls
.
RequireAnyClientCert
,
false
,
noCAs
},
{
`tls `
+
certFile
+
` `
+
keyFile
+
` {
clients verify_if_given client_ca.crt client2_ca.crt
}`
,
tls
.
VerifyClientCertIfGiven
,
false
,
twoCAs
},
{
`tls `
+
certFile
+
` `
+
keyFile
+
` {
clients verify_if_given
}`
,
tls
.
VerifyClientCertIfGiven
,
true
,
noCAs
},
}
{
c
:=
setup
.
NewTestController
(
caseData
.
params
)
_
,
err
:=
Setup
(
c
)
if
caseData
.
expectedErr
{
if
err
==
nil
{
t
.
Errorf
(
"In case %d: Expected an error, got: %v"
,
caseNumber
,
err
)
}
if
actual
:=
c
.
TLS
.
ClientCerts
[
0
];
actual
!=
"client_ca.crt"
{
t
.
Errorf
(
"Expected first client cert file to be '%s', but was '%s'"
,
"client_ca.crt"
,
actual
)
continue
}
if
actual
:=
c
.
TLS
.
ClientCerts
[
1
];
actual
!=
"client2_ca.crt"
{
t
.
Errorf
(
"Expected second client cert file to be '%s', but was '%s'"
,
"client2_ca.crt"
,
actual
)
if
err
!=
nil
{
t
.
Errorf
(
"In case %d: Expected no errors, got: %v"
,
caseNumber
,
err
)
}
// Test missing client cert file
params
=
`tls `
+
certFile
+
` `
+
keyFile
+
` {
clients
}`
c
=
setup
.
NewTestController
(
params
)
_
,
err
=
Setup
(
c
)
if
err
==
nil
{
t
.
Errorf
(
"Expected an error, but no error returned"
)
if
caseData
.
clientAuthType
!=
c
.
TLS
.
ClientAuth
{
t
.
Errorf
(
"In case %d: Expected TLS client auth type %v, got: %v"
,
caseNumber
,
caseData
.
clientAuthType
,
c
.
TLS
.
ClientAuth
)
}
if
count
:=
len
(
c
.
TLS
.
ClientCerts
);
count
<
len
(
caseData
.
expectedCAs
)
{
t
.
Fatalf
(
"In case %d: Expected %d client certs, had %d"
,
caseNumber
,
len
(
caseData
.
expectedCAs
),
count
)
}
for
idx
,
expected
:=
range
caseData
.
expectedCAs
{
if
actual
:=
c
.
TLS
.
ClientCerts
[
idx
];
actual
!=
expected
{
t
.
Errorf
(
"In case %d: Expected %dth client cert file to be '%s', but was '%s'"
,
caseNumber
,
idx
,
expected
,
actual
)
}
}
}
}
...
...
server/config.go
View file @
ddf4b1fd
package
server
import
(
"crypto/tls"
"net"
"github.com/mholt/caddy/middleware"
...
...
@@ -75,4 +76,5 @@ type TLSConfig struct {
ProtocolMaxVersion
uint16
PreferServerCipherSuites
bool
ClientCerts
[]
string
ClientAuth
tls
.
ClientAuthType
}
server/server.go
View file @
ddf4b1fd
...
...
@@ -14,6 +14,7 @@ import (
"net"
"net/http"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
...
...
@@ -332,6 +333,16 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}
// Use URL.RawPath If you need the original, "raw" URL.Path in your middleware.
// Collapse any ./ ../ /// madness here instead of doing that in every plugin.
if
r
.
URL
.
Path
!=
"/"
{
path
:=
filepath
.
Clean
(
r
.
URL
.
Path
)
if
!
strings
.
HasPrefix
(
path
,
"/"
)
{
path
=
"/"
+
path
}
r
.
URL
.
Path
=
path
}
// Execute the optional request callback if it exists and it's not disabled
if
s
.
ReqCallback
!=
nil
&&
!
s
.
vhosts
[
host
]
.
config
.
TLS
.
Manual
&&
s
.
ReqCallback
(
w
,
r
)
{
return
...
...
@@ -368,17 +379,19 @@ func DefaultErrorFunc(w http.ResponseWriter, r *http.Request, status int) {
// setupClientAuth sets up TLS client authentication only if
// any of the TLS configs specified at least one cert file.
func
setupClientAuth
(
tlsConfigs
[]
TLSConfig
,
config
*
tls
.
Config
)
error
{
var
clientAuth
bool
whatClientAuth
:=
tls
.
NoClientCert
for
_
,
cfg
:=
range
tlsConfigs
{
if
len
(
cfg
.
ClientCerts
)
>
0
{
clientAuth
=
true
break
if
whatClientAuth
<
cfg
.
ClientAuth
{
// Use the most restrictive.
whatClientAuth
=
cfg
.
ClientAuth
}
}
if
clientAuth
{
if
whatClientAuth
!=
tls
.
NoClientCert
{
pool
:=
x509
.
NewCertPool
()
for
_
,
cfg
:=
range
tlsConfigs
{
if
len
(
cfg
.
ClientCerts
)
==
0
{
continue
}
for
_
,
caFile
:=
range
cfg
.
ClientCerts
{
caCrt
,
err
:=
ioutil
.
ReadFile
(
caFile
)
// Anyone that gets a cert from this CA can connect
if
err
!=
nil
{
...
...
@@ -390,7 +403,7 @@ func setupClientAuth(tlsConfigs []TLSConfig, config *tls.Config) error {
}
}
config
.
ClientCAs
=
pool
config
.
ClientAuth
=
tls
.
RequireAndVerifyClientCert
config
.
ClientAuth
=
whatClientAuth
}
return
nil
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment