Search code examples
c++windowswinapisid

Why does ConvertStringSidToSid fail to convert a string SID?


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

Solution

  • 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.