Jeremy Allison 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
static void Usage(_TCHAR *progName)
{
wprintf(L"Usage: %s \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("