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
9d7639a9
Commit
9d7639a9
authored
Jun 02, 2015
by
Matt Holt
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #98 from mholt/clientauth
tls: Client authentication
parents
9ce0e8e1
6c523681
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
79 additions
and
2 deletions
+79
-2
config/setup/tls.go
config/setup/tls.go
+6
-1
config/setup/tls_test.go
config/setup/tls_test.go
+31
-0
server/config.go
server/config.go
+1
-0
server/server.go
server/server.go
+41
-1
No files found.
config/setup/tls.go
View file @
9d7639a9
...
...
@@ -53,8 +53,13 @@ func TLS(c *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
{
return
nil
,
c
.
ArgErr
()
}
default
:
return
nil
,
c
.
Errf
(
"Unknown keyword '%s'"
)
return
nil
,
c
.
Errf
(
"Unknown keyword '%s'"
,
c
.
Val
()
)
}
}
}
...
...
config/setup/tls_test.go
View file @
9d7639a9
...
...
@@ -127,3 +127,34 @@ func TestTLSParseWithWrongOptionalParams(t *testing.T) {
t
.
Errorf
(
"Expected errors, but no error returned"
)
}
}
func
TestTLSParseWithClientAuth
(
t
*
testing
.
T
)
{
params
:=
`tls cert.crt cert.key {
clients client_ca.crt client2_ca.crt
}`
c
:=
newTestController
(
params
)
_
,
err
:=
TLS
(
c
)
if
err
!=
nil
{
t
.
Errorf
(
"Expected no errors, got: %v"
,
err
)
}
if
count
:=
len
(
c
.
TLS
.
ClientCerts
);
count
!=
2
{
t
.
Fatalf
(
"Expected two client certs, had %d"
,
count
)
}
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
)
}
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
)
}
// Test missing client cert file
params
=
`tls cert.crt cert.key {
clients
}`
c
=
newTestController
(
params
)
_
,
err
=
TLS
(
c
)
if
err
==
nil
{
t
.
Errorf
(
"Expected an error, but no error returned"
)
}
}
server/config.go
View file @
9d7639a9
...
...
@@ -64,4 +64,5 @@ type TLSConfig struct {
ProtocolMinVersion
uint16
ProtocolMaxVersion
uint16
PreferServerCipherSuites
bool
ClientCerts
[]
string
}
server/server.go
View file @
9d7639a9
...
...
@@ -5,7 +5,9 @@ package server
import
(
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
...
...
@@ -137,15 +139,53 @@ func ListenAndServeTLSWithSNI(srv *http.Server, tlsConfigs []TLSConfig) error {
config
.
CipherSuites
=
tlsConfigs
[
0
]
.
Ciphers
config
.
PreferServerCipherSuites
=
tlsConfigs
[
0
]
.
PreferServerCipherSuites
conn
,
err
:=
net
.
Listen
(
"tcp"
,
addr
)
// TLS client authentication, if user enabled it
err
=
setupClientAuth
(
tlsConfigs
,
config
)
if
err
!=
nil
{
return
err
}
// Create listener and we're on our way
conn
,
err
:=
net
.
Listen
(
"tcp"
,
addr
)
if
err
!=
nil
{
return
err
}
tlsListener
:=
tls
.
NewListener
(
conn
,
config
)
return
srv
.
Serve
(
tlsListener
)
}
// 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
for
_
,
cfg
:=
range
tlsConfigs
{
if
len
(
cfg
.
ClientCerts
)
>
0
{
clientAuth
=
true
break
}
}
if
clientAuth
{
pool
:=
x509
.
NewCertPool
()
for
_
,
cfg
:=
range
tlsConfigs
{
for
_
,
caFile
:=
range
cfg
.
ClientCerts
{
caCrt
,
err
:=
ioutil
.
ReadFile
(
caFile
)
// Anyone that gets a cert from Matt Holt can connect
if
err
!=
nil
{
return
err
}
if
!
pool
.
AppendCertsFromPEM
(
caCrt
)
{
return
fmt
.
Errorf
(
"Error loading client certificate '%s': no certificates were successfully parsed"
,
caFile
)
}
}
}
config
.
ClientCAs
=
pool
config
.
ClientAuth
=
tls
.
RequireAndVerifyClientCert
}
return
nil
}
// ServeHTTP is the entry point for every request to the address that s
// is bound to. It acts as a multiplexer for the requests hostname as
// defined in the Host header so that the correct virtualhost
...
...
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