-
Notifications
You must be signed in to change notification settings - Fork 92
/
tlsclienthello.c
168 lines (156 loc) · 5.42 KB
/
tlsclienthello.c
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#ifdef _WIN32
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib")
#define socklen_t int
#define sleep(x) Sleep(x*1000)
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#endif
#include "../tlse.c"
void error(char *msg) {
perror(msg);
exit(0);
}
/*
// Use this version with DTLS (preserving message boundary)
int send_pending_udp(int client_sock, struct TLSContext *context, struct sockaddr_in *clientaddr, socklen_t socket_len) {
unsigned int out_buffer_len = 0;
unsigned int offset = 0;
int send_res = 0;
const unsigned char *out_buffer;
do {
out_buffer = tls_get_message(context, &out_buffer_len, offset);
if (out_buffer) {
send_res += sendto(client_sock, out_buffer, out_buffer_len, 0, (struct sockaddr *)clientaddr, socket_len);
offset += out_buffer_len;
}
} while (out_buffer);
tls_buffer_clear(context);
return send_res;
}
*/
int send_pending(int client_sock, struct TLSContext *context) {
unsigned int out_buffer_len = 0;
const unsigned char *out_buffer = tls_get_write_buffer(context, &out_buffer_len);
unsigned int out_buffer_index = 0;
int send_res = 0;
while ((out_buffer) && (out_buffer_len > 0)) {
int res = send(client_sock, (char *)&out_buffer[out_buffer_index], out_buffer_len, 0);
if (res <= 0) {
send_res = res;
break;
}
out_buffer_len -= res;
out_buffer_index += res;
}
tls_buffer_clear(context);
return send_res;
}
int validate_certificate(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len) {
int i;
int err;
if (certificate_chain) {
for (i = 0; i < len; i++) {
struct TLSCertificate *certificate = certificate_chain[i];
// check validity date
err = tls_certificate_is_valid(certificate);
if (err)
return err;
// check certificate in certificate->bytes of length certificate->len
// the certificate is in ASN.1 DER format
}
}
// check if chain is valid
err = tls_certificate_chain_is_valid(certificate_chain, len);
if (err)
return err;
const char *sni = tls_sni(context);
if ((len > 0) && (sni)) {
err = tls_certificate_valid_subject(certificate_chain[0], sni);
if (err)
return err;
}
fprintf(stderr, "Certificate OK\n");
//return certificate_expired;
//return certificate_revoked;
//return certificate_unknown;
return no_error;
}
int main(int argc, char *argv[]) {
int sockfd, portno, n;
//tls_print_certificate("testcert/server.certificate");
//tls_print_certificate("000.certificate");
//exit(0);
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
char *ref_argv[] = {"", "google.com", "443"};
if (argc < 3) {
argv = ref_argv;
//fprintf(stderr,"usage %s hostname port\n", argv[0]);
//exit(0);
}
#ifdef _WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#else
signal(SIGPIPE, SIG_IGN);
#endif
portno = atoi(argv[2]);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
memset((char *) &serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
struct TLSContext *context = tls_create_context(0, TLS_V13);
// the next line is needed only if you want to serialize the connection context or kTLS is used
tls_make_exportable(context, 1);
tls_sni_set(context, argv[1]);
tls_client_connect(context);
send_pending(sockfd, context);
unsigned char client_message[0xFFFF];
int read_size;
int sent = 0;
while ((read_size = recv(sockfd, client_message, sizeof(client_message) , 0)) > 0) {
tls_consume_stream(context, client_message, read_size, validate_certificate);
send_pending(sockfd, context);
if (tls_established(context) == 1) {
if (!sent) {
const char *request = "GET / HTTP/1.1\r\nConnection: close\r\n\r\n";
// try kTLS (kernel TLS implementation in linux >= 4.13)
// note that you can use send on a ktls socket
// recv must be handled by TLSe
if (!tls_make_ktls(context, sockfd)) {
// call send as on regular TCP sockets
// TLS record layer is handled by the kernel
send(sockfd, request, strlen(request), 0);
} else {
tls_write(context, (unsigned char *)request, strlen(request));
send_pending(sockfd, context);
}
sent = 1;
}
unsigned char read_buffer[0xFFFF];
int read_size = tls_read(context, read_buffer, 0xFFFF - 1);
if (read_size > 0)
fwrite(read_buffer, read_size, 1, stdout);
}
}
return 0;
}