]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
libcli/security: stricter identauth parsing
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Tue, 11 Apr 2023 23:38:24 +0000 (11:38 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 28 Apr 2023 02:15:36 +0000 (02:15 +0000)
We don't want octal numbers or overflows.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
libcli/security/dom_sid.c

index bcab0aec40760b2c4256784ff84022e88cf19741..6cf7cc4d6d832d7409118c7d5f36e1f6e42cd3b9 100644 (file)
@@ -131,7 +131,8 @@ bool dom_sid_parse_endp(const char *sidstr,struct dom_sid *sidout,
                        const char **endp)
 {
        const char *p;
-       char *q;
+       char *q = NULL;
+       char *end = NULL;
        uint64_t conv;
        int error = 0;
 
@@ -158,12 +159,27 @@ bool dom_sid_parse_endp(const char *sidstr,struct dom_sid *sidout,
        if (!isdigit(*q)) {
                goto format_error;
        }
+       while (q[0] == '0' && isdigit((unsigned char)q[1])) {
+               /*
+                * strtoull will think this is octal, which is not how SIDs
+                * work! So let's walk along until there are no leading zeros
+                * (or a single zero).
+                */
+               q++;
+       }
 
        /* get identauth */
-       conv = smb_strtoull(q, &q, 0, &error, SMB_STR_STANDARD);
+       conv = smb_strtoull(q, &end, 0, &error, SMB_STR_STANDARD);
        if (conv & AUTHORITY_MASK || error != 0) {
                goto format_error;
        }
+       if (conv >= (1ULL << 48) || end - q > 15) {
+               /*
+                * This identauth looks like a big number, but resolves to a
+                * small number after rounding.
+                */
+               goto format_error;
+       }
 
        /* NOTE - the conv value is in big-endian format. */
        sidout->id_auth[0] = (conv & 0xff0000000000ULL) >> 40;
@@ -174,6 +190,7 @@ bool dom_sid_parse_endp(const char *sidstr,struct dom_sid *sidout,
        sidout->id_auth[5] = (conv & 0x0000000000ffULL);
 
        sidout->num_auths = 0;
+       q = end;
        if (*q != '-') {
                /* Just id_auth, no subauths */
                goto done;
@@ -182,8 +199,6 @@ bool dom_sid_parse_endp(const char *sidstr,struct dom_sid *sidout,
        q++;
 
        while (true) {
-               char *end;
-
                if (!isdigit(*q)) {
                        goto format_error;
                }