[vlc-devel] [PATCH 1/3] contrib: add libsmb2

Thomas Guillem thomas at gllm.fr
Thu Oct 17 15:16:30 CEST 2019


(cherry picked from commit b56d2630dda483a6d949979160cba5f1805cd2d6)
(cherry picked from commit 2f3f44804e673a4b49d12faf21915964cef80baa)
(cherry picked from commit dbd816319d091f88cf6ab0bb516a7d2ad5f7c426)
(cherry picked from commit 537afeafb00684cb58282995cfa787a52dcb2967)
(cherry picked from commit 758c04a0d4d629d92bc5c123c6316372e8b04c76)
(cherry picked from commit e2f163e89023680e6e9f34f8aeebbd5cfb405cf4)
(cherry picked from commit 291c835c63d6dd5dcc453a2dc678af046bce56f5)
(cherry picked from commit a2289a28a997fd19bf0e2611f6a13efa9929e20a)
Signed-off-by: Thomas Guillem <thomas at gllm.fr>
---
 ...ssp-add-support-for-Anonymous-logins.patch | 219 ++++++++++++++++++
 .../0002-Fix-indent-and-white-spaces.patch    |  97 ++++++++
 .../src/smb2/0003-Fix-getlogin-usage.patch    |  70 ++++++
 ...troy_context-fix-possible-null-deref.patch |  48 ++++
 contrib/src/smb2/SHA512SUMS                   |   1 +
 contrib/src/smb2/rules.mak                    |  31 +++
 6 files changed, 466 insertions(+)
 create mode 100644 contrib/src/smb2/0001-ntlmssp-add-support-for-Anonymous-logins.patch
 create mode 100644 contrib/src/smb2/0002-Fix-indent-and-white-spaces.patch
 create mode 100644 contrib/src/smb2/0003-Fix-getlogin-usage.patch
 create mode 100644 contrib/src/smb2/0004-smb2_destroy_context-fix-possible-null-deref.patch
 create mode 100644 contrib/src/smb2/SHA512SUMS
 create mode 100644 contrib/src/smb2/rules.mak

