It is NTP, again.
Besides the integer overflow issue, not VM oriented, there is also leap seconds issue.
2012-06-25
2012-06-17
2012-06-15
Howto change file ownership in command line or by programming
Q: Changing file Ownership with PowerShell 2.0
A: Setting the owner on an ACL in Powershell
A tool is also provided by MS: takeown. But the latest comment is very interesting: he/she ended up with Cygwin's chown.
Next time, I would try both :)
And Copy&Pasted the blog from cosmoskey.blogspot.com for reference:
==================================================================================================================
I was trying to set the owner of an ACL in powershell using the following code:
PS C:\Users\Johan> $acl = get-acl c:\temp\acltest
PS C:\Users\Johan> $principal = New-Object Security.Principal.NTAccount "$env:computername\ownertestaccount"
PS C:\Users\Johan> $acl.psbase.SetOwner($principal)
PS C:\Users\Johan> set-acl -Path C:\Temp\acltest -AclObject $acl
Set-Acl : The security identifier is not allowed to be the owner of this object.
At line:1 char:8
+ set-acl <<<< -Path C:\Temp\acltest -AclObject $acl
+ CategoryInfo : InvalidOperation: (C:\Temp\acltest:String) [Set-Acl], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.SetAclCommand
PS C:\Users\Johan>
So setting this ACL doesn't work. Why? I am an administrator! OK, what happens when I start the shell with Run As Administrator?... The same result.
So now we go to google and search a bit and I found the following KB article. What it says is that we need to have the rights to do the deed. Hey, not too surprising. By default Administrators and Backup Administrators have the Restore files and directories (SeRestorePrivilege) User Right. To set the owner we need to have this right, but in the scenario above I was executing the code with a account with all this privilege.
The problem here is that the privilege is not enabled in the access token, we need to call a function called AdjustTokenPrivileges() to adjust the current access token of our process. So we need to call this function, pass in a variable saying that we need to enable a privilege and pass in the privilege we want to enable. To call this function we need to do a little bit of PInvoke. I borrowed the base of my code from pinvoke.net.
So here is my little Set-Owner function.
function Set-Owner {
param(
[System.Security.Principal.IdentityReference]$Principal=$(throw "Mandatory parameter -Principal missing."),
$File=$(throw "Mandatory parameter -File missing.")
)
if(-not (Test-Path $file)){
throw "File $file is missing."
}
if($Principal -eq $null){
throw "Principal is NULL"
}
$code = @"
using System;
using System.Runtime.InteropServices;
namespace CosmosKey.Utils
{
public class TokenManipulator
{
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr
phtok);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name,
ref long pluid);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public const string SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege";
public const string SE_AUDIT_NAME = "SeAuditPrivilege";
public const string SE_BACKUP_NAME = "SeBackupPrivilege";
public const string SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege";
public const string SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege";
public const string SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege";
public const string SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege";
public const string SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege";
public const string SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege";
public const string SE_DEBUG_NAME = "SeDebugPrivilege";
public const string SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege";
public const string SE_IMPERSONATE_NAME = "SeImpersonatePrivilege";
public const string SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege";
public const string SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege";
public const string SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege";
public const string SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege";
public const string SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege";
public const string SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege";
public const string SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege";
public const string SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege";
public const string SE_RELABEL_NAME = "SeRelabelPrivilege";
public const string SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege";
public const string SE_RESTORE_NAME = "SeRestorePrivilege";
public const string SE_SECURITY_NAME = "SeSecurityPrivilege";
public const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
public const string SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege";
public const string SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege";
public const string SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege";
public const string SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege";
public const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege";
public const string SE_TCB_NAME = "SeTcbPrivilege";
public const string SE_TIME_ZONE_NAME = "SeTimeZonePrivilege";
public const string SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege";
public const string SE_UNDOCK_NAME = "SeUndockPrivilege";
public const string SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege";
public static bool AddPrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
catch (Exception ex)
{
throw ex;
}
}
public static bool RemovePrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_DISABLED;
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
"@
$errPref = $ErrorActionPreference
$ErrorActionPreference= "silentlycontinue"
$type = [CosmosKey.Utils.TokenManipulator]
$ErrorActionPreference = $errPref
if($type -eq $null){
add-type $code
}
$acl = Get-Acl $File
$acl.psbase.SetOwner($principal)
[void][CosmosKey.Utils.TokenManipulator]::AddPrivilege([CosmosKey.Utils.TokenManipulator]::SE_RESTORE_NAME)
set-acl -Path $File -AclObject $acl -passthru
[void][CosmosKey.Utils.TokenManipulator]::RemovePrivilege([CosmosKey.Utils.TokenManipulator]::SE_RESTORE_NAME)
}
If we run this function then we will see a very different result:
PS C:\Users\Johan> get-acl C:\Temp\acltest
Directory: C:\Temp
Path Owner Access
---- ----- ------
acltest MyLaptop\OldTest BUILTIN\Administrators Allow FullCo...
PS C:\Users\Johan> set-owner $(new-object security.principal.ntaccount "$env:computername\NewTest") C:\Temp\acltest
Directory: C:\Temp
Path Owner Access
---- ----- ------
acltest MyLaptop\NewTest BUILTIN\Administrators Allow FullCo...
PS C:\Users\Johan>
In the end we got there but it took me some time... :)
A: Setting the owner on an ACL in Powershell
A tool is also provided by MS: takeown. But the latest comment is very interesting: he/she ended up with Cygwin's chown.
Next time, I would try both :)
And Copy&Pasted the blog from cosmoskey.blogspot.com for reference:
==================================================================================================================
I was trying to set the owner of an ACL in powershell using the following code:
PS C:\Users\Johan> $acl = get-acl c:\temp\acltest
PS C:\Users\Johan> $principal = New-Object Security.Principal.NTAccount "$env:computername\ownertestaccount"
PS C:\Users\Johan> $acl.psbase.SetOwner($principal)
PS C:\Users\Johan> set-acl -Path C:\Temp\acltest -AclObject $acl
Set-Acl : The security identifier is not allowed to be the owner of this object.
At line:1 char:8
+ set-acl <<<< -Path C:\Temp\acltest -AclObject $acl
+ CategoryInfo : InvalidOperation: (C:\Temp\acltest:String) [Set-Acl], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.SetAclCommand
PS C:\Users\Johan>
So setting this ACL doesn't work. Why? I am an administrator! OK, what happens when I start the shell with Run As Administrator?... The same result.
So now we go to google and search a bit and I found the following KB article. What it says is that we need to have the rights to do the deed. Hey, not too surprising. By default Administrators and Backup Administrators have the Restore files and directories (SeRestorePrivilege) User Right. To set the owner we need to have this right, but in the scenario above I was executing the code with a account with all this privilege.
The problem here is that the privilege is not enabled in the access token, we need to call a function called AdjustTokenPrivileges() to adjust the current access token of our process. So we need to call this function, pass in a variable saying that we need to enable a privilege and pass in the privilege we want to enable. To call this function we need to do a little bit of PInvoke. I borrowed the base of my code from pinvoke.net.
So here is my little Set-Owner function.
function Set-Owner {
param(
[System.Security.Principal.IdentityReference]$Principal=$(throw "Mandatory parameter -Principal missing."),
$File=$(throw "Mandatory parameter -File missing.")
)
if(-not (Test-Path $file)){
throw "File $file is missing."
}
if($Principal -eq $null){
throw "Principal is NULL"
}
$code = @"
using System;
using System.Runtime.InteropServices;
namespace CosmosKey.Utils
{
public class TokenManipulator
{
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
[DllImport("kernel32.dll", ExactSpelling = true)]
internal static extern IntPtr GetCurrentProcess();
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr
phtok);
[DllImport("advapi32.dll", SetLastError = true)]
internal static extern bool LookupPrivilegeValue(string host, string name,
ref long pluid);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal struct TokPriv1Luid
{
public int Count;
public long Luid;
public int Attr;
}
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
internal const int TOKEN_QUERY = 0x00000008;
internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
public const string SE_ASSIGNPRIMARYTOKEN_NAME = "SeAssignPrimaryTokenPrivilege";
public const string SE_AUDIT_NAME = "SeAuditPrivilege";
public const string SE_BACKUP_NAME = "SeBackupPrivilege";
public const string SE_CHANGE_NOTIFY_NAME = "SeChangeNotifyPrivilege";
public const string SE_CREATE_GLOBAL_NAME = "SeCreateGlobalPrivilege";
public const string SE_CREATE_PAGEFILE_NAME = "SeCreatePagefilePrivilege";
public const string SE_CREATE_PERMANENT_NAME = "SeCreatePermanentPrivilege";
public const string SE_CREATE_SYMBOLIC_LINK_NAME = "SeCreateSymbolicLinkPrivilege";
public const string SE_CREATE_TOKEN_NAME = "SeCreateTokenPrivilege";
public const string SE_DEBUG_NAME = "SeDebugPrivilege";
public const string SE_ENABLE_DELEGATION_NAME = "SeEnableDelegationPrivilege";
public const string SE_IMPERSONATE_NAME = "SeImpersonatePrivilege";
public const string SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege";
public const string SE_INCREASE_QUOTA_NAME = "SeIncreaseQuotaPrivilege";
public const string SE_INC_WORKING_SET_NAME = "SeIncreaseWorkingSetPrivilege";
public const string SE_LOAD_DRIVER_NAME = "SeLoadDriverPrivilege";
public const string SE_LOCK_MEMORY_NAME = "SeLockMemoryPrivilege";
public const string SE_MACHINE_ACCOUNT_NAME = "SeMachineAccountPrivilege";
public const string SE_MANAGE_VOLUME_NAME = "SeManageVolumePrivilege";
public const string SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege";
public const string SE_RELABEL_NAME = "SeRelabelPrivilege";
public const string SE_REMOTE_SHUTDOWN_NAME = "SeRemoteShutdownPrivilege";
public const string SE_RESTORE_NAME = "SeRestorePrivilege";
public const string SE_SECURITY_NAME = "SeSecurityPrivilege";
public const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
public const string SE_SYNC_AGENT_NAME = "SeSyncAgentPrivilege";
public const string SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege";
public const string SE_SYSTEM_PROFILE_NAME = "SeSystemProfilePrivilege";
public const string SE_SYSTEMTIME_NAME = "SeSystemtimePrivilege";
public const string SE_TAKE_OWNERSHIP_NAME = "SeTakeOwnershipPrivilege";
public const string SE_TCB_NAME = "SeTcbPrivilege";
public const string SE_TIME_ZONE_NAME = "SeTimeZonePrivilege";
public const string SE_TRUSTED_CREDMAN_ACCESS_NAME = "SeTrustedCredManAccessPrivilege";
public const string SE_UNDOCK_NAME = "SeUndockPrivilege";
public const string SE_UNSOLICITED_INPUT_NAME = "SeUnsolicitedInputPrivilege";
public static bool AddPrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
catch (Exception ex)
{
throw ex;
}
}
public static bool RemovePrivilege(string privilege)
{
try
{
bool retVal;
TokPriv1Luid tp;
IntPtr hproc = GetCurrentProcess();
IntPtr htok = IntPtr.Zero;
retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_DISABLED;
retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
return retVal;
}
catch (Exception ex)
{
throw ex;
}
}
}
}
"@
$errPref = $ErrorActionPreference
$ErrorActionPreference= "silentlycontinue"
$type = [CosmosKey.Utils.TokenManipulator]
$ErrorActionPreference = $errPref
if($type -eq $null){
add-type $code
}
$acl = Get-Acl $File
$acl.psbase.SetOwner($principal)
[void][CosmosKey.Utils.TokenManipulator]::AddPrivilege([CosmosKey.Utils.TokenManipulator]::SE_RESTORE_NAME)
set-acl -Path $File -AclObject $acl -passthru
[void][CosmosKey.Utils.TokenManipulator]::RemovePrivilege([CosmosKey.Utils.TokenManipulator]::SE_RESTORE_NAME)
}
If we run this function then we will see a very different result:
PS C:\Users\Johan> get-acl C:\Temp\acltest
Directory: C:\Temp
Path Owner Access
---- ----- ------
acltest MyLaptop\OldTest BUILTIN\Administrators Allow FullCo...
PS C:\Users\Johan> set-owner $(new-object security.principal.ntaccount "$env:computername\NewTest") C:\Temp\acltest
Directory: C:\Temp
Path Owner Access
---- ----- ------
acltest MyLaptop\NewTest BUILTIN\Administrators Allow FullCo...
PS C:\Users\Johan>
In the end we got there but it took me some time... :)
2012-06-06
琐事23
上周六,取草稿。
上周日,天色不好,窝家里。下午果然暴雨,持续时间倒是不长。
吃完晚饭,审美理发。
一则,一直没空去常去的理发店理发,头发太长了;二则,走到审美不过50m;三则,有一个优惠券,洗剪吹18.00。
指定理发店,自2007年就常去。算上这次,5年间,只有3次是在其他地方理发的。
一次是在育新花园路北的小理发店;剩下两次都是在这家审美,上次似乎花了38.00,只是稍稍剪短,所谓发型随便他折腾,没什么好,也没什么不好。
这次,很有吐槽点:据说是欧莱雅的师傅主刀,然后加上一个小姐,围着我疯狂推销欧莱雅的某款(滋养头皮、防治脱发、调理)产品(药品?)……
开始时,他们也没有直接推销,然后在附和他们的过程中,就被绕进去了。然后就一直不得安宁了:估计是暴雨的余威,加上时间比较晚了,再没有其他目标了。
不过理发倒是很给力:和平常一样,只要求耳朵上和脖颈处剪短一点,结果还真的往短了剪,理着理着,搞得我都有点恐慌了——不会搞成平头、板寸了吧……
周一,新sprint开始。
凌晨,老鼠在暖气片的复合板罩子里啃掉进去的报纸,把我吵醒了。轰不出来,只好在外面再用报纸粘的严严实实,把出路堵死。
晚上,看草稿。
老鼠继续在里面啃,还想钻出来,响动很大。半夜起来好几次……于是,亚马逊上定粘鼠板。
周二,one-one。
上午,收到粘鼠板。中午,饭后摆放粘鼠板,碗筷尚未收拾妥当,老鼠不知是被诱惑的,还是给吓到了,吱吱直叫,被轰到墙脚后,小命就玩完了。
晚上,探探网上别人的路线,骑了45km。天色暗下来才发现,尾灯拿去和老鼠斗阵后,忘了装回了。
上周日,天色不好,窝家里。下午果然暴雨,持续时间倒是不长。
吃完晚饭,审美理发。
一则,一直没空去常去的理发店理发,头发太长了;二则,走到审美不过50m;三则,有一个优惠券,洗剪吹18.00。
指定理发店,自2007年就常去。算上这次,5年间,只有3次是在其他地方理发的。
一次是在育新花园路北的小理发店;剩下两次都是在这家审美,上次似乎花了38.00,只是稍稍剪短,所谓发型随便他折腾,没什么好,也没什么不好。
这次,很有吐槽点:据说是欧莱雅的师傅主刀,然后加上一个小姐,围着我疯狂推销欧莱雅的某款(滋养头皮、防治脱发、调理)产品(药品?)……
开始时,他们也没有直接推销,然后在附和他们的过程中,就被绕进去了。然后就一直不得安宁了:估计是暴雨的余威,加上时间比较晚了,再没有其他目标了。
不过理发倒是很给力:和平常一样,只要求耳朵上和脖颈处剪短一点,结果还真的往短了剪,理着理着,搞得我都有点恐慌了——不会搞成平头、板寸了吧……
周一,新sprint开始。
凌晨,老鼠在暖气片的复合板罩子里啃掉进去的报纸,把我吵醒了。轰不出来,只好在外面再用报纸粘的严严实实,把出路堵死。
晚上,看草稿。
老鼠继续在里面啃,还想钻出来,响动很大。半夜起来好几次……于是,亚马逊上定粘鼠板。
周二,one-one。
上午,收到粘鼠板。中午,饭后摆放粘鼠板,碗筷尚未收拾妥当,老鼠不知是被诱惑的,还是给吓到了,吱吱直叫,被轰到墙脚后,小命就玩完了。
晚上,探探网上别人的路线,骑了45km。天色暗下来才发现,尾灯拿去和老鼠斗阵后,忘了装回了。
Subscribe to:
Posts (Atom)