2

I am trying to convert a SID to a string and back again using ConvertSidToStringSid and ConvertStringSidToSid, but the conversion back is failing with error code 1337.

A test SID I created failed to make the round trip -- it caused ConvertStringSidToSid to fail with code 1337 (ERROR_INVALID_SID). It looks like Windows represents identifier authorities with too many bytes using hex instead of decimal in the string representation, and ConvertStringSidToSid chokes. The documentation for ConvertStringSidToSid linked above says "You can use this function to retrieve a SID that the ConvertSidToStringSid function converted to string format," which suggests that what I am trying to do should be supported. Is there a better way to convert SIDs back and forth to their string representation?

Here is a minimal example that demonstrates the problem:

#include "pch.h"
#include <iostream>
#include <windows.h>
#include <sddl.h>

int main()
{
    SID_IDENTIFIER_AUTHORITY sid_id_auth = { 1,2,3,4,5,6 };
    PSID sid;
    PSID new_sid;
    LPWSTR string_sid;

    // Create a new SID with the given ID authority and no sub-authorities
    if (!AllocateAndInitializeSid(&sid_id_auth, 0, 0, 0, 0, 0, 0, 0, 0, 0, &sid)) {
        std::cout << "Failed to allocate SID: error code " << GetLastError() << std::endl;
        return 1;
    }

    // Stringify and print
    if (!ConvertSidToStringSidW(sid, &string_sid)) {
        std::cout << "Failed to convert to string: error code " << GetLastError() << std::endl;
        FreeSid(sid);
        return 2;
    }
    std::wcout << string_sid << std::endl;

    // Destringify and print
    if (ConvertStringSidToSidW(string_sid, &new_sid)) {
        std::cout << "Success" << std::endl;
    }
    else {
        std::cout << "Failed: error code " << GetLastError() << std::endl;
    }

    // Clean up
    LocalFree(string_sid);
    LocalFree(new_sid);
    FreeSid(sid);
}

On my machine (Windows 10.0.16299, Visual Studio 15.9.7), this prints:

S-1-0x10203040506
Failed: error code 1337
ddulaney
  • 607
  • 3
  • 15
  • 2
    Can you check the return value of `AllocateAndInitializeSid` to make sure you really are getting a valid `PSID`? – NathanOliver Feb 26 '19 at 22:26
  • Edited. I also checked the return of `ConvertSidToStringSid`. The issue is still there, which makes sense because I was getting a valid-looking string SID. – ddulaney Feb 26 '19 at 22:39

2 Answers2

3

You're passing an invalid value for nSubAuthorityCount to AllocateAndInitializeSid.
The documentation states:

nSubAuthorityCount

Specifies the number of subauthorities to place in the SID. This parameter also identifies how many of the subauthority parameters have meaningful values. This parameter must contain a value from 1 to 8.

and

S-R-I-S

In this notation, the literal character "S" identifies the series of digits as a SID, R is the revision level, I is the identifier-authority value, and S… is one or more subauthority values.

Passing 0 is therefore wrong even though AllocateAndInitializeSid returns TRUE which might have been an oversight.

ConvertSidToStringSidW doesn't seem to check for that requirement either which is why the conversion succeeds.
ConvertStringSidToSidW fails because it expects a string in the format S-R-I-S.

Community
  • 1
  • 1
Axalo
  • 2,765
  • 4
  • 21
  • 35
1

You miss the identifier-authority value in the SID components: S-1-0x10203040506. So you get the ERROR_INVALID_SID (1337).

After add the identifier-authority value, here I use SECURITY_NT_AUTHORITY (is used with Windows well-known SIDs): 5 like bellow. The error solved.

if (ConvertStringSidToSidW(L"S-1-5-0x10203040506", &new_sid)) {
    std::cout << "Success" << std::endl;
}
else {
    std::cout << "Failed: error code " << GetLastError() << std::endl;
}
Rita Han
  • 8,827
  • 1
  • 7
  • 20