~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/cloudconfig/windowsuserdatafiles/Carbon.cs

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
Original sources available at: https://bitbucket.org/splatteredbits/carbon
 
3
*/
 
4
 
 
5
using System;
 
6
using System.Collections.Generic;
 
7
using System.ComponentModel;
 
8
using System.Runtime.InteropServices;
 
9
using System.Security.Principal;
 
10
using System.Text;
 
11
 
 
12
namespace PSCarbon
 
13
{
 
14
        public sealed class Lsa
 
15
        {
 
16
                // ReSharper disable InconsistentNaming
 
17
                [StructLayout(LayoutKind.Sequential)]
 
18
                internal struct LSA_UNICODE_STRING
 
19
                {
 
20
                        internal LSA_UNICODE_STRING(string inputString)
 
21
                        {
 
22
                                if (inputString == null)
 
23
                                {
 
24
                                        Buffer = IntPtr.Zero;
 
25
                                        Length = 0;
 
26
                                        MaximumLength = 0;
 
27
                                }
 
28
                                else
 
29
                                {
 
30
                                        Buffer = Marshal.StringToHGlobalAuto(inputString);
 
31
                                        Length = (ushort)(inputString.Length * UnicodeEncoding.CharSize);
 
32
                                        MaximumLength = (ushort)((inputString.Length + 1) * UnicodeEncoding.CharSize);
 
33
                                }
 
34
                        }
 
35
 
 
36
                        internal ushort Length;
 
37
                        internal ushort MaximumLength;
 
38
                        internal IntPtr Buffer;
 
39
                }
 
40
 
 
41
                [StructLayout(LayoutKind.Sequential)]
 
42
                internal struct LSA_OBJECT_ATTRIBUTES
 
43
                {
 
44
                        internal uint Length;
 
45
                        internal IntPtr RootDirectory;
 
46
                        internal LSA_UNICODE_STRING ObjectName;
 
47
                        internal uint Attributes;
 
48
                        internal IntPtr SecurityDescriptor;
 
49
                        internal IntPtr SecurityQualityOfService;
 
50
                }
 
51
 
 
52
                [StructLayout(LayoutKind.Sequential)]
 
53
                public struct LUID
 
54
                {
 
55
                        public uint LowPart;
 
56
                        public int HighPart;
 
57
                }
 
58
 
 
59
                // ReSharper disable UnusedMember.Local
 
60
                private const uint POLICY_VIEW_LOCAL_INFORMATION = 0x00000001;
 
61
                private const uint POLICY_VIEW_AUDIT_INFORMATION = 0x00000002;
 
62
                private const uint POLICY_GET_PRIVATE_INFORMATION = 0x00000004;
 
63
                private const uint POLICY_TRUST_ADMIN = 0x00000008;
 
64
                private const uint POLICY_CREATE_ACCOUNT = 0x00000010;
 
65
                private const uint POLICY_CREATE_SECRET = 0x00000014;
 
66
                private const uint POLICY_CREATE_PRIVILEGE = 0x00000040;
 
67
                private const uint POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080;
 
68
                private const uint POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100;
 
69
                private const uint POLICY_AUDIT_LOG_ADMIN = 0x00000200;
 
70
                private const uint POLICY_SERVER_ADMIN = 0x00000400;
 
71
                private const uint POLICY_LOOKUP_NAMES = 0x00000800;
 
72
                private const uint POLICY_NOTIFICATION = 0x00001000;
 
73
                // ReSharper restore UnusedMember.Local
 
74
 
 
75
                [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
 
76
                public static extern bool LookupPrivilegeValue(
 
77
                        [MarshalAs(UnmanagedType.LPTStr)] string lpSystemName,
 
78
                        [MarshalAs(UnmanagedType.LPTStr)] string lpName,
 
79
                        out LUID lpLuid);
 
80
 
 
81
                [DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
 
82
                private static extern uint LsaAddAccountRights(
 
83
                        IntPtr PolicyHandle,
 
84
                        IntPtr AccountSid,
 
85
                        LSA_UNICODE_STRING[] UserRights,
 
86
                        uint CountOfRights);
 
87
 
 
88
                [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = false)]
 
89
                private static extern uint LsaClose(IntPtr ObjectHandle);
 
90
 
 
91
                [DllImport("advapi32.dll", SetLastError = true)]
 
92
                private static extern uint LsaEnumerateAccountRights(IntPtr PolicyHandle,
 
93
                        IntPtr AccountSid,
 
94
                        out IntPtr UserRights,
 
95
                        out uint CountOfRights
 
96
                        );
 
97
 
 
98
                [DllImport("advapi32.dll", SetLastError = true)]
 
99
                private static extern uint LsaFreeMemory(IntPtr pBuffer);
 
100
 
 
101
                [DllImport("advapi32.dll")]
 
102
                private static extern int LsaNtStatusToWinError(long status);
 
103
 
 
104
                [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
 
105
                private static extern uint LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, uint DesiredAccess, out IntPtr PolicyHandle );
 
106
 
 
107
                [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)]
 
108
                static extern uint LsaRemoveAccountRights(
 
109
                        IntPtr PolicyHandle,
 
110
                        IntPtr AccountSid,
 
111
                        [MarshalAs(UnmanagedType.U1)]
 
112
                        bool AllRights,
 
113
                        LSA_UNICODE_STRING[] UserRights,
 
114
                        uint CountOfRights);
 
115
                // ReSharper restore InconsistentNaming
 
116
 
 
117
                private static IntPtr GetIdentitySid(string identity)
 
118
                {
 
119
                        SecurityIdentifier sid =
 
120
                                new NTAccount(identity).Translate(typeof (SecurityIdentifier)) as SecurityIdentifier;
 
121
                        if (sid == null)
 
122
                        {
 
123
                                throw new ArgumentException(string.Format("Account {0} not found.", identity));
 
124
                        }
 
125
                        byte[] sidBytes = new byte[sid.BinaryLength];
 
126
                        sid.GetBinaryForm(sidBytes, 0);
 
127
                        System.IntPtr sidPtr = Marshal.AllocHGlobal(sidBytes.Length);
 
128
                        Marshal.Copy(sidBytes, 0, sidPtr, sidBytes.Length);
 
129
                        return sidPtr;
 
130
                }
 
131
 
 
132
                private static IntPtr GetLsaPolicyHandle()
 
133
                {
 
134
                        string computerName = Environment.MachineName;
 
135
                        IntPtr hPolicy;
 
136
                        LSA_OBJECT_ATTRIBUTES objectAttributes = new LSA_OBJECT_ATTRIBUTES();
 
137
                        objectAttributes.Length = 0;
 
138
                        objectAttributes.RootDirectory = IntPtr.Zero;
 
139
                        objectAttributes.Attributes = 0;
 
140
                        objectAttributes.SecurityDescriptor = IntPtr.Zero;
 
141
                        objectAttributes.SecurityQualityOfService = IntPtr.Zero;
 
142
 
 
143
                        const uint ACCESS_MASK = POLICY_CREATE_SECRET | POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION;
 
144
                        LSA_UNICODE_STRING machineNameLsa = new LSA_UNICODE_STRING(computerName);
 
145
                        uint result = LsaOpenPolicy(ref machineNameLsa, ref objectAttributes, ACCESS_MASK, out hPolicy);
 
146
                        HandleLsaResult(result);
 
147
                        return hPolicy;
 
148
                }
 
149
 
 
150
                public static string[] GetPrivileges(string identity)
 
151
                {
 
152
                        IntPtr sidPtr = GetIdentitySid(identity);
 
153
                        IntPtr hPolicy = GetLsaPolicyHandle();
 
154
                        IntPtr rightsPtr = IntPtr.Zero;
 
155
 
 
156
                        try
 
157
                        {
 
158
 
 
159
                                List<string> privileges = new List<string>();
 
160
 
 
161
                                uint rightsCount;
 
162
                                uint result = LsaEnumerateAccountRights(hPolicy, sidPtr, out rightsPtr, out rightsCount);
 
163
                                int win32ErrorCode = LsaNtStatusToWinError(result);
 
164
                                // the user has no privileges
 
165
                                if( win32ErrorCode == STATUS_OBJECT_NAME_NOT_FOUND )
 
166
                                {
 
167
                                        return new string[0];
 
168
                                }
 
169
                                HandleLsaResult(result);
 
170
 
 
171
                                LSA_UNICODE_STRING myLsaus = new LSA_UNICODE_STRING();
 
172
                                for (ulong i = 0; i < rightsCount; i++)
 
173
                                {
 
174
                                        IntPtr itemAddr = new IntPtr(rightsPtr.ToInt64() + (long) (i*(ulong) Marshal.SizeOf(myLsaus)));
 
175
                                        myLsaus = (LSA_UNICODE_STRING) Marshal.PtrToStructure(itemAddr, myLsaus.GetType());
 
176
                                        char[] cvt = new char[myLsaus.Length/UnicodeEncoding.CharSize];
 
177
                                        Marshal.Copy(myLsaus.Buffer, cvt, 0, myLsaus.Length/UnicodeEncoding.CharSize);
 
178
                                        string thisRight = new string(cvt);
 
179
                                        privileges.Add(thisRight);
 
180
                                }
 
181
                                return privileges.ToArray();
 
182
                        }
 
183
                        finally
 
184
                        {
 
185
                                Marshal.FreeHGlobal(sidPtr);
 
186
                                uint result = LsaClose(hPolicy);
 
187
                                HandleLsaResult(result);
 
188
                                result = LsaFreeMemory(rightsPtr);
 
189
                                HandleLsaResult(result);
 
190
                        }
 
191
                }
 
192
 
 
193
                public static void GrantPrivileges(string identity, string[] privileges)
 
194
                {
 
195
                        IntPtr sidPtr = GetIdentitySid(identity);
 
196
                        IntPtr hPolicy = GetLsaPolicyHandle();
 
197
 
 
198
                        try
 
199
                        {
 
200
                                LSA_UNICODE_STRING[] lsaPrivileges = StringsToLsaStrings(privileges);
 
201
                                uint result = LsaAddAccountRights(hPolicy, sidPtr, lsaPrivileges, (uint)lsaPrivileges.Length);
 
202
                                HandleLsaResult(result);
 
203
                        }
 
204
                        finally
 
205
                        {
 
206
                                Marshal.FreeHGlobal(sidPtr);
 
207
                                uint result = LsaClose(hPolicy);
 
208
                                HandleLsaResult(result);
 
209
                        }
 
210
                }
 
211
 
 
212
                const int STATUS_SUCCESS = 0x0;
 
213
                const int STATUS_OBJECT_NAME_NOT_FOUND = 0x00000002;
 
214
                const int STATUS_ACCESS_DENIED = 0x00000005;
 
215
                const int STATUS_INVALID_HANDLE = 0x00000006;
 
216
                const int STATUS_UNSUCCESSFUL = 0x0000001F;
 
217
                const int STATUS_INVALID_PARAMETER = 0x00000057;
 
218
                const int STATUS_NO_SUCH_PRIVILEGE = 0x00000521;
 
219
                const int STATUS_INVALID_SERVER_STATE = 0x00000548;
 
220
                const int STATUS_INTERNAL_DB_ERROR = 0x00000567;
 
221
                const int STATUS_INSUFFICIENT_RESOURCES = 0x000005AA;
 
222
 
 
223
                private static Dictionary<int, string> ErrorMessages = new Dictionary<int, string>();
 
224
                public Lsa () {
 
225
                        ErrorMessages.Add(STATUS_ACCESS_DENIED, "Access denied. Caller does not have the appropriate access to complete the operation.");
 
226
                        ErrorMessages.Add(STATUS_INVALID_HANDLE, "Invalid handle. Indicates an object or RPC handle is not valid in the context used.");
 
227
                        ErrorMessages.Add(STATUS_UNSUCCESSFUL, "Unsuccessful. Generic failure, such as RPC connection failure.");
 
228
                        ErrorMessages.Add(STATUS_INVALID_PARAMETER, "Invalid parameter. One of the parameters is not valid.");
 
229
                        ErrorMessages.Add(STATUS_NO_SUCH_PRIVILEGE, "No such privilege. Indicates a specified privilege does not exist.");
 
230
                        ErrorMessages.Add(STATUS_INVALID_SERVER_STATE, "Invalid server state. Indicates the LSA server is currently disabled.");
 
231
                        ErrorMessages.Add(STATUS_INTERNAL_DB_ERROR, "Internal database error. The LSA database contains an internal inconsistency.");
 
232
                        ErrorMessages.Add(STATUS_INSUFFICIENT_RESOURCES, "Insufficient resources. There are not enough system resources (such as memory to allocate buffers) to complete the call.");
 
233
                        ErrorMessages.Add(STATUS_OBJECT_NAME_NOT_FOUND, "Object name not found. An object in the LSA policy database was not found. The object may have been specified either by SID or by name, depending on its type.");
 
234
                }
 
235
 
 
236
                private static void HandleLsaResult(uint returnCode)
 
237
                {
 
238
                        int win32ErrorCode = LsaNtStatusToWinError(returnCode);
 
239
 
 
240
                        if( win32ErrorCode == STATUS_SUCCESS)
 
241
                                return;
 
242
 
 
243
                        if( ErrorMessages.ContainsKey(win32ErrorCode) )
 
244
                        {
 
245
                                throw new Win32Exception(win32ErrorCode, ErrorMessages[win32ErrorCode]);
 
246
                        }
 
247
 
 
248
                        throw new Win32Exception(win32ErrorCode);
 
249
                }
 
250
 
 
251
                public static void RevokePrivileges(string identity, string[] privileges)
 
252
                {
 
253
                        IntPtr sidPtr = GetIdentitySid(identity);
 
254
                        IntPtr hPolicy = GetLsaPolicyHandle();
 
255
 
 
256
                        try
 
257
                        {
 
258
                                string[] currentPrivileges = GetPrivileges(identity);
 
259
                                if (currentPrivileges.Length == 0)
 
260
                                {
 
261
                                        return;
 
262
                                }
 
263
                                LSA_UNICODE_STRING[] lsaPrivileges = StringsToLsaStrings(privileges);
 
264
                                uint result = LsaRemoveAccountRights(hPolicy, sidPtr, false, lsaPrivileges, (uint)lsaPrivileges.Length);
 
265
                                HandleLsaResult(result);
 
266
                        }
 
267
                        finally
 
268
                        {
 
269
                                Marshal.FreeHGlobal(sidPtr);
 
270
                                uint result = LsaClose(hPolicy);
 
271
                                HandleLsaResult(result);
 
272
                        }
 
273
 
 
274
                }
 
275
 
 
276
                private static LSA_UNICODE_STRING[] StringsToLsaStrings(string[] privileges)
 
277
                {
 
278
                        LSA_UNICODE_STRING[] lsaPrivileges = new LSA_UNICODE_STRING[privileges.Length];
 
279
                        for (int idx = 0; idx < privileges.Length; ++idx)
 
280
                        {
 
281
                                lsaPrivileges[idx] = new LSA_UNICODE_STRING(privileges[idx]);
 
282
                        }
 
283
                        return lsaPrivileges;
 
284
                }
 
285
        }
 
286
}