1 //
2 // WindowsPrincipal.cs: Windows IPrincipal implementation
3 //
4 // Author:
5 //	Sebastien Pouliot (sebastien@ximian.com)
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 
30 using System.Collections;
31 using System.Runtime.CompilerServices;
32 using System.Runtime.InteropServices;
33 using System.Security.Claims;
34 
35 namespace System.Security.Principal {
36 
37 	[Serializable]
38 	[ComVisible (true)]
39 	public class WindowsPrincipal :
40 		ClaimsPrincipal
41 	{
42 		private WindowsIdentity _identity;
43 		// http://groups.google.ca/groups?q=WindowsPrincipal+m_roles&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=OghXf4OgCHA.4228%40tkmsftngp08&rnum=4
44 		private string [] m_roles;
45 
46 		// case sensitivity versus number of groups
47 		// http://groups.google.ca/groups?q=WindowsPrincipal+m_roles&hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=%23JEMHsMQCHA.1916%40tkmsftngp13&rnum=5
48 
WindowsPrincipal(WindowsIdentity ntIdentity)49 		public WindowsPrincipal (WindowsIdentity ntIdentity)
50 		{
51 			if (ntIdentity == null)
52 				throw new ArgumentNullException ("ntIdentity");
53 
54 			_identity = ntIdentity;
55 		}
56 
57 		// properties
58 		override
59 		public IIdentity Identity {
60 			get { return _identity; }
61 		}
62 
63 		// methods
64 
IsInRole(int rid)65 		public virtual bool IsInRole (int rid)
66 		{
67 			if (Environment.IsUnix) {
68 				return IsMemberOfGroupId (Token, (IntPtr) rid);
69 			}
70 			else {
71 				string role = null;
72 				switch (rid) {
73 					case 544: // Administrator
74 						role = "BUILTIN\\Administrators";
75 						break;
76 					case 545: // User
77 						role = "BUILTIN\\Users";
78 						break;
79 					case 546: // Guest
80 						role = "BUILTIN\\Guests";
81 						break;
82 					case 547: // PowerUser
83 						role = "BUILTIN\\Power Users";
84 						break;
85 					case 548: // AccountOperator
86 						role = "BUILTIN\\Account Operators";
87 						break;
88 					case 549: // SystemOperator
89 						role = "BUILTIN\\System Operators";
90 						break;
91 					case 550: // PrintOperator
92 						role = "BUILTIN\\Print Operators";
93 						break;
94 					case 551: // BackupOperator
95 						role = "BUILTIN\\Backup Operators";
96 						break;
97 					case 552: // Replicator
98 						role = "BUILTIN\\Replicator";
99 						break;
100 					default:
101 						return false;
102 				}
103 				return IsInRole (role);
104 			}
105 		}
106 
107 		override
IsInRole(string role)108 		public bool IsInRole (string role)
109 		{
110 			if (role == null)
111 				return false;	// ArgumentNullException
112 
113 			if (Environment.IsUnix) {
114 				// note: Posix is always case-sensitive
115 				return IsMemberOfGroupName (Token, role);
116 			}
117 			else {
118 				// Windows specific code that
119 				// (a) build the role cache like the MS framework (for compatibility)
120 				// (b) case sensitive (for Fx 1.0) and case insensitive (later Fx)
121 				if (m_roles == null) {
122 					m_roles = WindowsIdentity._GetRoles (Token);
123 				}
124 
125 				role = role.ToUpperInvariant ();
126 				foreach (string check in m_roles) {
127 					if ((check != null) && (role == check.ToUpperInvariant ()))
128 						return true;
129 				}
130 				return false;
131 			}
132 		}
133 
IsInRole(WindowsBuiltInRole role)134 		public virtual bool IsInRole (WindowsBuiltInRole role)
135 		{
136 			if (Environment.IsUnix) {
137 				// right now we only map Administrator == root
138 				string group = null;
139 				switch (role) {
140 					case WindowsBuiltInRole.Administrator:
141 						group = "root";
142 						break;
143 					default:
144 						return false;
145 				}
146 				return IsInRole (group);
147 			}
148 			else {
149 				return IsInRole ((int) role);
150 			}
151 		}
152 		[MonoTODO ("not implemented")]
153 		[ComVisible (false)]
IsInRole(SecurityIdentifier sid)154 		public virtual bool IsInRole (SecurityIdentifier sid)
155 		{
156 			throw new NotImplementedException ();
157 		}
158 
159 		private IntPtr Token {
160 			get { return (_identity as WindowsIdentity).Token; }
161 		}
162 
163 		// see mono/mono/metadata/security.c for implementation
164 
165 		// note: never called by Win32 code (i.e. always return false)
166 		[MethodImplAttribute (MethodImplOptions.InternalCall)]
IsMemberOfGroupId(IntPtr user, IntPtr group)167 		private extern static bool IsMemberOfGroupId (IntPtr user, IntPtr group);
168 
169 		// note: never called by Win32 code (i.e. always return false)
170 		[MethodImplAttribute (MethodImplOptions.InternalCall)]
IsMemberOfGroupName(IntPtr user, string group)171 		private extern static bool IsMemberOfGroupName (IntPtr user, string group);
172 	}
173 }
174