Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ jobs:
key: plan9port-${{ runner.os }}-v1
- name: Add plan9port to PATH
run: echo "$PLAN9/bin" >> $GITHUB_PATH
- name: Install OpenSSL
run: sudo apt-get install -y libssl-dev pkg-config
- name: Run tests
run: mk test

Expand All @@ -61,6 +63,8 @@ jobs:
key: plan9port-${{ runner.os }}-v1
- name: Add plan9port to PATH
run: echo "$PLAN9/bin" >> $GITHUB_PATH
- name: Install OpenSSL
run: sudo apt-get install -y libssl-dev pkg-config
- name: Build o.thread
run: mk o.thread

Expand Down
4 changes: 2 additions & 2 deletions mkfile
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ runtest:V: $O.test
./$O.test

$O.thread: $THREADOFILES $LIB
$LD $LDFLAGS -o $target $prereq
$LD -o $target $prereq $LDFLAGS

$TESTOFILES: $TESTHFILES
$O.test: $TESTOFILES $LIB
$LD $LDFLAGS -o $target $prereq
$LD -o $target $prereq $LDFLAGS
4 changes: 3 additions & 1 deletion opt.rc
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#!/bin/rc

if(! ~ $#PLAN9 0) {
# plan9port
echo '<$PLAN9/src/mkhdr'
echo 'MKONE=$PLAN9/src/mkone'
echo 'TLSFILE=tlsp9p'
echo 'BIN=$PLAN9/bin'
# OpenSSL for tlsp9p.c
echo 'CFLAGS=' `{pkg-config --cflags-only-I openssl}
echo 'LDFLAGS=' `{pkg-config --libs openssl}
}
if not {
echo '</$objtype/mkfile'
Expand Down
158 changes: 142 additions & 16 deletions tlsp9p.c
Original file line number Diff line number Diff line change
@@ -1,38 +1,164 @@
#include <u.h>
#include <sys/socket.h> /* before libc.h to avoid accept/listen macro conflicts */
#include <libc.h>
#include <mp.h>
#include <libsec.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "dat.h"
#include "fns.h"

int
static int
istrusted(uchar* cert, int certlen)
{
uchar digest[SHA1dlen];
Thumbprint* table;

fmtinstall('H', encodefmt);
if(cert == nil || certlen <= 0){
werrstr("server did not provide TLS certificate");
return 0;
}
sha1(cert, certlen, digest, nil);
table = initThumbprints(unsharp("#9/lib/tls/rdp"), unsharp("#9/lib/tls/rdp.exclude"));
if(!table || !okThumbprint(digest, table)){
werrstr("server certificate not recognized");
fprint(2, "verify server certificate %.*H\n", SHA1dlen, digest);
fprint(2, "add thumbprint after verification:\n");
fprint(2, "\techo 'x509 sha1=%.*H' >> $PLAN9/lib/tls/rdp\n", SHA1dlen, digest);
return 0;
}
freeThumbprints(table);
return 1;
}

/* lifted from /sys/src/cmd/upas/fs/imap4.c:/^starttls */
static int
checkpeer(SSL* s)
{
X509* peercrt;
uchar* cert;
int certlen, ok;

peercrt = SSL_get_peer_certificate(s);
cert = nil;
certlen = 0;
if(peercrt != nil)
certlen = i2d_X509(peercrt, &cert);
X509_free(peercrt);
ok = istrusted(cert, certlen);
OPENSSL_free(cert);
return ok;
}

static void
readtls(int pipefd, SSL* s)
{
char buf[16384];
int n;

for(;;){
n = SSL_read(s, buf, sizeof buf);
if(n <= 0)
break;
if(write(pipefd, buf, n) != n)
break;
}
SSL_shutdown(s);
SSL_free(s);
close(pipefd);
_exits(nil);
}

static void
readlocal(int pipefd, SSL* s)
{
char buf[16384];
int n;

for(;;){
n = read(pipefd, buf, sizeof buf);
if(n <= 0)
break;
if(SSL_write(s, buf, n) <= 0)
break;
}
SSL_free(s);
close(pipefd);
_exits(nil);
}

int
starttls(Rdp* r)
{
TLSconn c;
int fd, sfd;
SSL_CTX* ctx;
SSL* s;
int p[2];
static int inited;

if(!inited){
SSL_library_init();
SSL_load_error_strings();
inited = 1;
}

fd = r->fd;
ctx = SSL_CTX_new(TLS_client_method());
if(ctx == nil)
goto ErrCtx;
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nil);
s = SSL_new(ctx);
SSL_CTX_free(ctx);
if(s == nil)
goto ErrNew;
if(SSL_set_fd(s, r->fd) != 1 || SSL_connect(s) != 1)
goto ErrConnect;
fprint(2, "tls: %s %s\n", SSL_get_version(s), SSL_get_cipher(s));

memset(&c, 0, sizeof c);
sfd = tlsClient(fd, &c);
if(sfd < 0){
werrstr("tlsClient: %r");
return -1;
if(!checkpeer(s))
goto ErrCert;

if(socketpair(AF_UNIX, SOCK_STREAM, 0, p) < 0)
goto ErrSocket;
switch(fork()){
case -1:
goto ErrFork;
case 0:
close(p[1]);
readtls(p[0], s);
}
if(!istrusted(c.cert, c.certlen)){
close(sfd);
return -1;
switch(fork()){
case -1:
goto ErrFork;
case 0:
close(p[1]);
readlocal(p[0], s);
}
/* BUG: free c.cert? */

close(r->fd);
r->fd = sfd;
return sfd;
close(p[0]);
r->fd = p[1];
return p[1];

ErrFork:
werrstr("fork: %r");
close(p[0]);
close(p[1]);
SSL_free(s);
return -1;
ErrSocket:
werrstr("socketpair: %r");
SSL_free(s);
return -1;
ErrCert:
SSL_free(s);
return -1;
ErrConnect:
werrstr("SSL: %s", ERR_reason_error_string(ERR_get_error()));
SSL_free(s);
return -1;
ErrNew:
werrstr("SSL_new failed");
return -1;
ErrCtx:
werrstr("SSL_CTX_new: %s", ERR_reason_error_string(ERR_get_error()));
return -1;
}
Loading