Skip to content

Commit 4e36202

Browse files
committed
Modified TaskPrincipal to handle odd condition #835 where UserId is stored as DOMAIN\User rather than the SID. The Account property will now always display the name.
1 parent 56c382d commit 4e36202

File tree

2 files changed

+28
-26
lines changed

2 files changed

+28
-26
lines changed

TaskService/Task.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2227,7 +2227,12 @@ public string Account
22272227
{
22282228
var un = pn["UserId"] ?? pn["GroupId"];
22292229
if (un != null)
2230-
try { return User.FromSidString(un.InnerText).Name; } catch { return un.Value; }
2230+
try { return User.FromSidString(un.InnerText).Name; }
2231+
catch
2232+
{
2233+
try { return new User(un.InnerText).Name; }
2234+
catch { }
2235+
}
22312236
}
22322237
}
22332238
return new User(ToString()).Name;

TaskService/User.cs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,48 +6,48 @@ namespace Microsoft.Win32.TaskScheduler
66
/// <summary>Represents a system account.</summary>
77
internal class User : IEquatable<User>, IDisposable
88
{
9-
private WindowsIdentity acct;
9+
private static readonly WindowsIdentity cur = WindowsIdentity.GetCurrent();
1010
private SecurityIdentifier sid;
1111

1212
/// <summary>Initializes a new instance of the <see cref="User"/> class.</summary>
1313
/// <param name="userName">
14-
/// Name of the user. This can be in the format <c>DOMAIN\username</c> or <c>username@domain.com</c> or <c>username</c> or <c>null</c> (for current user).
14+
/// Name of the user. This can be in the format <c>DOMAIN\username</c> or <c>username@domain.com</c> or <c>username</c> or
15+
/// <c>null</c> (for current user).
1516
/// </param>
1617
public User(string userName = null)
1718
{
18-
var cur = WindowsIdentity.GetCurrent();
1919
if (string.IsNullOrEmpty(userName)) userName = null;
20-
// 2018-03-02: Hopefully not a breaking change, but by adding in the comparison of an account name without a domain and the current user, there is a
21-
// chance that current implementations will break given the condition that a local account with the same name as a domain account exists and the
22-
// intention was to prefer the local account. In such a case, the developer should prepend the user name in TaskDefinition.Principal.UserId with the
23-
// machine name of the local machine.
20+
// 2018-03-02: Hopefully not a breaking change, but by adding in the comparison of an account name without a domain and the
21+
// current user, there is a chance that current implementations will break given the condition that a local account with the same
22+
// name as a domain account exists and the intention was to prefer the local account. In such a case, the developer should
23+
// prepend the user name in TaskDefinition.Principal.UserId with the machine name of the local machine.
2424
if (userName == null || cur.Name.Equals(userName, StringComparison.InvariantCultureIgnoreCase) || GetUser(cur.Name).Equals(userName, StringComparison.InvariantCultureIgnoreCase))
2525
{
26-
acct = cur;
27-
sid = acct.User;
26+
Identity = cur;
27+
sid = Identity.User;
2828
}
2929
else if (userName.Contains("\\") && !userName.StartsWith(@"NT AUTHORITY\"))
3030
{
3131
try
3232
{
3333
using (var ds = new NativeMethods.DomainService())
3434
{
35-
acct = new WindowsIdentity(ds.CrackName(userName));
36-
sid = acct.User;
35+
Identity = new WindowsIdentity(ds.CrackName(userName));
36+
sid = Identity.User;
3737
}
3838
}
3939
catch { }
4040
}
4141

42-
if (acct == null)
42+
if (Identity == null)
4343
{
4444
if (userName != null && userName.Contains("@"))
4545
{
46-
acct = new WindowsIdentity(userName);
47-
sid = acct.User;
46+
Identity = new WindowsIdentity(userName);
47+
sid = Identity.User;
4848
}
4949

50-
if (acct == null && userName != null)
50+
if (Identity == null && userName != null)
5151
{
5252
var ntacct = new NTAccount(userName);
5353
try { sid = (SecurityIdentifier)ntacct.Translate(typeof(SecurityIdentifier)); } catch { }
@@ -63,23 +63,23 @@ string GetUser(string domUser)
6363

6464
/// <summary>Initializes a new instance of the <see cref="User"/> class.</summary>
6565
/// <param name="wid">The <see cref="WindowsIdentity"/>.</param>
66-
internal User(WindowsIdentity wid) { acct = wid; sid = wid.User; }
66+
internal User(WindowsIdentity wid) { Identity = wid; sid = wid.User; }
6767

6868
/// <summary>Gets the current user.</summary>
6969
/// <value>The current user.</value>
70-
public static User Current => new User(WindowsIdentity.GetCurrent());
70+
public static User Current => new User(cur);
7171

7272
/// <summary>Gets the identity.</summary>
7373
/// <value>The identity.</value>
74-
public WindowsIdentity Identity => acct;
74+
public WindowsIdentity Identity { get; private set; }
7575

7676
/// <summary>Gets a value indicating whether this instance is in an administrator role.</summary>
7777
/// <value><c>true</c> if this instance is an admin; otherwise, <c>false</c>.</value>
78-
public bool IsAdmin => acct != null ? new WindowsPrincipal(acct).IsInRole(WindowsBuiltInRole.Administrator) : false;
78+
public bool IsAdmin => Identity != null ? new WindowsPrincipal(Identity).IsInRole(WindowsBuiltInRole.Administrator) : false;
7979

8080
/// <summary>Gets a value indicating whether this instance is the interactive user.</summary>
8181
/// <value><c>true</c> if this instance is the current user; otherwise, <c>false</c>.</value>
82-
public bool IsCurrent => acct?.User.Equals(WindowsIdentity.GetCurrent().User) ?? false;
82+
public bool IsCurrent => Identity?.User.Equals(cur.User) ?? false;
8383

8484
/// <summary>Gets a value indicating whether this instance is a service account.</summary>
8585
/// <value><c>true</c> if this instance is a service account; otherwise, <c>false</c>.</value>
@@ -106,18 +106,15 @@ public bool IsServiceAccount
106106

107107
/// <summary>Gets the NT name (DOMAIN\username).</summary>
108108
/// <value>The name of the user.</value>
109-
public string Name => acct?.Name ?? ((NTAccount)sid?.Translate(typeof(NTAccount)))?.Value;
109+
public string Name => Identity?.Name ?? ((NTAccount)sid?.Translate(typeof(NTAccount)))?.Value;
110110

111111
/// <summary>Create a <see cref="User"/> instance from a SID string.</summary>
112112
/// <param name="sid">The SID string.</param>
113113
/// <returns>A <see cref="User"/> instance.</returns>
114114
public static User FromSidString(string sid) => new User(((NTAccount)new SecurityIdentifier(sid).Translate(typeof(NTAccount))).Value);
115115

116116
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
117-
public void Dispose()
118-
{
119-
acct?.Dispose();
120-
}
117+
public void Dispose() => Identity?.Dispose();
121118

122119
/// <summary>Determines whether the specified <see cref="System.Object"/>, is equal to this instance.</summary>
123120
/// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>

0 commit comments

Comments
 (0)