[Samba] SMB2 CREATE + ACCESS_SYSTEM_SECURITY
Steve Tice
stic6021 at gmail.com
Mon Dec 31 09:47:56 MST 2012
Jeremy Allison <jra <at> samba.org> writes:
>
> On Tue, Dec 18, 2012 at 12:24:04PM -0600, Steve Tice wrote:
> > Can anybody provide the expected response to an SMB2 CREATE request that
> > includes ACCESS_SYSTEM_SECURITY in the DesiredAccess mask? I’m particularly
> > interested in cases where the SMB client is connected as an authenticated
> > user with administrative (superuser) privileges on the share, and has made
> > the request on a directory. Should such a client expect full (read/change)
> > access to the SACL (under any conditions)?
> >
> > The question above is theoretical in nature. Practically speaking, does any
> > version of the Samba server respond correctly to the request described
> > above? I have a Windows application that makes such a request, and have
> > tested it against Samba server versions 3.5.10-125.el6 and 3.6.7. I keep
> > seeing a response of NT_STATUS_PRIVILEGE_NOT_HELD, and think that's not the
> > correct response when the client has superuser privileges - but perhaps my
> > expectation is wrong. If I make the same request while connected to a share
> > on a Windows server, the response is NT_STATUS_OK.
> >
> > Is there a Samba server configuration change I could make that would affect
> > the behavior? Is there any setup work to do prior to sending the SMB2
> > CREATE request (for example, adding a privilege)?
>
> You need to give the connected user the SeSecurity privilege.
>
> Jeremy
Agreed. The Windows app which reproduces the behavior described above adds the
following privileges after creating but before attempting to open the new
directory:
SeSecurityPrivilege
SeBackupPrivilege
SeRestorePrivilege
I just noticed that my description above is incorrect. The unexpected behavior
occurs when attempting to open (not create) a directory. Here's a copy of the
Windows application source:
--
// Reproduce-Problem.cpp : Attempt to open a directory with
ACCESS_SYSTEM_SECURITY
// set in the dwDesiredAccess argument.
//
#include "stdafx.h"
#include <windows.h>
static void Usage(_TCHAR *progName)
{
wprintf(L"Usage: %s <DirectoryToCreate>\n", progName);
}
static void ReportError(char *msg)
{
DWORD le = GetLastError();
printf("***ERROR*** %s; error code: %d\n", msg, le);
}
static BOOL CloseProcessToken(HANDLE pt)
{
BOOL ptClosed = CloseHandle(pt);
if (FALSE == ptClosed) {
printf(" Unable to CloseHandle on ProcessToken.\n");
}
return ptClosed;
}
static void PrintCurrentPrivileges(void)
{
printf("Attempting to print current privileges...\n");
HANDLE pt;
BOOL ptOpened = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &pt);
if (FALSE == ptOpened) {
ReportError(" Unable to OpenProcessToken.");
return;
}
DWORD rl;
TOKEN_PRIVILEGES tokenInfo[32];
BOOL tokenInfoFetched = GetTokenInformation(pt, TokenPrivileges,
&tokenInfo, sizeof(tokenInfo), &rl);
if (FALSE == tokenInfoFetched) {
ReportError(" Unable to GetTokenInformation.");
printf(" sizeof(tokenInfo): %u; required: %u\n",
sizeof(tokenInfo), rl);
CloseProcessToken(pt);
return;
}
for (unsigned int i = 0; i < tokenInfo[0].PrivilegeCount; ++i) {
TCHAR privName[256];
DWORD pnSize = 256;
BOOL lookedUp = LookupPrivilegeName((LPCWSTR) NULL,
&tokenInfo[0].Privileges[i].Luid, privName, &pnSize);
if (FALSE == lookedUp) {
ReportError(" Unable to LookupPrivilegeName.");
printf(" sizeof(privName): %u; required: %u\n",
sizeof(privName), pnSize);
CloseProcessToken(pt);
return;
}
wprintf(L"Privilege %u: LUID = %s, Attributes = 0x%X\n", i,
privName, tokenInfo[0].Privileges[i].Attributes);
}
CloseProcessToken(pt);
printf("All current privileges have been printed.\n");
}
static BOOL AddPrivilege(const wchar_t *privilege)
{
HANDLE pt;
BOOL ptOpened = OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &pt);
if (FALSE == ptOpened) {
printf(" Unable to OpenProcessToken.\n");
return FALSE;
}
LUID luid;
BOOL lookedUp = LookupPrivilegeValue((LPCWSTR) NULL, privilege, &luid);
if (FALSE == lookedUp) {
printf(" Unable to LookupPrivilegeValue.\n");
CloseProcessToken(pt);
return FALSE;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
BOOL privAdjusted = AdjustTokenPrivileges(pt, FALSE, &tp,
sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL);
if (FALSE == privAdjusted) {
printf(" Unable to AdjustTokenPrivileges.\n");
CloseProcessToken(pt);
return FALSE;
}
if (ERROR_NOT_ALL_ASSIGNED == GetLastError()) {
wprintf(L" The token does not have the privilege '%s'.\n",
privilege);
}
if (FALSE == CloseProcessToken(pt)) {
return FALSE;
}
return TRUE;
}
int _tmain(int argc, _TCHAR* argv[])
{
if (argc != 2) {
Usage(argv[0]);
return 22;
}
printf("Attempting to reproduce failure when opening directory with
ACCESS_SYSTEM_SECURITY set.\n");
wprintf(L"Attempting to create directory\n '%s'.\n", argv[1]);
BOOL dirCreated = CreateDirectory(argv[1], (LPSECURITY_ATTRIBUTES)
NULL);
if (FALSE == dirCreated) {
ReportError("Unable to create directory");
return 1;
}
BOOL privilegeAdded = AddPrivilege(SE_SECURITY_NAME);
if (FALSE == privilegeAdded) {
ReportError("Unable to add privilege SE_SECURITY_NAME");
return 1;
}
privilegeAdded = AddPrivilege(SE_BACKUP_NAME);
if (FALSE == privilegeAdded) {
ReportError("Unable to add privilege SE_SECURITY_NAME");
return 1;
}
privilegeAdded = AddPrivilege(SE_RESTORE_NAME);
if (FALSE == privilegeAdded) {
ReportError("Unable to add privilege SE_SECURITY_NAME");
return 1;
}
PrintCurrentPrivileges();
//
// This is the open directory operation that works with Windows and
fails with Samba.
//
HANDLE rc = CreateFile(argv[1], (GENERIC_READ | GENERIC_WRITE |
ACCESS_SYSTEM_SECURITY),
(DWORD) 0, (LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
(FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_BACKUP_SEMANTICS), (HANDLE) NULL);
if (INVALID_HANDLE_VALUE == rc) {
ReportError("Unable to open directory via CreateFile");
return 1;
}
printf("Success. The specified directory was created and opened via
CreateFile.\n");
return 0;
}
More information about the samba
mailing list