Skip to content

Commit af81b72

Browse files
committed
Record tls peer in logParts struct
* Record the TLS peer name in the logParts structure. * By default use the CN of the first peer certificate. * Allow a function to be specified which can extract whatever data is required from the connection and optionally return ok=false in order to close the connection. * Add a test for the above Signed-off-by: Alex Bligh <[email protected]>
1 parent 560bcf9 commit af81b72

File tree

2 files changed

+49
-10
lines changed

2 files changed

+49
-10
lines changed

server.go

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ const (
2323
datagramReadBufferSize = 64 * 1024
2424
)
2525

26+
// A function type which gets the TLS peer name from the connection. Can return
27+
// ok=false to terminate the connection
28+
type TlsPeerNameFunc func(tlsConn *tls.Conn) (tlsPeer string, ok bool)
29+
2630
type Server struct {
2731
listeners []net.Listener
2832
connections []net.Conn
@@ -33,11 +37,12 @@ type Server struct {
3337
handler Handler
3438
lastError error
3539
readTimeoutMilliseconds int64
40+
tlsPeerNameFunc TlsPeerNameFunc
3641
}
3742

3843
//NewServer returns a new Server
3944
func NewServer() *Server {
40-
return &Server{}
45+
return &Server{tlsPeerNameFunc: defaultTlsPeerName}
4146
}
4247

4348
//Sets the syslog format (RFC3164 or RFC5424 or RFC6587)
@@ -55,6 +60,21 @@ func (s *Server) SetTimeout(millseconds int64) {
5560
s.readTimeoutMilliseconds = millseconds
5661
}
5762

63+
// Set the function that extracts a TLS peer name from the TLS connection
64+
func (s *Server) SetTlsPeerNameFunc(tlsPeerNameFunc TlsPeerNameFunc) {
65+
s.tlsPeerNameFunc = tlsPeerNameFunc
66+
}
67+
68+
// Default TLS peer name function - returns the CN of the certificate
69+
func defaultTlsPeerName(tlsConn *tls.Conn) (tlsPeer string, ok bool) {
70+
state := tlsConn.ConnectionState()
71+
if len(state.PeerCertificates) <= 0 {
72+
return "", false
73+
}
74+
cn := state.PeerCertificates[0].Subject.CommonName
75+
return cn, true
76+
}
77+
5878
//Configure the server for listen on an UDP addr
5979
func (s *Server) ListenUDP(addr string) error {
6080
udpAddr, err := net.ResolveUDPAddr("udp", addr)
@@ -171,20 +191,37 @@ func (s *Server) goScanConnection(connection net.Conn) {
171191
scanner.Split(sf)
172192
}
173193

174-
var scanCloser *ScanCloser
175-
scanCloser = &ScanCloser{scanner, connection}
176-
177194
remoteAddr := connection.RemoteAddr()
178195
var client string
179196
if remoteAddr != nil {
180197
client = remoteAddr.String()
181198
}
182199

200+
tlsPeer := ""
201+
if tlsConn, ok := connection.(*tls.Conn); ok {
202+
// Handshake now so we get the TLS peer information
203+
if err := tlsConn.Handshake(); err != nil {
204+
connection.Close()
205+
return
206+
}
207+
if s.tlsPeerNameFunc != nil {
208+
var ok bool
209+
tlsPeer, ok = s.tlsPeerNameFunc(tlsConn)
210+
if !ok {
211+
connection.Close()
212+
return
213+
}
214+
}
215+
}
216+
217+
var scanCloser *ScanCloser
218+
scanCloser = &ScanCloser{scanner, connection}
219+
183220
s.wait.Add(1)
184-
go s.scan(scanCloser, client)
221+
go s.scan(scanCloser, client, tlsPeer)
185222
}
186223

187-
func (s *Server) scan(scanCloser *ScanCloser, client string) {
224+
func (s *Server) scan(scanCloser *ScanCloser, client string, tlsPeer string) {
188225
loop:
189226
for {
190227
select {
@@ -196,7 +233,7 @@ loop:
196233
scanCloser.closer.SetReadDeadline(time.Now().Add(time.Duration(s.readTimeoutMilliseconds) * time.Millisecond))
197234
}
198235
if scanCloser.Scan() {
199-
s.parser([]byte(scanCloser.Text()), client)
236+
s.parser([]byte(scanCloser.Text()), client, tlsPeer)
200237
} else {
201238
break loop
202239
}
@@ -206,7 +243,7 @@ loop:
206243
s.wait.Done()
207244
}
208245

209-
func (s *Server) parser(line []byte, client string) {
246+
func (s *Server) parser(line []byte, client string, tlsPeer string) {
210247
parser := s.format.GetParser(line)
211248
err := parser.Parse()
212249
if err != nil {
@@ -215,6 +252,7 @@ func (s *Server) parser(line []byte, client string) {
215252

216253
logParts := parser.Dump()
217254
logParts["client"] = client
255+
logParts["tls_peer"] = tlsPeer
218256

219257
s.handler.Handle(logParts, int64(len(line)), err)
220258
}
@@ -315,10 +353,10 @@ func (s *Server) goParseDatagrams() {
315353
}
316354
if sf := s.format.GetSplitFunc(); sf != nil {
317355
if _, token, err := sf(msg.message, true); err == nil {
318-
s.parser(token, msg.client)
356+
s.parser(token, msg.client, "")
319357
}
320358
} else {
321-
s.parser(msg.message, msg.client)
359+
s.parser(msg.message, msg.client, "")
322360
}
323361
}
324362
}

servertls_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ func (s *ServerSuite) TestTLS(c *C) {
8181
c.Check(handler.LastLogParts["hostname"], Equals, "hostname")
8282
c.Check(handler.LastLogParts["tag"], Equals, "tag")
8383
c.Check(handler.LastLogParts["content"], Equals, "content")
84+
c.Check(handler.LastLogParts["tls_peer"], Equals, "dummycert1")
8485
c.Check(handler.LastMessageLength, Equals, int64(len(exampleSyslog)))
8586
c.Check(handler.LastError, IsNil)
8687
}

0 commit comments

Comments
 (0)