Skip to content

Commit 856e8ca

Browse files
committed
add TLS-enabled nc
haven't used libtls before, so might be buggy.
1 parent d62e836 commit 856e8ca

File tree

3 files changed

+214
-1
lines changed

3 files changed

+214
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
nc
2+
tlsnc

Makefile

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
.POSIX:
22

33
XCFLAGS = $(CFLAGS) -Wall -Wextra -Wpedantic -g -Og -D_XOPEN_SOURCE=700
4+
TLSFLAGS = $$(pkg-config --libs --cflags libtls || echo -ltls)
5+
6+
all: nc tlsnc
47

58
nc: nc.c
69
$(CC) $(XCFLAGS) $(LDFLAGS) nc.c -o $@
710

11+
tlsnc: tlsnc.c
12+
$(CC) $(XCFLAGS) $(LDFLAGS) $(TLSFLAGS) tlsnc.c -o $@
13+
814
clean:
9-
rm -f nc
15+
rm -f nc tlsnc
16+
17+
.PHONY: clean

tlsnc.c

+204
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*
2+
* This file is in the public domain. If this is not possible in your region,
3+
* please refer to the UNLICENSE which should be included with the software.
4+
* Author: Ben Fuller
5+
* Upstream: https://git.bvnf.space/bnetkit/
6+
*
7+
* Basic TLS-enabled netcat-like utility to create a connection on the specified
8+
* address and port, using stdin and stdout.
9+
*
10+
* Needs libtls.
11+
*
12+
*/
13+
#include <stdio.h>
14+
#include <errno.h>
15+
#include <poll.h>
16+
#include <sys/socket.h>
17+
#include <sys/types.h>
18+
#include <stdlib.h>
19+
#include <string.h>
20+
#include <unistd.h>
21+
#include <netdb.h>
22+
#include <tls.h>
23+
24+
#define BUF_LEN 1024
25+
26+
int sock_write(struct tls *ctx, char *msg, size_t len);
27+
int sock_read(struct tls *ctx);
28+
29+
int server_connect(char *argv0, char *nodename, char *servname) {
30+
int sfd = -1;
31+
struct addrinfo hints, *result, *rp;
32+
memset(&hints, 0, sizeof hints);
33+
hints.ai_family = AF_UNSPEC;
34+
hints.ai_socktype = SOCK_STREAM;
35+
hints.ai_flags = AI_PASSIVE;
36+
hints.ai_protocol = 0;
37+
38+
int s = getaddrinfo(nodename, servname, &hints, &result);
39+
if (s != 0) {
40+
fprintf(stderr, "%s: getaddrinfo: %s\n", argv0, gai_strerror(s));
41+
return -1;
42+
}
43+
44+
for (rp = result; rp != NULL; rp = rp->ai_next) {
45+
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
46+
if (sfd == -1)
47+
continue;
48+
49+
if (connect(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
50+
break;
51+
52+
if (close(sfd) == -1) {
53+
perror("close");
54+
freeaddrinfo(result);
55+
return -1;
56+
}
57+
}
58+
59+
freeaddrinfo(result);
60+
61+
if (rp == NULL) {
62+
fprintf(stderr, "%s: %s:%s: connection refused\n", argv0, nodename, servname);
63+
return -1;
64+
}
65+
66+
return sfd;
67+
}
68+
69+
int main(int argc, char **argv) {
70+
int timeout = 5 * 1000; /* 5 seconds */
71+
if (argc < 3) {
72+
fprintf(stderr, "usage: %s host port\n", argv[0]);
73+
return 1;
74+
}
75+
76+
struct tls_config *cfg = tls_config_new();
77+
const char *def_ca_file = tls_default_ca_cert_file();
78+
tls_config_set_ca_file(cfg, def_ca_file);
79+
tls_config_insecure_noverifycert(cfg);
80+
struct tls *ctx = tls_client();
81+
if (ctx == NULL) {
82+
fprintf(stderr, "tls client creation failed\n");
83+
tls_config_free(cfg);
84+
return 1;
85+
}
86+
if (tls_configure(ctx, cfg) == -1) {
87+
fprintf(stderr, "tls_configure: %s\n", tls_error(ctx));
88+
tls_config_free(cfg);
89+
tls_free(ctx);
90+
return 1;
91+
}
92+
tls_config_free(cfg);
93+
94+
int sfd = server_connect(argv[0], argv[1], argv[2]);
95+
if (sfd == -1)
96+
return 1;
97+
if (tls_connect_socket(ctx, sfd, argv[1]) == -1) {
98+
fprintf(stderr, "tls_connect_socket: %s\n", tls_error(ctx));
99+
return 1;
100+
}
101+
102+
int pollret;
103+
struct pollfd fds[2];
104+
fds[0].fd = 0;
105+
fds[0].events = POLLIN;
106+
fds[1].fd = sfd;
107+
fds[1].events = POLLIN;
108+
109+
char *line = NULL;
110+
size_t linelen = 0;
111+
112+
while (1) {
113+
fds[0].revents = 0;
114+
fds[1].revents = 0;
115+
errno = 0;
116+
pollret = poll(fds, 2, timeout);
117+
if (pollret < 0) {
118+
if (errno == EAGAIN)
119+
continue;
120+
perror("poll");
121+
free(line);
122+
return 1;
123+
} else if (pollret == 0) {
124+
/* timeout */
125+
fprintf(stderr, "%s: %s:%s: timeout\r\n", argv[0], argv[1], argv[2]);
126+
free(line);
127+
return 1;
128+
}
129+
if (fds[0].revents) {
130+
ssize_t n = getline(&line, &linelen, stdin);
131+
if (n == -1) {
132+
/* send EOF to server */
133+
//if (shutdown(sfd, SHUT_WR) == -1)
134+
//perror("shutdown");
135+
136+
/* prevent poll from checking stdin all the time */
137+
fds[0].fd = -1;
138+
continue;
139+
}
140+
ssize_t ret = tls_write(ctx, line, (size_t)n);
141+
if (ret == -1) {
142+
fprintf(stderr, "sock_write: %s\n", tls_error(ctx));
143+
tls_free(ctx);
144+
free(line);
145+
return 1;
146+
} else if (ret == TLS_WANT_POLLIN)
147+
fds[1].events = POLLIN;
148+
else if (ret == TLS_WANT_POLLOUT)
149+
fds[1].events = POLLOUT;
150+
}
151+
if (fds[1].revents) {
152+
char buff[BUF_LEN] = {'\0'};
153+
ssize_t ret = tls_read(ctx, buff, BUF_LEN);
154+
155+
if (ret == -1) {
156+
fprintf(stderr, "tls_read: %s\n", tls_error(ctx));
157+
free(line);
158+
return 1;
159+
} else if (ret == TLS_WANT_POLLIN)
160+
fds[1].events = POLLIN;
161+
else if (ret == TLS_WANT_POLLOUT)
162+
fds[1].events = POLLOUT;
163+
else if (ret == 0) /* received EOF */
164+
break;
165+
else {
166+
write(1, buff, ret);
167+
}
168+
}
169+
}
170+
171+
free(line);
172+
173+
if (tls_close(ctx) == -1)
174+
fprintf(stderr, "tls_close: %s\n", tls_error(ctx));
175+
tls_free(ctx);
176+
if (close(sfd) == -1) {
177+
perror("close");
178+
return 1;
179+
}
180+
return 0;
181+
}
182+
183+
int sock_write(struct tls *ctx, char *msg, size_t len) {
184+
ssize_t ret = tls_write(ctx, msg, len);
185+
if (ret != (ssize_t) len) {
186+
fprintf(stderr, "sock_write: %s\n", tls_error(ctx));
187+
return 1;
188+
}
189+
return 0;
190+
}
191+
192+
int sock_read(struct tls *ctx) {
193+
char buff[BUF_LEN] = {'\0'};
194+
ssize_t ret = tls_read(ctx, buff, BUF_LEN);
195+
196+
if (ret < 0) {
197+
fprintf(stderr, "sock_read: %s\n", tls_error(ctx));
198+
return -1;
199+
}
200+
if (ret == 0)
201+
return 0;
202+
write(1, buff, ret);
203+
return 1;
204+
}

0 commit comments

Comments
 (0)