-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtlsv3serverresponse.go
109 lines (100 loc) · 3.78 KB
/
tlsv3serverresponse.go
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
package main
import (
"bufio"
"crypto/x509"
"fmt"
"net"
"strings"
)
type TlsV3ServerResponse struct {
Protocol SslProtocol
ServerHello TlsV3ServerHello
Certificate []x509.Certificate
}
func (shello *TlsV3ServerResponse) read(socket net.Conn) (*TlsV3ServerResponse, error) {
data := getBytesFromSocket(socket, 5)
if len(data) == 0 {
return nil, ErrorRecordProtocolUnknown
}
running := true
for running { // some servers have a header for each message
switch data[0] {
case 0x16:
case 0x15:
return nil, ErrorRecordProtocolAlert
default:
return nil, ErrorRecordProtocolUnknown
}
shello.Protocol.Value = data[1:3]
servermessagelength := bytesToInt(data[3:5])
servermessagehex := getBytesFromSocket(socket, servermessagelength)
for len(servermessagehex) > 0 {
switch servermessagehex[0] {
case 0x00: // Hello Request
/*
When this message will be sent:
The HelloRequest message MAY be sent by the server at any time.
Meaning of this message:
HelloRequest is a simple notification that the client should begin
the negotiation process anew. In response, the client should send
a ClientHello message when convenient. This message is not
intended to establish which side is the client or server but
merely to initiate a new negotiation. Servers SHOULD NOT send a
HelloRequest immediately upon the client's initial connection. It
is the client's job to send a ClientHello at that time.
This message will be ignored by the client if the client is
currently negotiating a session. This message MAY be ignored by
the client if it does not wish to renegotiate a session, or the
client may, if it wishes, respond with a no_renegotiation alert.
Since handshake messages are intended to have transmission
precedence over application data, it is expected that the
negotiation will begin before no more than a few records are
received from the client. If the server sends a HelloRequest but
does not receive a ClientHello in response, it may close the
connection with a fatal alert.
After sending a HelloRequest, servers SHOULD NOT repeat the
request until the subsequent handshake negotiation is complete.
https://tools.ietf.org/html/rfc5246#section-7.4.1.1
*/
length := bytesToInt(servermessagehex[1:4])
servermessagehex = servermessagehex[length+4:]
case 0x02: // Server Hello
shello.ServerHello, servermessagehex = shello.ServerHello.parse(servermessagehex)
case 0x0b: // Certificate
shello.Certificate, servermessagehex = parseX509Certificate(servermessagehex)
case 0x0c: // Server Key Exchange
length := bytesToInt(servermessagehex[1:4])
servermessagehex = servermessagehex[length+4:] // dont parse, just cut off the data
case 0x0e: // Server Hello Done
length := bytesToInt(servermessagehex[1:4])
servermessagehex = servermessagehex[length+4:] // dont parse, just cut off the data
running = false
default:
servermessagehex = []byte{}
// if we reach this, the server wants us to parse something unknown, we ignore it
}
}
if running {
data = getBytesFromSocket(socket, 5)
if len(data) < 5 {
running = false
}
}
}
return shello, nil
}
func (shello *TlsV3ServerResponse) String() string {
lines := []string{}
lines = append(lines, fmt.Sprintf("Protocol: %s", shello.Protocol.String()))
scanner := bufio.NewScanner(strings.NewReader(shello.ServerHello.String()))
for scanner.Scan() {
lines = append(lines, fmt.Sprintf(" %s", scanner.Text()))
}
for _, cert := range shello.Certificate {
scanner := bufio.NewScanner(strings.NewReader(X509CertificateString(cert)))
for scanner.Scan() {
lines = append(lines, fmt.Sprintf(" %s", scanner.Text()))
}
}
return strings.Join(lines, "\n")
}