Browse Source

certfp: Add certfp retrieval from client

tags/v0.1.0
Daniel Oaks 7 years ago
parent
commit
49034cb20e
3 changed files with 34 additions and 0 deletions
  1. 6
    0
      irc/client.go
  2. 1
    0
      irc/server.go
  3. 27
    0
      irc/socket.go

+ 6
- 0
irc/client.go View File

@@ -51,6 +51,7 @@ type Client struct {
51 51
 	socket         *Socket
52 52
 	username       Name
53 53
 	isDestroyed    bool
54
+	certfp         string
54 55
 }
55 56
 
56 57
 func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
@@ -201,6 +202,11 @@ func (client *Client) Register() {
201 202
 	if client.registered {
202 203
 		return
203 204
 	}
205
+	if client.flags[TLS] {
206
+		// error is not useful to us here anyways, so we can ignore it
207
+		client.certfp, _ = client.socket.CertFP()
208
+		//TODO(dan): login based on certfp
209
+	}
204 210
 	client.registered = true
205 211
 	client.Touch()
206 212
 }

+ 1
- 0
irc/server.go View File

@@ -261,6 +261,7 @@ func (s *Server) listen(addr string, tlsMap map[Name]*tls.Config) {
261 261
 
262 262
 	tlsString := "plaintext"
263 263
 	if listenTLS {
264
+		config.ClientAuth = tls.RequestClientCert
264 265
 		listener = tls.NewListener(listener, config)
265 266
 		tlsString = "TLS"
266 267
 	}

+ 27
- 0
irc/socket.go View File

@@ -6,11 +6,20 @@ package irc
6 6
 
7 7
 import (
8 8
 	"bufio"
9
+	"crypto/sha256"
10
+	"crypto/tls"
11
+	"encoding/hex"
12
+	"errors"
9 13
 	"io"
10 14
 	"net"
11 15
 	"strings"
12 16
 )
13 17
 
18
+var (
19
+	errNotTls      = errors.New("Not a TLS connection")
20
+	errNoPeerCerts = errors.New("Client did not provide a certificate")
21
+)
22
+
14 23
 // Socket represents an IRC socket.
15 24
 type Socket struct {
16 25
 	Closed bool
@@ -35,6 +44,24 @@ func (socket *Socket) Close() {
35 44
 	socket.conn.Close()
36 45
 }
37 46
 
47
+// CertFP returns the fingerprint of the certificate provided by the client.
48
+func (socket *Socket) CertFP() (string, error) {
49
+	var tlsConn, isTLS = socket.conn.(*tls.Conn)
50
+	if !isTLS {
51
+		return "", errNotTls
52
+	}
53
+
54
+	peerCerts := tlsConn.ConnectionState().PeerCertificates
55
+	if len(peerCerts) < 1 {
56
+		return "", errNoPeerCerts
57
+	}
58
+
59
+	rawCert := sha256.Sum256(peerCerts[0].Raw)
60
+	fingerprint := hex.EncodeToString(rawCert[:])
61
+
62
+	return fingerprint, nil
63
+}
64
+
38 65
 // Read returns a single IRC line from a Socket.
39 66
 func (socket *Socket) Read() (string, error) {
40 67
 	if socket.Closed {

Loading…
Cancel
Save