1

How can i write this function using SAL annotations for C? I need to implement some functions and i dont know how to declare them. I just need 1 function as a model, so i can implement the rest.

Down here is my main C file with take all the hanldes i have implemented, i dont need to modifiy this.

static void
PrintHelp()
{
    printf("Available commands:\n");
    printf("\t> register <username> <password>\n");
    printf("\t> login <username> <password>\n");
    printf("\t> logout\n");
    printf("\t> store <source file path> <submission name>\n");
    printf("\t> retrieve <submission name> <destination file path>\n");
    printf("\t> exit\n");
}

int main()
{
    char command[10];
    char arg1[50];
    char arg2[50];

    NTSTATUS status = GlobalDataInitialize();
    if (!NT_SUCCESS(status))
    {
        printf("GlobalDataInitialize failed with NTSTATUS = 0x%X\n", status);
        assert(FALSE);
        return -1;
    }

    PrintHelp();
    do
    {
        printf("Enter your command:\n");
        scanf("%s", command);

        if (memcmp(command, "register", sizeof("register")) == 0)
        {
            scanf("%s", arg1);    // username
            scanf("%s", arg2);    // password

            printf("register with username [%s] password [%s]\n", arg1, arg2);
            SafeStorageHandleRegister(arg1, (USHORT)strlen(arg1), arg2, (USHORT)strlen(arg2));
        }
        else if (memcmp(command, "login", sizeof("login")) == 0)
        {
            scanf("%s", arg1);    // username
            scanf("%s", arg2);    // password

            printf("login with username [%s] password [%s]\n", arg1, arg2);
            SafeStorageHandleLogin(arg1, (USHORT)strlen(arg1), arg2, (USHORT)strlen(arg2));
        }
        else if (memcmp(command, "logout", sizeof("logout")) == 0)
        {
            printf("logout\n");
            SafeStorageHandleLogout();
        }
        else if (memcmp(command, "store", sizeof("store")) == 0)
        {
            scanf("%s", arg1);    // source file path
            scanf("%s", arg2);    // submission name

            printf("store with source file path [%s] submission name [%s]\n", arg1, arg2);
            SafeStorageHandleStore(arg2, (USHORT)strlen(arg2), arg1, (USHORT)strlen(arg1));
        }
        else if (memcmp(command, "retrieve", sizeof("retrieve")) == 0)
        {
            scanf("%s", arg1);    // submission name 
            scanf("%s", arg2);    // destination file path

            printf("retrieve with submission name [%s] destination file path [%s]\n", arg1, arg2);
            SafeStorageHandleRetrieve(arg1, (USHORT)strlen(arg1), arg2, (USHORT)strlen(arg2));
        }
        else if (memcmp(command, "exit", sizeof("exit")) == 0)
        {
            printf("Bye Bye!\n");
            break;
        }
        else
        {
            printf("Unknown command. Try again!\n");
        }
    } while (TRUE);

    return 0;

I need help implementing this registration handle function. I can see that this registration functions has these 2 parameters Username**Password and also define the type of data. I dont know how to write proper C declarations using SAL annotations to make this work.

// Handles the "register" command
// Creates the user with Username and Password specified
//      * Creates the user's subdirectory in the %APPDIR%\users directory
// Fails if the user is already registered
// This command is available only if no user is currently logged in (it must fail otherwise)
// It returns STATUS_SUCCESS if everything succeeded or a proper error status otherwise.

_Must_inspect_result_
NTSTATUS
SafeStorageHandleRegister(
    _In_reads_bytes_opt_(UsernameLength) PCHAR Username,
    _In_ USHORT UsernameLength,
    _In_reads_bytes_opt_(PasswordLength) PCHAR Password, 
    _In_ USHORT PasswordLength);
NullByte55
  • 11
  • 1
  • Can you provide more detail about what the errors you are seeing are? I think I see some issues with the way the function is being called. – ryyker Jan 07 '21 at 14:06

1 Answers1

1

Addressing the call to SafeStorageHandleRegister():

Given your original prototype:

SafeStorageHandleRegister(
_In_reads_bytes_opt_(UsernameLength) PCHAR Username,
_In_ USHORT UsernameLength,
_In_reads_bytes_opt_(PasswordLength) PCHAR Password, 
_In_ USHORT PasswordLength);

One issue is that in your call:

SafeStorageHandleRegister(arg1, (USHORT)strlen(arg1), arg2, (USHORT)strlen(arg2));

...the number of bytes specified in arguments 3 & 4 does not include room for the null byte, resulting in an incorrect number of bytes value. strlen() does not include \0 in its calculation, but \0 is at the end of all C strings (which are being used here.) Use sizeof(arg1) and sizeof(arg2) instead. eg:

SafeStorageHandleRegister(arg1, (USHORT)sizeof(arg1), arg2, (USHORT)sizeof(arg2));

And, because the sizeof macro returns size_t if this is your function prototype, (i.e. one that you can modify.) I suggest changing it from using USHORT to size_t for the 2nd and 4th arguments:

SafeStorageHandleRegister(
_In_reads_bytes_opt_(UsernameLength) PCHAR Username,
_In_ size_t UsernameLength,
_In_reads_bytes_opt_(PasswordLength) PCHAR Password, 
_In_ size_t PasswordLength);

...making it more readable because there will be no casts:

SafeStorageHandleRegister(arg1, sizeof(arg1), arg2, sizeof(arg2));

_Addressing potential issues for SAL notations:

This may or may not be causing your failure, but important to note anyway...

"If the caller is not allowed to pass in a null pointer, use _In_ or _Out_ instead of _In_opt_ or _Out_opt_. This applies even to a function that checks its parameters and returns an error if it is NULL when it should not be."...

So, for example:

// Incorrect
void Func1(_Out_opt_ int *p1)
{
    *p = 1;
}

// Correct
void Func2(_Out_ int *p1)
{
    *p = 1;
}

Since you do not want your functions to have the option to pass NULL pointers it would be good to consider modifying the SAL notation from _In_reads_bytes_opt_ to _In_reads_bytes_ (removing the option)

 SafeStorageHandleRegister(
_In_reads_bytes(UsernameLength) PCHAR Username,
_In_ size_t UsernameLength,
_In_reads_bytes(PasswordLength) PCHAR Password, 
_In_ size_t PasswordLength);

Much more on SAL notations.

ryyker
  • 22,849
  • 3
  • 43
  • 87