Skip to content

Commit

Permalink
Merge branch 'LizardByte:nightly' into nightly
Browse files Browse the repository at this point in the history
  • Loading branch information
xanderfrangos committed Jan 20, 2024
2 parents b8f8b46 + a10ec3a commit 2511bd0
Show file tree
Hide file tree
Showing 14 changed files with 407 additions and 97 deletions.
27 changes: 24 additions & 3 deletions DOCKER_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ Create and run the container (substitute your `<values>`):

```bash
docker run -d \
--device /dev/dri/ \
--name=<image_name> \
--restart=unless-stopped
--restart=unless-stopped \
-e PUID=<uid> \
-e PGID=<gid> \
-e TZ=<timezone> \
Expand Down Expand Up @@ -86,6 +87,25 @@ services:
- "47998-48000:47998-48000/udp"
```
### Using podman run
Create and run the container (substitute your `<values>`):

```bash
podman run -d \
--device /dev/dri/ \
--name=<image_name> \
--restart=unless-stopped \
--userns=keep-id \
-e PUID=<uid> \
-e PGID=<gid> \
-e TZ=<timezone> \
-v <path to data>:/config \
-p 47984-47990:47984-47990/tcp \
-p 48010:48010 \
-p 47998-48000:47998-48000/udp \
<image>
```

### Parameters
You must substitute the `<values>` with your own settings.

Expand Down Expand Up @@ -132,8 +152,9 @@ The architectures supported by these images are shown in the table below.
| tag suffix | amd64/x86_64 | arm64/aarch64 |
|-----------------|--------------|---------------|
| archlinux | ✅ | ❌ |
| debian-bookworm | ✅ | ✅ |
| debian-bullseye | ✅ | ✅ |
| fedora-36 | ✅ | ✅ |
| fedora-37 | ✅ | ✅ |
| fedora-38 | ✅ | ✅ |
| fedora-39 | ✅ | ✅ |
| ubuntu-20.04 | ✅ | ✅ |
| ubuntu-22.04 | ✅ | ✅ |
58 changes: 58 additions & 0 deletions docs/source/about/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,64 @@ keybindings
external_ip = 123.456.789.12
`lan_encryption_mode <https://localhost:47990/config/#lan_encryption_mode>`__
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

**Description**
This determines when encryption will be used when streaming over your local network.

.. warning:: Encryption can reduce streaming performance, particularly on less powerful hosts and clients.

**Choices**

.. table::
:widths: auto

===== ===========
Value Description
===== ===========
0 encryption will not be used
1 encryption will be used if the client supports it
2 encryption is mandatory and unencrypted connections are rejected
===== ===========

**Default**
``0``

**Example**
.. code-block:: text
lan_encryption_mode = 0
`wan_encryption_mode <https://localhost:47990/config/#wan_encryption_mode>`__
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

**Description**
This determines when encryption will be used when streaming over the Internet.

.. warning:: Encryption can reduce streaming performance, particularly on less powerful hosts and clients.

**Choices**

.. table::
:widths: auto

===== ===========
Value Description
===== ===========
0 encryption will not be used
1 encryption will be used if the client supports it
2 encryption is mandatory and unencrypted connections are rejected
===== ===========

**Default**
``1``

**Example**
.. code-block:: text
wan_encryption_mode = 1
`ping_timeout <https://localhost:47990/config/#ping_timeout>`__
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
8 changes: 7 additions & 1 deletion src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,10 @@ namespace config {
APPS_JSON_PATH,

20, // fecPercentage
1 // channels
1, // channels

ENCRYPTION_MODE_NEVER, // lan_encryption_mode
ENCRYPTION_MODE_OPPORTUNISTIC, // wan_encryption_mode
};

nvhttp_t nvhttp {
Expand Down Expand Up @@ -1016,6 +1019,9 @@ namespace config {

int_between_f(vars, "channels", stream.channels, { 1, std::numeric_limits<int>::max() });

int_between_f(vars, "lan_encryption_mode", stream.lan_encryption_mode, { 0, 2 });
int_between_f(vars, "wan_encryption_mode", stream.wan_encryption_mode, { 0, 2 });

path_f(vars, "file_apps", stream.file_apps);
int_between_f(vars, "fec_percentage", stream.fec_percentage, { 1, 255 });

Expand Down
8 changes: 8 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ namespace config {
bool install_steam_drivers;
};

constexpr int ENCRYPTION_MODE_NEVER = 0; // Never use video encryption, even if the client supports it
constexpr int ENCRYPTION_MODE_OPPORTUNISTIC = 1; // Use video encryption if available, but stream without it if not supported
constexpr int ENCRYPTION_MODE_MANDATORY = 2; // Always use video encryption and refuse clients that can't encrypt

struct stream_t {
std::chrono::milliseconds ping_timeout;

Expand All @@ -85,6 +89,10 @@ namespace config {

// max unique instances of video and audio streams
int channels;

// Video encryption settings for LAN and WAN streams
int lan_encryption_mode;
int wan_encryption_mode;
};

struct nvhttp_t {
Expand Down
59 changes: 26 additions & 33 deletions src/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,23 +152,23 @@ namespace crypto {
auto cipher = tagged_cipher.substr(tag_size);
auto tag = tagged_cipher.substr(0, tag_size);

plaintext.resize((cipher.size() + 15) / 16 * 16);
plaintext.resize(round_to_pkcs7_padded(cipher.size()));

int size;
if (EVP_DecryptUpdate(decrypt_ctx.get(), plaintext.data(), &size, (const std::uint8_t *) cipher.data(), cipher.size()) != 1) {
int update_outlen, final_outlen;

if (EVP_DecryptUpdate(decrypt_ctx.get(), plaintext.data(), &update_outlen, (const std::uint8_t *) cipher.data(), cipher.size()) != 1) {
return -1;
}

if (EVP_CIPHER_CTX_ctrl(decrypt_ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(), const_cast<char *>(tag.data())) != 1) {
return -1;
}

int len = size;
if (EVP_DecryptFinal_ex(decrypt_ctx.get(), plaintext.data() + size, &len) != 1) {
if (EVP_DecryptFinal_ex(decrypt_ctx.get(), plaintext.data() + update_outlen, &final_outlen) != 1) {
return -1;
}

plaintext.resize(size + len);
plaintext.resize(update_outlen + final_outlen);
return 0;
}

Expand All @@ -187,30 +187,27 @@ namespace crypto {
auto tag = tagged_cipher;
auto cipher = tag + tag_size;

int len;
int size = round_to_pkcs7_padded(plaintext.size());
int update_outlen, final_outlen;

// Encrypt into the caller's buffer
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher, &size, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher, &update_outlen, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
return -1;
}

// GCM encryption won't ever fill ciphertext here but we have to call it anyway
if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher + size, &len) != 1) {
if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher + update_outlen, &final_outlen) != 1) {
return -1;
}

if (EVP_CIPHER_CTX_ctrl(encrypt_ctx.get(), EVP_CTRL_GCM_GET_TAG, tag_size, tag) != 1) {
return -1;
}

return len + size;
return update_outlen + final_outlen;
}

int
ecb_t::decrypt(const std::string_view &cipher, std::vector<std::uint8_t> &plaintext) {
int len;

auto fg = util::fail_guard([this]() {
EVP_CIPHER_CTX_reset(decrypt_ctx.get());
});
Expand All @@ -221,19 +218,19 @@ namespace crypto {
}

EVP_CIPHER_CTX_set_padding(decrypt_ctx.get(), padding);
plaintext.resize(round_to_pkcs7_padded(cipher.size()));

int update_outlen, final_outlen;

plaintext.resize((cipher.size() + 15) / 16 * 16);
auto size = (int) plaintext.size();
// Decrypt into the caller's buffer, leaving room for the auth tag to be prepended
if (EVP_DecryptUpdate(decrypt_ctx.get(), plaintext.data(), &size, (const std::uint8_t *) cipher.data(), cipher.size()) != 1) {
if (EVP_DecryptUpdate(decrypt_ctx.get(), plaintext.data(), &update_outlen, (const std::uint8_t *) cipher.data(), cipher.size()) != 1) {
return -1;
}

if (EVP_DecryptFinal_ex(decrypt_ctx.get(), plaintext.data(), &len) != 1) {
if (EVP_DecryptFinal_ex(decrypt_ctx.get(), plaintext.data() + update_outlen, &final_outlen) != 1) {
return -1;
}

plaintext.resize(len + size);
plaintext.resize(update_outlen + final_outlen);
return 0;
}

Expand All @@ -249,22 +246,20 @@ namespace crypto {
}

EVP_CIPHER_CTX_set_padding(encrypt_ctx.get(), padding);
cipher.resize(round_to_pkcs7_padded(plaintext.size()));

int len;

cipher.resize((plaintext.size() + 15) / 16 * 16);
auto size = (int) cipher.size();
int update_outlen, final_outlen;

// Encrypt into the caller's buffer
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher.data(), &size, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher.data(), &update_outlen, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
return -1;
}

if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher.data() + size, &len) != 1) {
if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher.data() + update_outlen, &final_outlen) != 1) {
return -1;
}

cipher.resize(len + size);
cipher.resize(update_outlen + final_outlen);
return 0;
}

Expand All @@ -280,20 +275,18 @@ namespace crypto {
return false;
}

int len;

int size = plaintext.size(); // round_to_pkcs7_padded(plaintext.size());
int update_outlen, final_outlen;

