/*
ucspi/cmd/tlsc -- UCSPI TLS server
-Copyright (C) 2021 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2021-2022 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
"crypto/x509"
"flag"
"fmt"
+ "io"
"log"
"os"
"os/exec"
cfg.ClientAuth = tls.RequireAndVerifyClientCert
}
- conn := &ucspi.Conn{R: os.Stdin, W: os.Stdout}
+ conn, _ := ucspi.NewConn(os.Stdin, os.Stdout)
tlsConn := tls.Server(conn, cfg)
if err = tlsConn.Handshake(); err != nil {
log.Fatalln(err)
dn = tlsConn.ConnectionState().PeerCertificates[0].Subject.String()
}
+ rr, rw, err := os.Pipe()
+ if err != nil {
+ log.Fatalln(err)
+ }
+ wr, ww, err := os.Pipe()
+ if err != nil {
+ log.Fatalln(err)
+ }
args := flag.Args()
cmd := exec.Command(args[0], args[1:]...)
- cmd.Stdin = tlsConn
- cmd.Stdout = tlsConn
+ cmd.Stdin = rr
+ cmd.Stdout = ww
cmd.Stderr = os.Stderr
cmd.Env = append(os.Environ(), "PROTO=TLS")
if dn != "" {
if err = cmd.Start(); err != nil {
log.Fatalln(err)
}
- if _, err = cmd.Process.Wait(); err != nil {
+ worker := make(chan struct{})
+ go func() {
+ io.Copy(rw, tlsConn)
+ rw.Close()
+ }()
+ go func() {
+ io.Copy(tlsConn, wr)
+ tlsConn.Close()
+ close(worker)
+ }()
+ err = cmd.Wait()
+ ww.Close()
+ <-worker
+ if err != nil {
log.Fatalln(err)
}
}