diff --git a/contrib/src/smb2/0001-ntlmssp-add-support-for-Anonymous-logins.patch b/contrib/src/smb2/0001-ntlmssp-add-support-for-Anonymous-logins.patch
new file mode 100644
index 0000000000..3be16c99ff
--- /dev/null
+++ b/contrib/src/smb2/0001-ntlmssp-add-support-for-Anonymous-logins.patch
@@ -0,0 +1,219 @@
+From 1bf49f51d27e87230d826b6f482db312c693586f Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <ronniesahlberg at gmail.com>
+Date: Tue, 6 Aug 2019 13:30:51 +1000
+Subject: [PATCH 1/4] ntlmssp: add support for Anonymous logins
+
+Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>
+---
+ lib/ntlmssp.c | 131 +++++++++++++++++++++++++++++---------------------
+ 1 file changed, 77 insertions(+), 54 deletions(-)
+
+diff --git a/lib/ntlmssp.c b/lib/ntlmssp.c
+index 646a511..a34d119 100644
+--- a/lib/ntlmssp.c
++++ b/lib/ntlmssp.c
+@@ -96,6 +96,7 @@ struct auth_data {
+ #define NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY         0x00080000
+ #define NTLMSSP_TARGET_TYPE_SERVER                         0x00020000
+ #define NTLMSSP_NEGOTIATE_ALWAYS_SIGN                      0x00008000
++#define NTLMSSP_NEGOTIATE_ANONYMOUS                        0x00000800
+ #define NTLMSSP_NEGOTIATE_NTLM                             0x00000200
+ #define NTLMSSP_NEGOTIATE_SIGN                             0x00000010
+ #define NTLMSSP_REQUEST_TARGET                             0x00000004
+@@ -320,7 +321,7 @@ encode_ntlm_auth(struct smb2_context *smb2, time_t ti,
+         struct ucs2 *ucs2_domain = NULL;
+         struct ucs2 *ucs2_user = NULL;
+         struct ucs2 *ucs2_workstation = NULL;
+-        int NTChallengeResponse_len;
++        int NTChallengeResponse_len = 0;
+         unsigned char NTProofStr[16];
+         unsigned char LMStr[16];
+         uint64_t t;
+@@ -330,14 +331,15 @@ encode_ntlm_auth(struct smb2_context *smb2, time_t ti,
+         uint32_t u32;
+         uint32_t server_neg_flags;
+         unsigned char key_exch[SMB2_KEY_SIZE];
++        uint8_t anonymous = 0;
+ 
+         tv.tv_sec = ti;
+         tv.tv_usec = 0;
+         t = timeval_to_win(&tv);
+ 
+         if (auth_data->password == NULL) {
+-                smb2_set_error(smb2, "No password set, can not use NTLM\n");
+-                goto finished;
++                anonymous = 1;
++                goto encode;
+         }
+ 
+         /*
+@@ -383,6 +385,7 @@ encode_ntlm_auth(struct smb2_context *smb2, time_t ti,
+         smb2_hmac_md5(NTProofStr, 16, ResponseKeyNT, 16, key_exch);
+         memcpy(auth_data->exported_session_key, key_exch, 16);
+ 
++ encode:
+         /*
+          * Generate AUTHENTICATE_MESSAGE
+          */
+@@ -393,14 +396,20 @@ encode_ntlm_auth(struct smb2_context *smb2, time_t ti,
+         encoder(&u32, 4, auth_data);
+ 
+         /* lm challenge response fields */
+-        memcpy(&lm_buf[0], server_challenge, 8);
+-        memcpy(&lm_buf[8], auth_data->client_challenge, 8);
+-        smb2_hmac_md5(&lm_buf[0], 16,
+-                 ResponseKeyNT, 16, LMStr);
+-        u32 = htole32(0x00180018);
+-        encoder(&u32, 4, auth_data);
+-        u32 = 0;
+-        encoder(&u32, 4, auth_data);
++        if (!anonymous) {
++                memcpy(&lm_buf[0], server_challenge, 8);
++                memcpy(&lm_buf[8], auth_data->client_challenge, 8);
++                smb2_hmac_md5(&lm_buf[0], 16,
++                              ResponseKeyNT, 16, LMStr);
++                u32 = htole32(0x00180018);
++                encoder(&u32, 4, auth_data);
++                u32 = 0;
++                encoder(&u32, 4, auth_data);
++        } else {
++                u32 = 0;
++                encoder(&u32, 4, auth_data);
++                encoder(&u32, 4, auth_data);
++        }
+ 
+         /* nt challenge response fields */
+         u32 = htole32((NTChallengeResponse_len<<16)|
+@@ -410,7 +419,7 @@ encode_ntlm_auth(struct smb2_context *smb2, time_t ti,
+         encoder(&u32, 4, auth_data);
+ 
+         /* domain name fields */
+-        if (auth_data->domain) {
++        if (!anonymous && auth_data->domain) {
+                 ucs2_domain = utf8_to_ucs2(auth_data->domain);
+                 if (ucs2_domain == NULL) {
+                         goto finished;
+@@ -427,18 +436,24 @@ encode_ntlm_auth(struct smb2_context *smb2, time_t ti,
+         }
+ 
+         /* user name fields */
+-        ucs2_user = utf8_to_ucs2(auth_data->user);
+-        if (ucs2_user == NULL) {
+-                goto finished;
++        if (!anonymous) {
++                ucs2_user = utf8_to_ucs2(auth_data->user);
++                if (ucs2_user == NULL) {
++                        goto finished;
++                }
++                u32 = ucs2_user->len * 2;
++                u32 = htole32((u32 << 16) | u32);
++                encoder(&u32, 4, auth_data);
++                u32 = 0;
++                encoder(&u32, 4, auth_data);
++        } else {
++                u32 = 0;
++                encoder(&u32, 4, auth_data);
++                encoder(&u32, 4, auth_data);
+         }
+-        u32 = ucs2_user->len * 2;
+-        u32 = htole32((u32 << 16) | u32);
+-        encoder(&u32, 4, auth_data);
+-        u32 = 0;
+-        encoder(&u32, 4, auth_data);
+ 
+         /* workstation name fields */
+-        if (auth_data->workstation) {
++        if (!anonymous && auth_data->workstation) {
+                 ucs2_workstation = utf8_to_ucs2(auth_data->workstation);
+                 if (ucs2_workstation == NULL) {
+                         goto finished;
+@@ -460,45 +475,53 @@ encode_ntlm_auth(struct smb2_context *smb2, time_t ti,
+         encoder(&u32, 4, auth_data);
+ 
+         /* negotiate flags */
+-        u32 = htole32(NTLMSSP_NEGOTIATE_56|NTLMSSP_NEGOTIATE_128|
+-                      NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY|
+-                      //NTLMSSP_NEGOTIATE_ALWAYS_SIGN|
+-                      NTLMSSP_NEGOTIATE_NTLM|
+-                      //NTLMSSP_NEGOTIATE_SIGN|
+-                      NTLMSSP_REQUEST_TARGET|NTLMSSP_NEGOTIATE_OEM|
+-                      NTLMSSP_NEGOTIATE_UNICODE);
++        u32 = NTLMSSP_NEGOTIATE_56|NTLMSSP_NEGOTIATE_128|
++                NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY|
++                //NTLMSSP_NEGOTIATE_ALWAYS_SIGN|
++                NTLMSSP_NEGOTIATE_NTLM|
++                //NTLMSSP_NEGOTIATE_SIGN|
++                NTLMSSP_REQUEST_TARGET|NTLMSSP_NEGOTIATE_OEM|
++                NTLMSSP_NEGOTIATE_UNICODE;
++        if (anonymous)
++                u32 |= NTLMSSP_NEGOTIATE_ANONYMOUS;
++        u32 = htole32(u32);
+         encoder(&u32, 4, auth_data);
+ 
+-        /* append domain */
+-        u32 = htole32(auth_data->len);
+-        memcpy(&auth_data->buf[32], &u32, 4);
+-        if (ucs2_domain) {
+-                encoder(ucs2_domain->val, ucs2_domain->len * 2, auth_data);
+-        }
++        if (!anonymous) {
++                /* append domain */
++                u32 = htole32(auth_data->len);
++                memcpy(&auth_data->buf[32], &u32, 4);
++                if (ucs2_domain) {
++                        encoder(ucs2_domain->val, ucs2_domain->len * 2,
++                                auth_data);
++                }
+ 
+-        /* append user */
+-        u32 = htole32(auth_data->len);
+-        memcpy(&auth_data->buf[40], &u32, 4);
+-        encoder(ucs2_user->val, ucs2_user->len * 2, auth_data);
++                /* append user */
++                u32 = htole32(auth_data->len);
++                memcpy(&auth_data->buf[40], &u32, 4);
++                encoder(ucs2_user->val, ucs2_user->len * 2, auth_data);
++
++                /* append workstation */
++                u32 = htole32(auth_data->len);
++                memcpy(&auth_data->buf[48], &u32, 4);
++                if (ucs2_workstation) {
++                        encoder(ucs2_workstation->val,
++                                ucs2_workstation->len * 2, auth_data);
++                }
+ 
+-        /* append workstation */
+-        u32 = htole32(auth_data->len);
+-        memcpy(&auth_data->buf[48], &u32, 4);
+-        if (ucs2_workstation) {
+-                encoder(ucs2_workstation->val, ucs2_workstation->len * 2, auth_data);
++                /* append LMChallengeResponse */
++                u32 = htole32(auth_data->len);
++                memcpy(&auth_data->buf[16], &u32, 4);
++                encoder(LMStr, 16, auth_data);
++                encoder(auth_data->client_challenge, 8, auth_data);
++
++                /* append NTChallengeResponse */
++                u32 = htole32(auth_data->len);
++                memcpy(&auth_data->buf[24], &u32, 4);
++                encoder(NTChallengeResponse_buf, NTChallengeResponse_len,
++                        auth_data);
+         }
+ 
+-        /* append LMChallengeResponse */
+-        u32 = htole32(auth_data->len);
+-        memcpy(&auth_data->buf[16], &u32, 4);
+-        encoder(LMStr, 16, auth_data);
+-        encoder(auth_data->client_challenge, 8, auth_data);
+-
+-        /* append NTChallengeResponse */
+-        u32 = htole32(auth_data->len);
+-        memcpy(&auth_data->buf[24], &u32, 4);
+-        encoder(NTChallengeResponse_buf, NTChallengeResponse_len, auth_data);
+-
+         ret = 0;
+ finished:
+         free(ucs2_domain);
+-- 
+2.20.1
+
diff --git a/contrib/src/smb2/0002-Fix-indent-and-white-spaces.patch b/contrib/src/smb2/0002-Fix-indent-and-white-spaces.patch
new file mode 100644
index 0000000000..66a97508c7
--- /dev/null
+++ b/contrib/src/smb2/0002-Fix-indent-and-white-spaces.patch
@@ -0,0 +1,97 @@
+From 13800418c0c2a8c1b26bf1acb0810004fb874213 Mon Sep 17 00:00:00 2001
+From: Thomas Guillem <thomas at gllm.fr>
+Date: Tue, 30 Jul 2019 17:46:49 +0200
+Subject: [PATCH 2/4] Fix indent and white spaces
+
+No functional changes.
+---
+ lib/init.c | 34 +++++++++++++++++-----------------
+ 1 file changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/lib/init.c b/lib/init.c
+index e6cf1e5..eab69a5 100644
+--- a/lib/init.c
++++ b/lib/init.c
+@@ -69,12 +69,12 @@ smb2_parse_args(struct smb2_context *smb2, const char *args)
+         while (args && *args != 0) {
+                 char *next, *value;
+ 
+-		next = strchr(args, '&');
++                next = strchr(args, '&');
+                 if (next) {
+                         *(next++) = '\0';
+                 }
+ 
+-		value = strchr(args, '=');
++                value = strchr(args, '=');
+                 if (value) {
+                         *(value++) = '\0';
+                 }
+@@ -135,7 +135,7 @@ struct smb2_url *smb2_parse_url(struct smb2_context *smb2, const char *url)
+                 smb2_set_error(smb2, "URL is too long");
+                 return NULL;
+         }
+-	strncpy(str, url + 6, MAX_URL_SIZE);
++        strncpy(str, url + 6, MAX_URL_SIZE);
+ 
+         args = strchr(str, '?');
+         if (args) {
+@@ -165,7 +165,7 @@ struct smb2_url *smb2_parse_url(struct smb2_context *smb2, const char *url)
+                 *(tmp++) = '\0';
+                 u->user = strdup(ptr);
+                 ptr = tmp;
+-	}
++        }
+         /* server */
+         if ((tmp = strchr(ptr, '/')) != NULL) {
+                 *(tmp++) = '\0';
+@@ -287,7 +287,7 @@ void smb2_destroy_context(struct smb2_context *smb2)
+ void smb2_free_iovector(struct smb2_context *smb2, struct smb2_io_vectors *v)
+ {
+         int i;
+-        
++
+         for (i = 0; i < v->niov; i++) {
+                 if (v->iov[i].free) {
+                         v->iov[i].free(v->iov[i].buf);
+@@ -316,25 +316,25 @@ struct smb2_iovec *smb2_add_iovector(struct smb2_context *smb2,
+ 
+ void smb2_set_error(struct smb2_context *smb2, const char *error_string, ...)
+ {
+-	va_list ap;
+-	char errstr[MAX_ERROR_SIZE] = {0};
++        va_list ap;
++        char errstr[MAX_ERROR_SIZE] = {0};
+ 
+-	va_start(ap, error_string);
+-	if (vsnprintf(errstr, MAX_ERROR_SIZE, error_string, ap) < 0) {
+-		strncpy(errstr, "could not format error string!",
++        va_start(ap, error_string);
++        if (vsnprintf(errstr, MAX_ERROR_SIZE, error_string, ap) < 0) {
++                strncpy(errstr, "could not format error string!",
+                         MAX_ERROR_SIZE);
+-	}
+-	va_end(ap);
+-	if (smb2 != NULL) {
+-		strncpy(smb2->error_string, errstr, MAX_ERROR_SIZE);
+-	}
++        }
++        va_end(ap);
++        if (smb2 != NULL) {
++                strncpy(smb2->error_string, errstr, MAX_ERROR_SIZE);
++        }
+ }
+ 
+ const char *smb2_get_error(struct smb2_context *smb2)
+ {
+-	return smb2 ? smb2->error_string : "";
++        return smb2 ? smb2->error_string : "";
+ }
+-        
++
+ const char *smb2_get_client_guid(struct smb2_context *smb2)
+ {
+         return smb2->client_guid;
+-- 
+2.20.1
+
diff --git a/contrib/src/smb2/0003-Fix-getlogin-usage.patch b/contrib/src/smb2/0003-Fix-getlogin-usage.patch
new file mode 100644
index 0000000000..91776d9f5f
--- /dev/null
+++ b/contrib/src/smb2/0003-Fix-getlogin-usage.patch
@@ -0,0 +1,70 @@
+From 434a880dc7f304eafb2377e26d47d93187109b14 Mon Sep 17 00:00:00 2001
+From: Thomas Guillem <thomas at gllm.fr>
+Date: Tue, 30 Jul 2019 18:02:14 +0200
+Subject: [PATCH 3/4] Fix getlogin() usage
+
+Use the reentrant version (the getlogin() string was statically allocated and
+could be overwritten on subsequent calls).
+
+Also check for error and use "Guest" as a fallback.
+---
+ lib/init.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/lib/init.c b/lib/init.c
+index eab69a5..4387cd0 100644
+--- a/lib/init.c
++++ b/lib/init.c
+@@ -52,17 +52,27 @@
+ #define MAX_URL_SIZE 256
+ 
+ #ifdef _MSC_VER
+-#define getlogin() "Guest"
++#include <errno.h>
++#define getlogin_r(a,b) ENXIO
+ #define random rand
+ #define getpid GetCurrentProcessId
+ #endif // _MSC_VER
+ 
+ #ifdef ESP_PLATFORM
++#include <errno.h>
+ #include <esp_system.h>
+ #define random esp_random
+-#define getlogin() "Guest"
++#define getlogin_r(a,b) ENXIO
+ #endif
+ 
++#ifdef __ANDROID__
++#include <errno.h>
++// getlogin_r() was added in API 28
++#if __ANDROID_API__ < 28
++#define getlogin_r(a,b) ENXIO
++#endif
++#endif // __ANDROID__
++
+ static int
+ smb2_parse_args(struct smb2_context *smb2, const char *args)
+ {
+@@ -206,7 +216,8 @@ void smb2_destroy_url(struct smb2_url *url)
+ struct smb2_context *smb2_init_context(void)
+ {
+         struct smb2_context *smb2;
+-        int i;
++        char buf[1024];
++        int i, ret;
+ 
+         smb2 = malloc(sizeof(struct smb2_context));
+         if (smb2 == NULL) {
+@@ -214,7 +225,8 @@ struct smb2_context *smb2_init_context(void)
+         }
+         memset(smb2, 0, sizeof(struct smb2_context));
+ 
+-        smb2_set_user(smb2, getlogin());
++        ret = getlogin_r(buf, sizeof(buf));
++        smb2_set_user(smb2, ret == 0 ? buf : "Guest");
+         smb2->fd = -1;
+         smb2->sec = SMB2_SEC_UNDEFINED;
+         smb2->version = SMB2_VERSION_ANY;
+-- 
+2.20.1
+
diff --git a/contrib/src/smb2/0004-smb2_destroy_context-fix-possible-null-deref.patch b/contrib/src/smb2/0004-smb2_destroy_context-fix-possible-null-deref.patch
new file mode 100644
index 0000000000..ec8f9331b3
--- /dev/null
+++ b/contrib/src/smb2/0004-smb2_destroy_context-fix-possible-null-deref.patch
@@ -0,0 +1,48 @@
+From 6e2126a854292621548948a3d30e6023943d7c99 Mon Sep 17 00:00:00 2001
+From: Thomas Guillem <thomas at gllm.fr>
+Date: Thu, 8 Aug 2019 15:18:31 +0200
+Subject: [PATCH 4/4] smb2_destroy_context: fix possible null-deref
+
+This could happen when the smb2_close_async() command was aborted
+(smb2_service() not being called).
+---
+ lib/init.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/lib/init.c b/lib/init.c
+index 4387cd0..03903fb 100644
+--- a/lib/init.c
++++ b/lib/init.c
+@@ -255,14 +255,6 @@ void smb2_destroy_context(struct smb2_context *smb2)
+                 smb2->fd = -1;
+         }
+ 
+-        if (smb2->fhs) {
+-                smb2_free_all_fhs(smb2);
+-        }
+-
+-        if (smb2->dirs) {
+-                smb2_free_all_dirs(smb2);
+-        }
+-
+         while (smb2->outqueue) {
+                 struct smb2_pdu *pdu = smb2->outqueue;
+ 
+@@ -283,6 +275,14 @@ void smb2_destroy_context(struct smb2_context *smb2)
+                 smb2->pdu = NULL;
+         }
+ 
++        if (smb2->fhs) {
++                smb2_free_all_fhs(smb2);
++        }
++
++        if (smb2->dirs) {
++                smb2_free_all_dirs(smb2);
++        }
++
+         free(smb2->session_key);
+         smb2->session_key = NULL;
+ 
+-- 
+2.20.1
+
diff --git a/contrib/src/smb2/SHA512SUMS b/contrib/src/smb2/SHA512SUMS
new file mode 100644
index 0000000000..668b39e377
--- /dev/null
+++ b/contrib/src/smb2/SHA512SUMS
@@ -0,0 +1 @@
+08f421182a08f54d7a50afbfd83609093c1a62b24f7abe2a56ec833a36570916b20c8f046fcdb5ba8c8ed0311a19e8338b75839cd7cf752fc5b33a1367cf839f  libsmb2-3.0.0.tar.gz
diff --git a/contrib/src/smb2/rules.mak b/contrib/src/smb2/rules.mak
new file mode 100644
index 0000000000..1cee854204
--- /dev/null
+++ b/contrib/src/smb2/rules.mak
@@ -0,0 +1,31 @@
+# SMB2
+SMB2_VERSION := 3.0.0
+SMB2_URL := https://github.com/sahlberg/libsmb2/archive/v$(SMB2_VERSION).tar.gz
+
+ifdef BUILD_NETWORK
+ifndef HAVE_WIN32
+PKGS += smb2
+endif
+endif
+ifeq ($(call need_pkg,"smb2"),)
+PKGS_FOUND += smb2
+endif
+
+$(TARBALLS)/libsmb2-$(SMB2_VERSION).tar.gz:
+	$(call download_pkg,$(SMB2_URL),smb2)
+
+.sum-smb2: libsmb2-$(SMB2_VERSION).tar.gz
+
+smb2: libsmb2-$(SMB2_VERSION).tar.gz .sum-smb2
+	$(UNPACK)
+	$(APPLY) $(SRC)/smb2/0001-ntlmssp-add-support-for-Anonymous-logins.patch
+	$(APPLY) $(SRC)/smb2/0002-Fix-indent-and-white-spaces.patch
+	$(APPLY) $(SRC)/smb2/0003-Fix-getlogin-usage.patch
+	$(APPLY) $(SRC)/smb2/0004-smb2_destroy_context-fix-possible-null-deref.patch
+	$(MOVE)
+
+.smb2: smb2
+	cd $< && ./bootstrap
+	cd $< && $(HOSTVARS) ./configure --disable-examples --disable-werror --without-libkrb5 $(HOSTCONF)
+	cd $< && $(MAKE) install
+	touch $@
-- 
2.20.1



More information about the vlc-devel mailing list