// Encrypt into the caller's buffer
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher, &size, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
if (EVP_EncryptUpdate(encrypt_ctx.get(), cipher, &update_outlen, (const std::uint8_t *) plaintext.data(), plaintext.size()) != 1) {
return -1;
}

if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher + size, &len) != 1) {
if (EVP_EncryptFinal_ex(encrypt_ctx.get(), cipher + update_outlen, &final_outlen) != 1) {
return -1;
}

return size + len;
return update_outlen + final_outlen;
}

ecb_t::ecb_t(const aes_t &key, bool padding):
Expand All @@ -309,7 +302,7 @@ namespace crypto {

aes_t
gen_aes_key(const std::array<uint8_t, 16> &salt, const std::string_view &pin) {
aes_t key;
aes_t key(16);

std::string salt_pin;
salt_pin.reserve(salt.size() + pin.size());
Expand Down
2 changes: 1 addition & 1 deletion src/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace crypto {

using sha256_t = std::array<std::uint8_t, SHA256_DIGEST_LENGTH>;

using aes_t = std::array<std::uint8_t, 16>;
using aes_t = std::vector<std::uint8_t>;
using x509_t = util::safe_ptr<X509, X509_free>;
using x509_store_t = util::safe_ptr<X509_STORE, X509_STORE_free>;
using x509_store_ctx_t = util::safe_ptr<X509_STORE_CTX, X509_STORE_CTX_free>;
Expand Down
2 changes: 1 addition & 1 deletion src/network.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace net {

net_e
from_address(const std::string_view &view) {
auto addr = ip::make_address(view);
auto addr = normalize_address(ip::make_address(view));

if (addr.is_v6()) {
for (auto &range : pc_ips_v6) {
Expand Down
9 changes: 9 additions & 0 deletions src/network.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ namespace net {
std::string_view
af_to_any_address_string(af_e af);

/**
* @brief Converts an address to a normalized form.
* @details Normalization converts IPv4-mapped IPv6 addresses into IPv4 addresses.
* @param address The address to normalize.
* @return Normalized address.
*/
boost::asio::ip::address
normalize_address(boost::asio::ip::address address);

/**
* @brief Returns the given address in normalized string form.
* @details Normalization converts IPv4-mapped IPv6 addresses into IPv4 addresses.
Expand Down
9 changes: 5 additions & 4 deletions src/nvhttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,10 @@ namespace nvhttp {
make_launch_session(bool host_audio, const args_t &args) {
rtsp_stream::launch_session_t launch_session;

auto rikey = util::from_hex_vec(get_arg(args, "rikey"), true);
std::copy(rikey.cbegin(), rikey.cend(), std::back_inserter(launch_session.gcm_key));

launch_session.host_audio = host_audio;
launch_session.gcm_key = util::from_hex<crypto::aes_t>(get_arg(args, "rikey"), true);
std::stringstream mode = std::stringstream(get_arg(args, "mode", "0x0x0"));
// Split mode by the char "x", to populate width/height/fps
int x = 0;
Expand All @@ -324,11 +326,10 @@ namespace nvhttp {
launch_session.av_ping_payload = util::hex_vec(raw_payload);
RAND_bytes((unsigned char *) &launch_session.control_connect_data, sizeof(launch_session.control_connect_data));

launch_session.iv.resize(16);
uint32_t prepend_iv = util::endian::big<uint32_t>(util::from_view(get_arg(args, "rikeyid")));
auto prepend_iv_p = (uint8_t *) &prepend_iv;

auto next = std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv));
std::fill(next, std::end(launch_session.iv), 0);
std::copy(prepend_iv_p, prepend_iv_p + sizeof(prepend_iv), std::begin(launch_session.iv));
return launch_session;
}

Expand Down
18 changes: 14 additions & 4 deletions src/platform/linux/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,22 @@ namespace platf {

fs::path
appdata() {
const char *homedir;
if ((homedir = getenv("HOME")) == nullptr) {
homedir = getpwuid(geteuid())->pw_dir;
const char *dir;

// May be set if running under a systemd service with the ConfigurationDirectory= option set.
if ((dir = getenv("CONFIGURATION_DIRECTORY")) != nullptr) {
return fs::path { dir } / "sunshine"sv;
}
// Otherwise, follow the XDG base directory specification:
// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
if ((dir = getenv("XDG_CONFIG_HOME")) != nullptr) {
return fs::path { dir } / "sunshine"sv;
}
if ((dir = getenv("HOME")) == nullptr) {
dir = getpwuid(geteuid())->pw_dir;
}

return fs::path { homedir } / ".config/sunshine"sv;
return fs::path { dir } / ".config/sunshine"sv;
}

std::string
Expand Down
Loading

0 comments on commit 2511bd0

Please sign in to comment.