-
Notifications
You must be signed in to change notification settings - Fork 154
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
End to end tests are now executed in the folowing modes: - `default`: pion client, pion server - `openssl_client`: openssl client, pion server - `openssl_server`: pion client, openssl server OpenSSL is launched using `exec.Command`
- Loading branch information
1 parent
34ebfdb
commit 10db9a6
Showing
4 changed files
with
435 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
package e2e | ||
|
||
import ( | ||
"crypto/x509" | ||
"encoding/pem" | ||
"errors" | ||
"fmt" | ||
"io/ioutil" | ||
"net" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
"time" | ||
|
||
"github.com/pion/dtls/v2" | ||
) | ||
|
||
func (c *comm) serverOpenSSL() { | ||
go func() { | ||
c.serverMutex.Lock() | ||
defer c.serverMutex.Unlock() | ||
|
||
cfg := c.serverConfig | ||
|
||
// create openssl arguments | ||
args := []string{"s_server", | ||
"-dtls1_2", | ||
"-quiet", | ||
fmt.Sprintf("-accept=%d", c.serverPort), | ||
} | ||
ciphers := ciphersOpenSSL(cfg) | ||
if ciphers != "" { | ||
args = append(args, fmt.Sprintf("-cipher=%s", ciphers)) | ||
} | ||
|
||
// psk arguments | ||
if cfg.PSK != nil { | ||
psk, err := cfg.PSK(nil) | ||
if err != nil { | ||
c.errChan <- err | ||
return | ||
} | ||
args = append(args, fmt.Sprintf("-psk=%X", psk)) | ||
if len(cfg.PSKIdentityHint) > 0 { | ||
args = append(args, fmt.Sprintf("-psk_hint=%s", cfg.PSKIdentityHint)) | ||
} | ||
} | ||
|
||
// certs arguments | ||
if len(cfg.Certificates) > 0 { | ||
// create temporary cert files | ||
certPEM, keyPEM, err := writeTempPEM(cfg) | ||
if err != nil { | ||
c.errChan <- err | ||
return | ||
} | ||
args = append(args, | ||
fmt.Sprintf("-cert=%s", certPEM), | ||
fmt.Sprintf("-key=%s", keyPEM)) | ||
defer func() { | ||
_ = os.Remove(certPEM) | ||
_ = os.Remove(keyPEM) | ||
}() | ||
} else { | ||
args = append(args, "-nocert") | ||
} | ||
|
||
// launch command | ||
// #nosec G204 | ||
cmd := exec.CommandContext(c.ctx, "openssl", args...) | ||
var inner net.Conn | ||
inner, c.serverConn = net.Pipe() | ||
cmd.Stdin = inner | ||
cmd.Stdout = inner | ||
cmd.Stderr = os.Stderr | ||
if err := cmd.Start(); err != nil { | ||
c.errChan <- err | ||
_ = inner.Close() | ||
return | ||
} | ||
|
||
c.serverReady <- struct{}{} | ||
simpleReadWrite(c.errChan, c.serverChan, c.serverConn, c.messageRecvCount) | ||
}() | ||
} | ||
|
||
func (c *comm) clientOpenSSL() { | ||
select { | ||
case <-c.serverReady: | ||
// OK | ||
case <-time.After(time.Second): | ||
c.errChan <- errors.New("waiting on serverReady err: timeout") | ||
} | ||
|
||
c.clientMutex.Lock() | ||
defer c.clientMutex.Unlock() | ||
|
||
cfg := c.clientConfig | ||
|
||
// create openssl arguments | ||
args := []string{"s_client", | ||
"-dtls1_2", | ||
"-quiet", | ||
fmt.Sprintf("-connect=localhost:%d", c.serverPort), | ||
} | ||
ciphers := ciphersOpenSSL(cfg) | ||
if ciphers != "" { | ||
args = append(args, fmt.Sprintf("-cipher=%s", ciphers)) | ||
} | ||
|
||
// psk arguments | ||
if cfg.PSK != nil { | ||
psk, err := cfg.PSK(nil) | ||
if err != nil { | ||
c.errChan <- err | ||
return | ||
} | ||
args = append(args, fmt.Sprintf("-psk=%X", psk)) | ||
} | ||
|
||
// certificate arguments | ||
if len(cfg.Certificates) > 0 { | ||
// create temporary cert files | ||
certPEM, keyPEM, err := writeTempPEM(cfg) | ||
if err != nil { | ||
c.errChan <- err | ||
return | ||
} | ||
fmt.Println(certPEM, keyPEM) | ||
args = append(args, fmt.Sprintf("-CAfile=%s", certPEM)) | ||
defer func() { | ||
_ = os.Remove(certPEM) | ||
_ = os.Remove(keyPEM) | ||
}() | ||
} | ||
|
||
// launch command | ||
// #nosec G204 | ||
cmd := exec.CommandContext(c.ctx, "openssl", args...) | ||
var inner net.Conn | ||
inner, c.clientConn = net.Pipe() | ||
cmd.Stdin = inner | ||
cmd.Stdout = inner | ||
cmd.Stderr = os.Stderr | ||
if err := cmd.Start(); err != nil { | ||
c.errChan <- err | ||
_ = inner.Close() | ||
return | ||
} | ||
|
||
simpleReadWrite(c.errChan, c.clientChan, c.clientConn, c.messageRecvCount) | ||
} | ||
|
||
func ciphersOpenSSL(cfg *dtls.Config) string { | ||
// See https://tls.mbed.org/supported-ssl-ciphersuites | ||
translate := map[dtls.CipherSuiteID]string{ | ||
dtls.TLS_ECDHE_ECDSA_WITH_AES_128_CCM: "ECDHE-ECDSA-AES128-CCM", | ||
dtls.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: "ECDHE-ECDSA-AES128-CCM8", | ||
dtls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "ECDHE-ECDSA-AES128-GCM-SHA256", | ||
dtls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "ECDHE-RSA-AES128-GCM-SHA256", | ||
|
||
dtls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "ECDHE-ECDSA-AES256-SHA", | ||
dtls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "ECDHE-RSA-AES128-SHA", | ||
|
||
dtls.TLS_PSK_WITH_AES_128_CCM: "PSK-AES128-CCM", | ||
dtls.TLS_PSK_WITH_AES_128_CCM_8: "PSK-AES128-CCM8", | ||
dtls.TLS_PSK_WITH_AES_128_GCM_SHA256: "PSK-AES128-GCM-SHA256", | ||
} | ||
|
||
var ciphers []string | ||
for _, c := range cfg.CipherSuites { | ||
if text, ok := translate[c]; ok { | ||
ciphers = append(ciphers, text) | ||
} | ||
} | ||
return strings.Join(ciphers, ";") | ||
} | ||
|
||
func writeTempPEM(cfg *dtls.Config) (string, string, error) { | ||
certOut, err := ioutil.TempFile("", "cert.pem") | ||
if err != nil { | ||
return "", "", fmt.Errorf("failed to create temporary file: %w", err) | ||
} | ||
keyOut, err := ioutil.TempFile("", "key.pem") | ||
if err != nil { | ||
return "", "", fmt.Errorf("failed to create temporary file: %w", err) | ||
} | ||
|
||
cert := cfg.Certificates[0] | ||
derBytes := cert.Certificate[0] | ||
if err = pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil { | ||
return "", "", fmt.Errorf("failed to write data to cert.pem: %w", err) | ||
} | ||
if err = certOut.Close(); err != nil { | ||
return "", "", fmt.Errorf("error closing cert.pem: %w", err) | ||
} | ||
|
||
priv := cert.PrivateKey | ||
var privBytes []byte | ||
privBytes, err = x509.MarshalPKCS8PrivateKey(priv) | ||
if err != nil { | ||
return "", "", fmt.Errorf("unable to marshal private key: %w", err) | ||
} | ||
if err = pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil { | ||
return "", "", fmt.Errorf("failed to write data to key.pem: %w", err) | ||
} | ||
if err = keyOut.Close(); err != nil { | ||
return "", "", fmt.Errorf("error closing key.pem: %w", err) | ||
} | ||
return certOut.Name(), keyOut.Name(), nil | ||
} |
Oops, something went wrong.