locked
setsystemtime fails with ERROR_PRIVILEGE_NOT_HELD (1314) RRS feed

  • Question

  • In all previous version of Windows this worked fine.

    An application calls SetSystemTime.

    To run as a low privileged user, the administrator tools feature:

    "

    You can assign privileges to accounts either by using the Local Security Policy Microsoft Management Console (MMC) snap-in (Secpol.msc)

    "

    is modified to allow EVERYONE to modify system time and time zone.

    This has worked for DECADES ( NT, 2K, VISTA, XP )

    What must I do to get this to work on WIndows 7?

    Please advise


    BDM

    Wednesday, June 24, 2015 6:09 PM

All replies

  • Show your code and UAC manifest. 


    Visual C++ MVP

    Thursday, June 25, 2015 2:29 PM
  •  int status = DB_Mailslot_getans ( &lCvrsFile, (LPSTR)&buffer, sizeof(buffer),  iCvrsNum );
      if (status == DBER_ok)
      {
         SYSTEMTIME *st = (SYSTEMTIME *)buffer.buf;
         if ( SetSystemTime( st ) )
         {
    	 bLogonChangedTime = TRUE;
    	 PostMessage(HWND_BROADCAST, WM_TIMECHANGE, 0, 0L);
         }
         else
         {
    	 static char buffe[512];
    	 DWORD dwWord = GetLastError();
    	wsprintf( buffe, "SetSystemTime error %d", dwWord );			 
             MessageBox( hWnd,  buffe, lpsAppname, MB_ICONSTOP | MB_OK);
          }
     }
    

    The "SYSTEMTIME *st = (SYSTEMTIME *)buffer.buf;"  is a binary blob of data returned by a server machine.  This code must execute while under a restricted-access user being logged on.  This is why the "Local Security Policy" is modified to all EVERYONE to change system time and time zone

    Boyd


    BDM

    Thursday, June 25, 2015 2:40 PM
  • Check the status of the SeSystemtimePrivilege in Process Explorer. If the process does not have the privilege, then you need to check your local security policy. If the policy is disabled, you need to enable the privilege before changing the system time. 


    Visual C++ MVP

    Thursday, June 25, 2015 3:20 PM
  • As this image shows, the task has the Privileges in question disabled but the Local Security Policy permits Everyone.

    At the moment, it is running with an Administrator logged on, but when a USER is logged on, it does not work.

    This used to work in NT, 2K, Vista, XP....

    Boyd

     

    BDM

    Thursday, June 25, 2015 4:02 PM
  • Are you using AdjustTokenPrivileges to enable the privilege on your current token before making the call?  If not, you should be.  If so, what error code is it failing with?  Privileges being enabled/disabled are different from the user's ability to be granted them.  

    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    Thursday, June 25, 2015 4:58 PM
  • Ok, so I went through the hoops of AdjustTokenPrivileges and now the code works as it should.

    My concern is still that the code worked as it was since WinNT days.  This is going to be a nightmare to adjust the code for every place this sort of change is required.  Why does the "old" way of configuring this to work not work any more?

    Boyd


    BDM

    Thursday, June 25, 2015 5:25 PM
  • It has always been best practice to do this before making system calls that require specific privileges, but it wasn't always necessary for all of the privilege types.  It is more secure to not enable all possible privileges on a process by default since it then requires any exploit code to include that as well, therefore making its size larger, which matters for many types of exploits.  I don't have anything more specific on this particular change and when/why it happened though, sorry!

    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    Thursday, June 25, 2015 5:32 PM
  • Looks like the documentation is no longer true. From https://msdn.microsoft.com/en-us/library/windows/desktop/ms724942%28v=vs.85%29.aspx:

    The SetSystemTime function enables the SE_SYSTEMTIME_NAME privilege before changing the system time and disables the privilege before returning.



    Visual C++ MVP

    Thursday, June 25, 2015 5:40 PM
  • I looked it up, and it still does attempt to enable/disable the privilege.  However, it does so based on the current thread's context, not the process context, and it doesn't account for impersonation.

    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    Thursday, June 25, 2015 5:49 PM
  • I'm not sure what the distinction is, but my application executes SetSystemTime as part of a WM_TIMER function of the main window.

    Boyd


    BDM

    Thursday, June 25, 2015 6:14 PM
  • Hi,

    This seems to be a vicious circle.

    As per suggestions, I developed the following code:

    HANDLE hToken;
    
    BOOL SetPrivilege( HWND hWnd,
        HANDLE hToken,          // access token handle
        LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
        BOOL bEnablePrivilege   // to enable or disable privilege
        ) 
    {
    
    
    	
    
        TOKEN_PRIVILEGES tp;
        LUID luid;
    	static char buffe[512];
    
        if ( !LookupPrivilegeValue( 
                NULL,            // lookup privilege on local system
                lpszPrivilege,   // privilege to lookup 
                &luid ) )        // receives LUID of privilege
        {
    			 DWORD dwWord = GetLastError();
    			 wsprintf( buffe, "LookupPrivilegeValue  error %d", dwWord );			 
                 MessageBox( hWnd,  buffe, lpsAppname, MB_ICONSTOP | MB_OK);
            return FALSE; 
        }
    
        tp.PrivilegeCount = 1;
        tp.Privileges[0].Luid = luid;
        if (bEnablePrivilege)
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        else
            tp.Privileges[0].Attributes = 0;
    
        // Enable the privilege or disable all privileges.
    
        if ( !AdjustTokenPrivileges(
               hToken, 
               FALSE, 
               &tp, 
               sizeof(TOKEN_PRIVILEGES), 
               (PTOKEN_PRIVILEGES) NULL, 
               (PDWORD) NULL) )
        { 
    			 DWORD dwWord = GetLastError();
    			 wsprintf( buffe, "AdjustTokenPrivileges  error %d", dwWord );			 
                 MessageBox( hWnd,  buffe, lpsAppname, MB_ICONSTOP | MB_OK);
              return FALSE; 
        } 
    
        
    	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
    
        {
               MessageBox( hWnd,  "The token does not have the specified privilege", lpsAppname, MB_ICONSTOP | MB_OK);
              return FALSE;
        } 
    	
    
        return TRUE;
    }
    
    
    
    
    
    
    ......
    
    
    
       OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
       SetPrivilege( hWnd, hToken,          // access token handle
                           SE_SYSTEMTIME_NAME,  // name of privilege to enable/disable
    					   TRUE );   // to enable or disable privilege
       CloseHandle(hToken);
    

    And guess what?

    While running as a USER, the code does not have the privilege to adjust the privilege.

    Ok, Now What???????


    BDM

    Thursday, July 9, 2015 4:14 PM
  • The privilege to set system time is protected by UAC; without considering any discussion of security practices and why it was added to UAC, if you don't give account the assigned right to set the system time, the privilege can't be granted by AdjustTokenPrivileges.  There are a couple of ways to remedy this:

    1. Require elevation for either the whole app or the portion of the app that needs to change the system time
    2. Grant the user(s) the rights assignment via secpol.msc, group policy, or LSAAddAccountRights.

    Is the screenshot before the same system where this is currently running?  Is the user account also a member of the Administrators group?  Assuming the answer to both of those is yes, if the user account is a member of the Administrators group, the process must be started elevated because the privilege will be denied to the process token if it is not.  If the user isn't a member of the Administrators group, then it should work since you have added Everyone in secpol.msc already.

     

    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    Thursday, July 9, 2015 5:14 PM
  • Hi Chris,

    The screen shot is of the system and presented to demonstrate that Group Policy, User Rights Assignment, Change the System Time is set to allow EVERYONE.

    The LOGON is to an account of generic Group USER.

    Yes this should allow the USER to change the time, but as other MSFT posters have pointed out, the application must first call "AdjustTokenPrivileges" and that is where I am currently stymied (roadblock).

    Not only can the application not adjust the time, but it cannot call "AdjustTokenPrivileges" as prescribed above, to enable adjusting the time.

    Thus the vicious circle.


    BDM

    Thursday, July 9, 2015 5:29 PM
  • Hi Boyd,

    I was able to test the code that you provided for AdjustTokenPrivileges and run it successfully in an MFC app when using a local user account who was not an administrator.  It would require elevation if the user were in the administrators group though and there's no way around that of which I am aware.

    Are you seeing something different?


    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    Thursday, July 9, 2015 5:33 PM
  • Yes.

    My code has executed unchanged since Windows NT days.

    Now I feel old.

    Anyway, NT, 2K, VISTA, XP, Server 2000, 2003, 2005, 2008: not a problem.

    Windows 7? Crash and burn.

    Boyd


    BDM

    Thursday, July 9, 2015 5:37 PM
  • Sorry for any confusion; I meant are you seeing the failure result for AdjustTokenPrivileges with a user who is not a local admin with the security policy defined as in the screenshot?  If so, can you take a screenshot of the security tab of the process properties for your process after the AdjustTokenPrivileges code has executed?  Here's what it looks like on my system:

    Process Explorer Screenshot

    It will fail if the user is an admin regardless of Everyone being set in the security policy if the process is not elevated.


    WinSDK Support Team Blog: http://blogs.msdn.com/b/winsdk/

    Thursday, July 9, 2015 5:44 PM
  • This is embarrassing.

    After MANY rebuilds ( with improved error messaging ) and MANY reboots, the problem seems to have gone away.

    I swear all I did was add text to Messagebox diagnostic calls.

    Boyd


    BDM

    Thursday, July 9, 2015 8:24 PM
  • I spoke too soon about flagging this as the answer.

    Now the AdjustTokenPrivileges seems to work as advertised.  It does execute and generates no error response.

    So that part, yes is now working ever so much better.

    But the initial problem of SetSystemTime is now MUCH WORSE.

    Instead of just not working, the call now causes the application to block forever.  Task Manager reports "Task not responding"  and indeed the task is not responding; and takes several "terminate process" requests to get rid of it.

    Definitely much worse now.


    BDM

    Friday, July 10, 2015 3:49 PM