diff --git a/src/windows_secure_file.c b/src/windows_secure_file.c index 9a94ad3..3acdc48 100644 --- a/src/windows_secure_file.c +++ b/src/windows_secure_file.c @@ -28,6 +28,7 @@ #include "string_utils.h" #include "error_translation.h" #include "secured_env_vars.h" +#include "io_utils.h" #if defined (HAVE_NTIFS) #include @@ -523,11 +524,27 @@ static bool get_System_Volume(char *winSysVol, size_t winSysVolLen) return validsystemvol; } -static bool is_Folder_Secure(const char* securityDescriptorString, const char* dirptr) +FUNC_ATTR_PRINTF(2, 3) static void set_dir_security_output_error_message(char **outputError, const char* format, ...) +{ + if (outputError != M_NULLPTR) + { + va_list args; + va_start(args, format); + int result = vasprintf(outputError, format, args); + va_end(args); + if (result < 0 && *outputError != M_NULLPTR) + { + safe_free(outputError); + } + } +} + +static bool is_Folder_Secure(const char* securityDescriptorString, const char* dirptr, char **outputError) { bool secure = true; if (securityDescriptorString == M_NULLPTR || dirptr == M_NULLPTR) { + set_dir_security_output_error_message(outputError, "Invalid security descriptor string or directory given.\n"); return false; } DECLARE_ZERO_INIT_ARRAY(char, windowsSystemVolume, MAX_PATH); @@ -549,36 +566,42 @@ static bool is_Folder_Secure(const char* securityDescriptorString, const char* d if (FALSE == ConvertStringSidToSidA(mySidStr, &mySid)) { /* Handle Error */ + set_dir_security_output_error_message(outputError, "Failed to convert current user's SID string to sid structure\n"); secure = false; break; } if (FALSE == IsValidSid(mySid)) { /* Handle Error */ + set_dir_security_output_error_message(outputError, "Invalid sid\n"); secure = false; break; } if (FALSE == ConvertStringSecurityDescriptorToSecurityDescriptorA(securityDescriptorString, SDDL_REVISION, &secdesc, &secdesclen)) { /* Handle Error */ + set_dir_security_output_error_message(outputError, "Failed to convert security descriptor string to security descriptor structure\n"); secure = false; break; } if (FALSE == IsValidSecurityDescriptor(secdesc)) { /* Handle Error */ + set_dir_security_output_error_message(outputError, "Invalid security descriptor\n"); secure = false; break; } if (FALSE == GetSecurityDescriptorOwner(secdesc, &userSid, &defaultOwner)) { /* Handle Error */ + set_dir_security_output_error_message(outputError, "Failed to get security descriptor owner\n"); secure = false; break; } if (FALSE == IsValidSid(userSid)) { /* Handle Error */ + set_dir_security_output_error_message(outputError, "Invalid SID for security descriptor owner\n"); secure = false; break; } @@ -621,13 +644,13 @@ static bool is_Folder_Secure(const char* securityDescriptorString, const char* d { /* Directory is owned by someone besides user/system/administrator */ secure = false; -#if defined (_DEBUG) char* sidString = M_NULLPTR; if (ConvertSidToStringSidA(userSid, &sidString)) { - printf("Untrusted Owner SID: %s\n", sidString); + set_dir_security_output_error_message(outputError, "Directory (%s) owned by SID (not trusted): %s\n", dirptr, sidString); + LocalFree(sidString); + sidString = M_NULLPTR; } -#endif //_DEBUG break; } } @@ -636,13 +659,13 @@ static bool is_Folder_Secure(const char* securityDescriptorString, const char* d { /* Directory is owned by someone besides user/system/administrator */ secure = false; -#if defined (_DEBUG) char* sidString = M_NULLPTR; if (ConvertSidToStringSidA(userSid, &sidString)) { - printf("Untrusted Owner SID: %s\n", sidString); + set_dir_security_output_error_message(outputError, "Directory (%s) owned by SID (not trusted): %s\n", dirptr, sidString); + LocalFree(sidString); + sidString = M_NULLPTR; } -#endif //_DEBUG break; } } @@ -650,13 +673,13 @@ static bool is_Folder_Secure(const char* securityDescriptorString, const char* d { /* Directory is owned by someone besides user/system/administrator */ secure = false; -#if defined (_DEBUG) char* sidString = M_NULLPTR; if (ConvertSidToStringSidA(userSid, &sidString)) { - printf("Untrusted Owner SID: %s\n", sidString); + set_dir_security_output_error_message(outputError, "Directory (%s) owned by SID (not trusted): %s\n", dirptr, sidString); + LocalFree(sidString); + sidString = M_NULLPTR; } -#endif //_DEBUG break; } } @@ -686,6 +709,7 @@ static bool is_Folder_Secure(const char* securityDescriptorString, const char* d { /* Handle Error */ secure = false; + set_dir_security_output_error_message(outputError, "Unable to retrieve DACL from security descriptor: %s\n", dirptr); break; } @@ -693,6 +717,7 @@ static bool is_Folder_Secure(const char* securityDescriptorString, const char* d { /* Missing DACL, so cannot verify permissions */ secure = false; + set_dir_security_output_error_message(outputError, "DACL Missing. Cannot verify permissions: %s\n", dirptr); break; } @@ -700,6 +725,7 @@ static bool is_Folder_Secure(const char* securityDescriptorString, const char* d { /* Handle Error */ secure = false; + set_dir_security_output_error_message(outputError, "Invalid DACL received. Cannot verify permissions: %s\n", dirptr); break; } @@ -728,14 +754,14 @@ static bool is_Folder_Secure(const char* securityDescriptorString, const char* d if (!(allowEveryoneGroup && everyoneGroupSID != M_NULLPTR && EqualSid(aceSID, everyoneGroupSID))) { - secure = false; -#if defined (_DEBUG) char* sidString = M_NULLPTR; + secure = false; if (ConvertSidToStringSidA(aceSID, &sidString)) { - printf("Untrusted SID: %s\n", sidString); + set_dir_security_output_error_message(outputError, "Directory (%s) can be accessed by SID (not trusted, must be removed to be secure): %s\n", dirptr, sidString); + LocalFree(sidString); + sidString = M_NULLPTR; } -#endif //_DEBUG } #if defined (_DEBUG) else @@ -744,6 +770,8 @@ static bool is_Folder_Secure(const char* securityDescriptorString, const char* d if (ConvertSidToStringSidA(aceSID, &sidString)) { printf("Trusted SID: %s\n", sidString); + LocalFree(sidString); + sidString = M_NULLPTR; } } #endif //_DEBUG @@ -761,6 +789,7 @@ static bool is_Folder_Secure(const char* securityDescriptorString, const char* d } else { + set_dir_security_output_error_message(outputError, "Invalid ACE in DACL. Directory (%s) cannot be trusted\n", dirptr); secure = false; } } @@ -946,6 +975,7 @@ static bool internal_OS_Is_Directory_Secure(const char* fullpath, unsigned int n { /* handle error */ secure = false; + set_dir_security_output_error_message(outputError, "Unable to read directory attributes: %s\n", dirptr); if (appendedTrailingSlash) { safe_free(&dirptr); @@ -956,6 +986,7 @@ static bool internal_OS_Is_Directory_Secure(const char* fullpath, unsigned int n { /* handle error */ secure = false; + set_dir_security_output_error_message(outputError, "Too many symlinks in path (>%d): %s\n", MAX_SYMLINKS_IN_PATH, dirptr); free_File_Attributes(&attrs); if (appendedTrailingSlash) { @@ -1005,22 +1036,26 @@ static bool internal_OS_Is_Directory_Secure(const char* fullpath, unsigned int n } else { + set_dir_security_output_error_message(outputError, "Unable to allocate memory to check reparse point in path: %s\n", dirptr); secure = false; } } else { + set_dir_security_output_error_message(outputError, "Unable to calculate memory length to check reparse point in path: %s\n", dirptr); secure = false; } } else { + set_dir_security_output_error_message(outputError, "Unable to issue FSCTL_GET_REPASE_POINT to validate reparse point in path: %s\n", dirptr); secure = false; } safe_free_reparse_data_buf(&reparseData); } else { + set_dir_security_output_error_message(outputError, "Unable to allocate memory to check reparse point in path: %s\n", dirptr); secure = false; } CloseHandle(link); @@ -1039,6 +1074,7 @@ static bool internal_OS_Is_Directory_Secure(const char* fullpath, unsigned int n } else { + set_dir_security_output_error_message(outputError, "Unable to open handle to reparse point in path: %s\n", dirptr); secure = false; free_File_Attributes(&attrs); if (appendedTrailingSlash) @@ -1053,6 +1089,7 @@ static bool internal_OS_Is_Directory_Secure(const char* fullpath, unsigned int n { /* Not a directory */ secure = false; + set_dir_security_output_error_message(outputError, "%s is not a directory. Cannot validate as part of path.\n", dirptr); free_File_Attributes(&attrs); if (appendedTrailingSlash) { @@ -1061,7 +1098,7 @@ static bool internal_OS_Is_Directory_Secure(const char* fullpath, unsigned int n break; } - secure = is_Folder_Secure(attrs->winSecurityDescriptor, dirptr); + secure = is_Folder_Secure(attrs->winSecurityDescriptor, dirptr, outputError); if (appendedTrailingSlash) { safe_free(&dirptr);