mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
module-raop: Use new openssl methods
Fix Digest, we need to use the method to generate a new Digest for each request. Use newer openssl methods instead of deprecated ones. The RSA sign still need to be ported.
This commit is contained in:
parent
98222ab2ae
commit
9a4a4fe9c4
1 changed files with 173 additions and 139 deletions
|
|
@ -20,6 +20,7 @@
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
|
#include <openssl/core_names.h>
|
||||||
#include <openssl/engine.h>
|
#include <openssl/engine.h>
|
||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
|
|
@ -210,12 +211,15 @@ struct impl {
|
||||||
|
|
||||||
char session_id[32];
|
char session_id[32];
|
||||||
char *password;
|
char *password;
|
||||||
|
char *auth_method;
|
||||||
|
char *realm;
|
||||||
|
char *nonce;
|
||||||
|
|
||||||
unsigned int do_disconnect:1;
|
unsigned int do_disconnect:1;
|
||||||
|
|
||||||
uint8_t key[AES_CHUNK_SIZE]; /* Key for aes-cbc */
|
uint8_t key[AES_CHUNK_SIZE]; /* Key for aes-cbc */
|
||||||
uint8_t iv[AES_CHUNK_SIZE]; /* Initialization vector for cbc */
|
uint8_t iv[AES_CHUNK_SIZE]; /* Initialization vector for cbc */
|
||||||
AES_KEY aes; /* AES encryption */
|
EVP_CIPHER_CTX *ctx;
|
||||||
|
|
||||||
uint16_t control_port;
|
uint16_t control_port;
|
||||||
int control_fd;
|
int control_fd;
|
||||||
|
|
@ -269,21 +273,10 @@ static inline void bit_writer(uint8_t **p, int *pos, uint8_t data, int len)
|
||||||
|
|
||||||
static int aes_encrypt(struct impl *impl, uint8_t *data, int len)
|
static int aes_encrypt(struct impl *impl, uint8_t *data, int len)
|
||||||
{
|
{
|
||||||
uint8_t nv[AES_CHUNK_SIZE];
|
int i = len & ~0xf, clen = i;
|
||||||
uint8_t *buffer;
|
EVP_EncryptInit(impl->ctx, EVP_aes_128_cbc(), impl->key, impl->iv);
|
||||||
int i, j;
|
EVP_EncryptUpdate(impl->ctx, data, &clen, data, i);
|
||||||
|
return i;
|
||||||
memcpy(nv, impl->iv, AES_CHUNK_SIZE);
|
|
||||||
for (i = 0; i + AES_CHUNK_SIZE <= len; i += AES_CHUNK_SIZE) {
|
|
||||||
buffer = data + i;
|
|
||||||
for (j = 0; j < AES_CHUNK_SIZE; j++)
|
|
||||||
buffer[j] ^= nv[j];
|
|
||||||
|
|
||||||
AES_encrypt(buffer, buffer, &impl->aes);
|
|
||||||
|
|
||||||
memcpy(nv, buffer, AES_CHUNK_SIZE);
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64_t timespec_to_ntp(struct timespec *ts)
|
static inline uint64_t timespec_to_ntp(struct timespec *ts)
|
||||||
|
|
@ -706,6 +699,126 @@ on_control_source_io(void *data, int fd, uint32_t mask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void base64_encode(const uint8_t *data, size_t len, char *enc, char pad)
|
||||||
|
{
|
||||||
|
static const char tab[] =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < len; i += 3) {
|
||||||
|
uint32_t v;
|
||||||
|
v = data[i+0] << 16;
|
||||||
|
v |= (i+1 < len ? data[i+1] : 0) << 8;
|
||||||
|
v |= (i+2 < len ? data[i+2] : 0);
|
||||||
|
*enc++ = tab[(v >> (3*6)) & 0x3f];
|
||||||
|
*enc++ = tab[(v >> (2*6)) & 0x3f];
|
||||||
|
*enc++ = i+1 < len ? tab[(v >> (1*6)) & 0x3f] : pad;
|
||||||
|
*enc++ = i+2 < len ? tab[(v >> (0*6)) & 0x3f] : pad;
|
||||||
|
}
|
||||||
|
*enc = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t base64_decode(const char *data, size_t len, uint8_t *dec)
|
||||||
|
{
|
||||||
|
uint8_t tab[] = {
|
||||||
|
62, -1, -1, -1, 63, 52, 53, 54, 55, 56,
|
||||||
|
57, 58, 59, 60, 61, -1, -1, -1, -1, -1,
|
||||||
|
-1, -1, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||||
|
8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||||
|
18, 19, 20, 21, 22, 23, 24, 25, -1, -1,
|
||||||
|
-1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
|
||||||
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
||||||
|
42, 43, 44, 45, 46, 47, 48, 49, 50, 51 };
|
||||||
|
size_t i, j;
|
||||||
|
for (i = 0, j = 0; i < len; i += 4) {
|
||||||
|
uint32_t v;
|
||||||
|
v = tab[data[i+0]-43] << (3*6);
|
||||||
|
v |= tab[data[i+1]-43] << (2*6);
|
||||||
|
v |= (data[i+2] == '=' ? 0 : tab[data[i+2]-43]) << (1*6);
|
||||||
|
v |= (data[i+3] == '=' ? 0 : tab[data[i+3]-43]);
|
||||||
|
dec[j++] = (v >> 16) & 0xff;
|
||||||
|
if (data[i+2] != '=') dec[j++] = (v >> 8) & 0xff;
|
||||||
|
if (data[i+3] != '=') dec[j++] = v & 0xff;
|
||||||
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_PRINTF_FUNC(2,3)
|
||||||
|
static int MD5_hash(char hash[MD5_HASH_LENGTH+1], const char *fmt, ...)
|
||||||
|
{
|
||||||
|
unsigned char d[MD5_DIGEST_LENGTH];
|
||||||
|
int i;
|
||||||
|
va_list args;
|
||||||
|
char buffer[1024];
|
||||||
|
unsigned int size;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
size = MD5_DIGEST_LENGTH;
|
||||||
|
EVP_Digest(buffer, strlen(buffer), d, &size, EVP_md5(), NULL);
|
||||||
|
for (i = 0; i < MD5_DIGEST_LENGTH; i++)
|
||||||
|
sprintf(&hash[2*i], "%02x", (uint8_t) d[i]);
|
||||||
|
hash[MD5_HASH_LENGTH] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtsp_add_auth(struct impl *impl, const char *method)
|
||||||
|
{
|
||||||
|
char auth[1024];
|
||||||
|
|
||||||
|
if (impl->auth_method == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (spa_streq(impl->auth_method, "Basic")) {
|
||||||
|
char buf[256];
|
||||||
|
char enc[512];
|
||||||
|
spa_scnprintf(buf, sizeof(buf), "%s:%s", DEFAULT_USER_NAME, impl->password);
|
||||||
|
base64_encode((uint8_t*)buf, strlen(buf), enc, '=');
|
||||||
|
spa_scnprintf(auth, sizeof(auth), "Basic %s", enc);
|
||||||
|
}
|
||||||
|
else if (spa_streq(impl->auth_method, "Digest")) {
|
||||||
|
const char *url;
|
||||||
|
char h1[MD5_HASH_LENGTH+1];
|
||||||
|
char h2[MD5_HASH_LENGTH+1];
|
||||||
|
char resp[MD5_HASH_LENGTH+1];
|
||||||
|
|
||||||
|
url = pw_rtsp_client_get_url(impl->rtsp);
|
||||||
|
|
||||||
|
MD5_hash(h1, "%s:%s:%s", DEFAULT_USER_NAME, impl->realm, impl->password);
|
||||||
|
MD5_hash(h2, "%s:%s", method, url);
|
||||||
|
MD5_hash(resp, "%s:%s:%s", h1, impl->nonce, h2);
|
||||||
|
|
||||||
|
pw_log_warn("%s:%s", method, url);
|
||||||
|
spa_scnprintf(auth, sizeof(auth),
|
||||||
|
"username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
|
||||||
|
DEFAULT_USER_NAME, impl->realm, impl->nonce, url, resp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
pw_properties_setf(impl->headers, "Authorization", "%s %s",
|
||||||
|
impl->auth_method, auth);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
error:
|
||||||
|
pw_log_error("error adding auth");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rtsp_send(struct impl *impl, const char *method,
|
||||||
|
const char *content_type, const char *content,
|
||||||
|
int (*reply) (void *data, int status, const struct spa_dict *headers))
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
rtsp_add_auth(impl, method);
|
||||||
|
|
||||||
|
res = pw_rtsp_client_send(impl->rtsp, method, &impl->headers->dict,
|
||||||
|
content_type, content, reply, impl);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static int rtsp_flush_reply(void *data, int status, const struct spa_dict *headers)
|
static int rtsp_flush_reply(void *data, int status, const struct spa_dict *headers)
|
||||||
{
|
{
|
||||||
pw_log_info("reply %d", status);
|
pw_log_info("reply %d", status);
|
||||||
|
|
@ -725,8 +838,7 @@ static int rtsp_do_flush(struct impl *impl)
|
||||||
|
|
||||||
impl->recording = false;
|
impl->recording = false;
|
||||||
|
|
||||||
res = pw_rtsp_client_send(impl->rtsp, "FLUSH", &impl->headers->dict,
|
res = rtsp_send(impl, "FLUSH", NULL, NULL, rtsp_flush_reply);
|
||||||
NULL, NULL, rtsp_flush_reply, impl);
|
|
||||||
|
|
||||||
pw_properties_set(impl->headers, "Range", NULL);
|
pw_properties_set(impl->headers, "Range", NULL);
|
||||||
pw_properties_set(impl->headers, "RTP-Info", NULL);
|
pw_properties_set(impl->headers, "RTP-Info", NULL);
|
||||||
|
|
@ -770,8 +882,7 @@ static int rtsp_record_reply(void *data, int status, const struct spa_dict *head
|
||||||
impl->recording = true;
|
impl->recording = true;
|
||||||
|
|
||||||
snprintf(progress, sizeof(progress), "progress: %s/%s/%s\r\n", "0", "0", "0");
|
snprintf(progress, sizeof(progress), "progress: %s/%s/%s\r\n", "0", "0", "0");
|
||||||
return pw_rtsp_client_send(impl->rtsp, "SET_PARAMETER", NULL,
|
return rtsp_send(impl, "SET_PARAMETER", "text/parameters", progress, NULL);
|
||||||
"text/parameters", progress, NULL, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtsp_do_record(struct impl *impl)
|
static int rtsp_do_record(struct impl *impl)
|
||||||
|
|
@ -785,8 +896,7 @@ static int rtsp_do_record(struct impl *impl)
|
||||||
pw_properties_setf(impl->headers, "RTP-Info",
|
pw_properties_setf(impl->headers, "RTP-Info",
|
||||||
"seq=%u;rtptime=%u", impl->seq, impl->rtptime);
|
"seq=%u;rtptime=%u", impl->seq, impl->rtptime);
|
||||||
|
|
||||||
res = pw_rtsp_client_send(impl->rtsp, "RECORD", &impl->headers->dict,
|
res = rtsp_send(impl, "RECORD", NULL, NULL, rtsp_record_reply);
|
||||||
NULL, NULL, rtsp_record_reply, impl);
|
|
||||||
|
|
||||||
pw_properties_set(impl->headers, "Range", NULL);
|
pw_properties_set(impl->headers, "Range", NULL);
|
||||||
pw_properties_set(impl->headers, "RTP-Info", NULL);
|
pw_properties_set(impl->headers, "RTP-Info", NULL);
|
||||||
|
|
@ -942,8 +1052,7 @@ static int rtsp_do_setup(struct impl *impl)
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = pw_rtsp_client_send(impl->rtsp, "SETUP", &impl->headers->dict,
|
res = rtsp_send(impl, "SETUP", NULL, NULL, rtsp_setup_reply);
|
||||||
NULL, NULL, rtsp_setup_reply, impl);
|
|
||||||
|
|
||||||
pw_properties_set(impl->headers, "Transport", NULL);
|
pw_properties_set(impl->headers, "Transport", NULL);
|
||||||
|
|
||||||
|
|
@ -969,49 +1078,6 @@ static int rtsp_announce_reply(void *data, int status, const struct spa_dict *he
|
||||||
return rtsp_do_setup(impl);
|
return rtsp_do_setup(impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void base64_encode(const uint8_t *data, size_t len, char *enc, char pad)
|
|
||||||
{
|
|
||||||
static const char tab[] =
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < len; i += 3) {
|
|
||||||
uint32_t v;
|
|
||||||
v = data[i+0] << 16;
|
|
||||||
v |= (i+1 < len ? data[i+1] : 0) << 8;
|
|
||||||
v |= (i+2 < len ? data[i+2] : 0);
|
|
||||||
*enc++ = tab[(v >> (3*6)) & 0x3f];
|
|
||||||
*enc++ = tab[(v >> (2*6)) & 0x3f];
|
|
||||||
*enc++ = i+1 < len ? tab[(v >> (1*6)) & 0x3f] : pad;
|
|
||||||
*enc++ = i+2 < len ? tab[(v >> (0*6)) & 0x3f] : pad;
|
|
||||||
}
|
|
||||||
*enc = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t base64_decode(const char *data, size_t len, uint8_t *dec)
|
|
||||||
{
|
|
||||||
uint8_t tab[] = {
|
|
||||||
62, -1, -1, -1, 63, 52, 53, 54, 55, 56,
|
|
||||||
57, 58, 59, 60, 61, -1, -1, -1, -1, -1,
|
|
||||||
-1, -1, 0, 1, 2, 3, 4, 5, 6, 7,
|
|
||||||
8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
|
||||||
18, 19, 20, 21, 22, 23, 24, 25, -1, -1,
|
|
||||||
-1, -1, -1, -1, 26, 27, 28, 29, 30, 31,
|
|
||||||
32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
|
|
||||||
42, 43, 44, 45, 46, 47, 48, 49, 50, 51 };
|
|
||||||
size_t i, j;
|
|
||||||
for (i = 0, j = 0; i < len; i += 4) {
|
|
||||||
uint32_t v;
|
|
||||||
v = tab[data[i+0]-43] << (3*6);
|
|
||||||
v |= tab[data[i+1]-43] << (2*6);
|
|
||||||
v |= (data[i+2] == '=' ? 0 : tab[data[i+2]-43]) << (1*6);
|
|
||||||
v |= (data[i+3] == '=' ? 0 : tab[data[i+3]-43]);
|
|
||||||
dec[j++] = (v >> 16) & 0xff;
|
|
||||||
if (data[i+2] != '=') dec[j++] = (v >> 8) & 0xff;
|
|
||||||
if (data[i+3] != '=') dec[j++] = v & 0xff;
|
|
||||||
}
|
|
||||||
return j;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int rsa_encrypt(uint8_t *data, int len, uint8_t *res)
|
static int rsa_encrypt(uint8_t *data, int len, uint8_t *res)
|
||||||
{
|
{
|
||||||
RSA *rsa;
|
RSA *rsa;
|
||||||
|
|
@ -1100,8 +1166,6 @@ static int rtsp_do_announce(struct impl *impl)
|
||||||
pw_getrandom(impl->iv, sizeof(impl->iv), 0) < 0)
|
pw_getrandom(impl->iv, sizeof(impl->iv), 0) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
AES_set_encrypt_key(impl->key, 128, &impl->aes);
|
|
||||||
|
|
||||||
i = rsa_encrypt(impl->key, 16, rsakey);
|
i = rsa_encrypt(impl->key, 16, rsakey);
|
||||||
base64_encode(rsakey, i, key, '=');
|
base64_encode(rsakey, i, key, '=');
|
||||||
base64_encode(impl->iv, 16, iv, '=');
|
base64_encode(impl->iv, 16, iv, '=');
|
||||||
|
|
@ -1122,8 +1186,7 @@ static int rtsp_do_announce(struct impl *impl)
|
||||||
default:
|
default:
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
res = pw_rtsp_client_send(impl->rtsp, "ANNOUNCE", &impl->headers->dict,
|
res = rtsp_send(impl, "ANNOUNCE", "application/sdp", sdp, rtsp_announce_reply);
|
||||||
"application/sdp", sdp, rtsp_announce_reply, impl);
|
|
||||||
free(sdp);
|
free(sdp);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -1150,24 +1213,6 @@ static int rtsp_do_auth_setup(struct impl *impl)
|
||||||
rtsp_auth_setup_reply, impl);
|
rtsp_auth_setup_reply, impl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *find_attr(char **tokens, const char *key)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
char *p, *s;
|
|
||||||
for (i = 0; tokens[i]; i++) {
|
|
||||||
if (!spa_strstartswith(tokens[i], key))
|
|
||||||
continue;
|
|
||||||
p = tokens[i] + strlen(key);
|
|
||||||
if ((s = rindex(p, '"')) == NULL)
|
|
||||||
continue;
|
|
||||||
*s = '\0';
|
|
||||||
if ((s = index(p, '"')) == NULL)
|
|
||||||
continue;
|
|
||||||
return s+1;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int rtsp_auth_reply(void *data, int status, const struct spa_dict *headers)
|
static int rtsp_auth_reply(void *data, int status, const struct spa_dict *headers)
|
||||||
{
|
{
|
||||||
struct impl *impl = data;
|
struct impl *impl = data;
|
||||||
|
|
@ -1186,37 +1231,37 @@ static int rtsp_auth_reply(void *data, int status, const struct spa_dict *header
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_PRINTF_FUNC(2,3)
|
static const char *find_attr(char **tokens, const char *key)
|
||||||
static int MD5_hash(char hash[MD5_HASH_LENGTH+1], const char *fmt, ...)
|
|
||||||
{
|
{
|
||||||
unsigned char d[MD5_DIGEST_LENGTH];
|
|
||||||
int i;
|
int i;
|
||||||
va_list args;
|
char *p, *s;
|
||||||
char buffer[1024];
|
for (i = 0; tokens[i]; i++) {
|
||||||
|
if (!spa_strstartswith(tokens[i], key))
|
||||||
va_start(args, fmt);
|
continue;
|
||||||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
p = tokens[i] + strlen(key);
|
||||||
va_end(args);
|
if ((s = rindex(p, '"')) == NULL)
|
||||||
|
continue;
|
||||||
MD5((unsigned char*) buffer, strlen(buffer), d);
|
*s = '\0';
|
||||||
for (i = 0; i < MD5_DIGEST_LENGTH; i++)
|
if ((s = index(p, '"')) == NULL)
|
||||||
sprintf(&hash[2*i], "%02x", (uint8_t) d[i]);
|
continue;
|
||||||
hash[MD5_HASH_LENGTH] = '\0';
|
return s+1;
|
||||||
return 0;
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rtsp_do_auth(struct impl *impl, const struct spa_dict *headers)
|
static int rtsp_do_auth(struct impl *impl, const struct spa_dict *headers)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str, *realm, *nonce;
|
||||||
char **tokens;
|
char **tokens;
|
||||||
int n_tokens;
|
int n_tokens;
|
||||||
char auth[1024];
|
|
||||||
|
|
||||||
if (impl->password == NULL)
|
|
||||||
return -ENOTSUP;
|
|
||||||
|
|
||||||
if ((str = spa_dict_lookup(headers, "WWW-Authenticate")) == NULL)
|
if ((str = spa_dict_lookup(headers, "WWW-Authenticate")) == NULL)
|
||||||
return -ENOENT;
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (impl->password == NULL) {
|
||||||
|
pw_log_warn("authentication required but no raop.password property was given");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
pw_log_info("Auth: %s", str);
|
pw_log_info("Auth: %s", str);
|
||||||
|
|
||||||
|
|
@ -1224,45 +1269,23 @@ static int rtsp_do_auth(struct impl *impl, const struct spa_dict *headers)
|
||||||
if (tokens == NULL || tokens[0] == NULL)
|
if (tokens == NULL || tokens[0] == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (spa_streq(tokens[0], "Basic")) {
|
impl->auth_method = strdup(tokens[0]);
|
||||||
char buf[256];
|
|
||||||
char enc[512];
|
|
||||||
spa_scnprintf(buf, sizeof(buf), "%s:%s", DEFAULT_USER_NAME, impl->password);
|
|
||||||
base64_encode((uint8_t*)buf, strlen(buf), enc, '=');
|
|
||||||
spa_scnprintf(auth, sizeof(auth), "Basic %s", enc);
|
|
||||||
}
|
|
||||||
else if (spa_streq(tokens[0], "Digest")) {
|
|
||||||
const char *realm, *nonce, *url;
|
|
||||||
char h1[MD5_HASH_LENGTH+1];
|
|
||||||
char h2[MD5_HASH_LENGTH+1];
|
|
||||||
char resp[MD5_HASH_LENGTH+1];
|
|
||||||
|
|
||||||
|
if (spa_streq(impl->auth_method, "Digest")) {
|
||||||
realm = find_attr(tokens, "realm");
|
realm = find_attr(tokens, "realm");
|
||||||
nonce = find_attr(tokens, "nonce");
|
nonce = find_attr(tokens, "nonce");
|
||||||
if (realm == NULL || nonce == NULL)
|
if (realm == NULL || nonce == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
url = pw_rtsp_client_get_url(impl->rtsp);
|
impl->realm = strdup(realm);
|
||||||
|
impl->nonce = strdup(nonce);
|
||||||
MD5_hash(h1, "%s:%s:%s", DEFAULT_USER_NAME, realm, impl->password);
|
|
||||||
MD5_hash(h2, "OPTIONS:%s", url);
|
|
||||||
MD5_hash(resp, "%s:%s:%s", h1, nonce, h2);
|
|
||||||
|
|
||||||
spa_scnprintf(auth, sizeof(auth),
|
|
||||||
"username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"",
|
|
||||||
DEFAULT_USER_NAME, realm, nonce, url, resp);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
pw_properties_setf(impl->headers, "Authorization", "%s %s",
|
|
||||||
tokens[0], auth);
|
|
||||||
pw_free_strv(tokens);
|
pw_free_strv(tokens);
|
||||||
|
|
||||||
pw_rtsp_client_send(impl->rtsp, "OPTIONS", &impl->headers->dict,
|
rtsp_send(impl, "OPTIONS", NULL, NULL, rtsp_auth_reply);
|
||||||
NULL, NULL, rtsp_auth_reply, impl);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
pw_free_strv(tokens);
|
pw_free_strv(tokens);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -1345,6 +1368,12 @@ static void connection_cleanup(struct impl *impl)
|
||||||
close(impl->timing_fd);
|
close(impl->timing_fd);
|
||||||
impl->timing_fd = -1;
|
impl->timing_fd = -1;
|
||||||
}
|
}
|
||||||
|
free(impl->auth_method);
|
||||||
|
impl->auth_method = NULL;
|
||||||
|
free(impl->realm);
|
||||||
|
impl->realm = NULL;
|
||||||
|
free(impl->nonce);
|
||||||
|
impl->nonce = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rtsp_disconnected(void *data)
|
static void rtsp_disconnected(void *data)
|
||||||
|
|
@ -1690,7 +1719,12 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||||
impl->server_fd = -1;
|
impl->server_fd = -1;
|
||||||
impl->control_fd = -1;
|
impl->control_fd = -1;
|
||||||
impl->timing_fd = -1;
|
impl->timing_fd = -1;
|
||||||
|
impl->ctx = EVP_CIPHER_CTX_new();
|
||||||
|
if (impl->ctx == NULL) {
|
||||||
|
res = -errno;
|
||||||
|
pw_log_error( "can't create cipher context: %m");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (args == NULL)
|
if (args == NULL)
|
||||||
args = "";
|
args = "";
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue