]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/sec_helper.cc
2003-09-15 Pierre Humblet <pierre.humblet@ieee.org>
[newlib-cygwin.git] / winsup / cygwin / sec_helper.cc
CommitLineData
c0d1968a
CV
1/* sec_helper.cc: NT security helper functions
2
b31c68c4 3 Copyright 2000, 2001, 2002 Red Hat, Inc.
c0d1968a
CV
4
5 Written by Corinna Vinschen <corinna@vinschen.de>
6
7This file is part of Cygwin.
8
9This software is a copyrighted work licensed under the terms of the
10Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11details. */
12
13#include "winsup.h"
14#include <grp.h>
15#include <pwd.h>
16#include <unistd.h>
17#include <stdlib.h>
c0d1968a
CV
18#include <limits.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <sys/acl.h>
22#include <ctype.h>
23#include <wingdi.h>
24#include <winuser.h>
17db1105 25#include <wininet.h>
c0d1968a 26#include "cygerrno.h"
6b91b8d5 27#include "security.h"
c0d1968a
CV
28#include "fhandler.h"
29#include "path.h"
30#include "dtable.h"
c0d1968a
CV
31#include "pinfo.h"
32#include "cygheap.h"
d6ffc075 33#include "pwdgrp.h"
c0d1968a 34
73d97618
CV
35/* General purpose security attribute objects for global use. */
36SECURITY_ATTRIBUTES NO_COPY sec_none;
37SECURITY_ATTRIBUTES NO_COPY sec_none_nih;
38SECURITY_ATTRIBUTES NO_COPY sec_all;
39SECURITY_ATTRIBUTES NO_COPY sec_all_nih;
40
4a21c2d5 41SID_IDENTIFIER_AUTHORITY NO_COPY sid_auth[] = {
1ff9f4b9
CF
42 {SECURITY_NULL_SID_AUTHORITY},
43 {SECURITY_WORLD_SID_AUTHORITY},
44 {SECURITY_LOCAL_SID_AUTHORITY},
45 {SECURITY_CREATOR_SID_AUTHORITY},
46 {SECURITY_NON_UNIQUE_AUTHORITY},
47 {SECURITY_NT_AUTHORITY}
c0d1968a
CV
48};
49
85ecb9be
CV
50cygsid well_known_null_sid;
51cygsid well_known_world_sid;
52cygsid well_known_local_sid;
53cygsid well_known_creator_owner_sid;
54cygsid well_known_creator_group_sid;
55cygsid well_known_dialup_sid;
56cygsid well_known_network_sid;
57cygsid well_known_batch_sid;
58cygsid well_known_interactive_sid;
59cygsid well_known_service_sid;
60cygsid well_known_authenticated_users_sid;
61cygsid well_known_system_sid;
62cygsid well_known_admins_sid;
63
4a21c2d5
CV
64bool
65cygpsid::operator== (const char *nsidstr) const
66{
67 cygsid nsid (nsidstr);
68 return psid == nsid;
69}
70
71__uid32_t
72cygpsid::get_id (BOOL search_grp, int *type)
73{
74 /* First try to get SID from group, then passwd */
75 __uid32_t id = ILLEGAL_UID;
76
77 if (search_grp)
78 {
79 struct __group32 *gr;
80 if (cygheap->user.groups.pgsid == psid)
81 id = myself->gid;
82 else if ((gr = internal_getgrsid (*this)))
83 id = gr->gr_gid;
84 if (id != ILLEGAL_UID)
a113a3c5 85 {
4a21c2d5
CV
86 if (type)
87 *type = GROUP;
88 return id;
89 }
90 }
91 if (!search_grp || type)
92 {
93 struct passwd *pw;
94 if (*this == cygheap->user.sid ())
95 id = myself->uid;
96 else if ((pw = internal_getpwsid (*this)))
97 id = pw->pw_uid;
98 if (id != ILLEGAL_UID && type)
a113a3c5 99 *type = USER;
4a21c2d5
CV
100 }
101 return id;
102}
103
104
105char *
106cygpsid::string (char *nsidstr) const
107{
108 char *t;
109 DWORD i;
110
111 if (!psid || !nsidstr)
112 return NULL;
113 strcpy (nsidstr, "S-1-");
114 t = nsidstr + sizeof ("S-1-") - 1;
115 t += __small_sprintf (t, "%u", GetSidIdentifierAuthority (psid)->Value[5]);
116 for (i = 0; i < *GetSidSubAuthorityCount (psid); ++i)
117 t += __small_sprintf (t, "-%lu", *GetSidSubAuthority (psid, i));
118 return nsidstr;
119}
120
85ecb9be
CV
121void
122cygsid::init ()
123{
124 well_known_null_sid = "S-1-0-0";
125 well_known_world_sid = "S-1-1-0";
126 well_known_local_sid = "S-1-2-0";
127 well_known_creator_owner_sid = "S-1-3-0";
128 well_known_creator_group_sid = "S-1-3-1";
129 well_known_dialup_sid = "S-1-5-1";
130 well_known_network_sid = "S-1-5-2";
131 well_known_batch_sid = "S-1-5-3";
132 well_known_interactive_sid = "S-1-5-4";
133 well_known_service_sid = "S-1-5-6";
134 well_known_authenticated_users_sid = "S-1-5-11";
135 well_known_system_sid = "S-1-5-18";
136 well_known_admins_sid = "S-1-5-32-544";
137}
2b0a111f 138
c0d1968a 139PSID
2b0a111f 140cygsid::get_sid (DWORD s, DWORD cnt, DWORD *r)
c0d1968a
CV
141{
142 DWORD i;
143
2b0a111f 144 if (s > 5 || cnt < 1 || cnt > 8)
1fcc912f
CV
145 {
146 psid = NO_SID;
147 return NULL;
148 }
2b0a111f 149 set ();
c90e1cf1 150 InitializeSid (psid, &sid_auth[s], cnt);
c0d1968a
CV
151 for (i = 0; i < cnt; ++i)
152 memcpy ((char *) psid + 8 + sizeof (DWORD) * i, &r[i], sizeof (DWORD));
153 return psid;
154}
155
2b0a111f
CV
156const PSID
157cygsid::getfromstr (const char *nsidstr)
c0d1968a 158{
7a11fe60
CV
159 char *lasts;
160 DWORD s, cnt = 0;
161 DWORD r[8];
c0d1968a 162
7a11fe60 163 if (nsidstr && !strncmp (nsidstr, "S-1-", 4))
1fcc912f 164 {
7a11fe60
CV
165 s = strtoul (nsidstr + 4, &lasts, 10);
166 while ( cnt < 8 && *lasts == '-')
167 r[cnt++] = strtoul (lasts + 1, &lasts, 10);
168 if (!*lasts)
169 return get_sid (s, cnt, r);
1fcc912f 170 }
7a11fe60 171 return psid = NO_SID;
c0d1968a
CV
172}
173
174BOOL
b2939a81 175cygsid::getfrompw (const struct passwd *pw)
c0d1968a 176{
1fcc912f 177 char *sp = (pw && pw->pw_gecos) ? strrchr (pw->pw_gecos, ',') : NULL;
647b92a7 178 return (*this = sp ? sp + 1 : sp) != NULL;
c0d1968a
CV
179}
180
181BOOL
57196405 182cygsid::getfromgr (const struct __group32 *gr)
c0d1968a 183{
1fcc912f 184 char *sp = (gr && gr->gr_passwd) ? gr->gr_passwd : NULL;
647b92a7 185 return (*this = sp) != NULL;
c0d1968a
CV
186}
187
0c8455c3
CV
188bool
189get_sids_info (cygpsid owner_sid, cygpsid group_sid, __uid32_t * uidret, __gid32_t * gidret)
190{
191 struct passwd *pw;
192 struct __group32 *gr = NULL;
193 bool ret = false;
194
61a52599
CV
195 owner_sid.debug_print ("get_sids_info: owner SID =");
196 group_sid.debug_print ("get_sids_info: group SID =");
197
0c8455c3
CV
198 if (group_sid == cygheap->user.groups.pgsid)
199 *gidret = myself->gid;
200 else if ((gr = internal_getgrsid (group_sid)))
201 *gidret = gr->gr_gid;
202 else
203 *gidret = ILLEGAL_GID;
204
205 if (owner_sid == cygheap->user.sid ())
206 {
207 *uidret = myself->uid;
208 if (*gidret == myself->gid)
209 ret = true;
210 else
211 ret = (internal_getgroups (0, NULL, &group_sid) > 0);
212 }
213 else if ((pw = internal_getpwsid (owner_sid)))
214 {
215 *uidret = pw->pw_uid;
216 if (gr || (*gidret != ILLEGAL_GID
217 && (gr = internal_getgrgid (*gidret))))
218 for (int idx = 0; gr->gr_mem[idx]; ++idx)
219 if ((ret = strcasematch (pw->pw_name, gr->gr_mem[idx])))
220 break;
221 }
222 else
223 *uidret = ILLEGAL_UID;
224
225 return ret;
226}
227
2e8abfc1 228#if 0 // unused
17db1105
CV
229#define SIDLEN (sidlen = MAX_SID_LEN, &sidlen)
230#define DOMLEN (domlen = INTERNET_MAX_HOST_NAME_LENGTH, &domlen)
231
c0d1968a
CV
232BOOL
233lookup_name (const char *name, const char *logsrv, PSID ret_sid)
234{
d551169a 235 cygsid sid;
c0d1968a 236 DWORD sidlen;
17db1105
CV
237 char domuser[INTERNET_MAX_HOST_NAME_LENGTH + UNLEN + 2];
238 char dom[INTERNET_MAX_HOST_NAME_LENGTH + 1];
c0d1968a
CV
239 DWORD domlen;
240 SID_NAME_USE acc_type;
241
242 debug_printf ("name : %s", name ? name : "NULL");
243
244 if (!name)
245 return FALSE;
246
247 if (cygheap->user.domain ())
248 {
249 strcat (strcat (strcpy (domuser, cygheap->user.domain ()), "\\"), name);
17db1105 250 if (LookupAccountName (NULL, domuser, sid, SIDLEN, dom, DOMLEN, &acc_type)
c0d1968a
CV
251 && legal_sid_type (acc_type))
252 goto got_it;
253 if (logsrv && *logsrv
17db1105
CV
254 && LookupAccountName (logsrv, domuser, sid, SIDLEN,
255 dom, DOMLEN, &acc_type)
c0d1968a
CV
256 && legal_sid_type (acc_type))
257 goto got_it;
258 }
259 if (logsrv && *logsrv)
260 {
17db1105 261 if (LookupAccountName (logsrv, name, sid, SIDLEN, dom, DOMLEN, &acc_type)
c0d1968a
CV
262 && legal_sid_type (acc_type))
263 goto got_it;
264 if (acc_type == SidTypeDomain)
265 {
266 strcat (strcat (strcpy (domuser, dom), "\\"), name);
17db1105
CV
267 if (LookupAccountName (logsrv, domuser, sid, SIDLEN,
268 dom, DOMLEN, &acc_type))
c0d1968a
CV
269 goto got_it;
270 }
271 }
17db1105 272 if (LookupAccountName (NULL, name, sid, SIDLEN, dom, DOMLEN, &acc_type)
c0d1968a
CV
273 && legal_sid_type (acc_type))
274 goto got_it;
275 if (acc_type == SidTypeDomain)
276 {
277 strcat (strcat (strcpy (domuser, dom), "\\"), name);
17db1105 278 if (LookupAccountName (NULL, domuser, sid, SIDLEN, dom, DOMLEN,&acc_type))
c0d1968a
CV
279 goto got_it;
280 }
c90e1cf1 281 debug_printf ("LookupAccountName (%s) %E", name);
c0d1968a
CV
282 __seterrno ();
283 return FALSE;
284
285got_it:
c90e1cf1
CF
286 debug_printf ("sid : [%d]", *GetSidSubAuthority ((PSID) sid,
287 *GetSidSubAuthorityCount ((PSID) sid) - 1));
c0d1968a
CV
288
289 if (ret_sid)
290 memcpy (ret_sid, sid, sidlen);
291
292 return TRUE;
293}
3c8e92d9 294
17db1105
CV
295#undef SIDLEN
296#undef DOMLEN
2e8abfc1 297#endif //unused
17db1105 298
3c8e92d9 299int
153e83c6 300set_process_privilege (const char *privilege, bool enable, bool use_thread)
3c8e92d9
CV
301{
302 HANDLE hToken = NULL;
303 LUID restore_priv;
1fcc912f 304 TOKEN_PRIVILEGES new_priv, orig_priv;
3c8e92d9 305 int ret = -1;
1fcc912f 306 DWORD size;
3c8e92d9 307
153e83c6
CV
308 if ((use_thread
309 && !OpenThreadToken (GetCurrentThread (), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
310 0, &hToken))
311 ||(!use_thread
312 && !OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
313 &hToken)))
3c8e92d9
CV
314 {
315 __seterrno ();
316 goto out;
317 }
318
319 if (!LookupPrivilegeValue (NULL, privilege, &restore_priv))
320 {
321 __seterrno ();
322 goto out;
323 }
324
325 new_priv.PrivilegeCount = 1;
326 new_priv.Privileges[0].Luid = restore_priv;
327 new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
328
1fcc912f 329 if (!AdjustTokenPrivileges (hToken, FALSE, &new_priv,
1ff9f4b9 330 sizeof orig_priv, &orig_priv, &size))
1fcc912f
CV
331 {
332 __seterrno ();
333 goto out;
334 }
335 /* AdjustTokenPrivileges returns TRUE even if the privilege could not
c90e1cf1 336 be enabled. GetLastError () returns an correct error code, though. */
1fcc912f 337 if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED)
3c8e92d9
CV
338 {
339 __seterrno ();
340 goto out;
341 }
342
1fcc912f 343 ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0;
3c8e92d9
CV
344
345out:
346 if (hToken)
347 CloseHandle (hToken);
348
96edd0a9 349 syscall_printf ("%d = set_process_privilege (%s, %d)", ret, privilege, enable);
3c8e92d9
CV
350 return ret;
351}
73d97618
CV
352
353/*
354 * Function to return a common SECURITY_DESCRIPTOR * that
355 * allows all access.
356 */
357
358static NO_COPY SECURITY_DESCRIPTOR *null_sdp = 0;
359
360SECURITY_DESCRIPTOR *__stdcall
361get_null_sd ()
362{
363 static NO_COPY SECURITY_DESCRIPTOR sd;
364
365 if (null_sdp == 0)
366 {
367 InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
368 SetSecurityDescriptorDacl (&sd, TRUE, 0, FALSE);
369 null_sdp = &sd;
370 }
371 return null_sdp;
372}
373
374BOOL
c61ada9b 375sec_acl (PACL acl, bool original, bool admins, PSID sid1, PSID sid2, DWORD access2)
73d97618
CV
376{
377 size_t acl_len = MAX_DACL_LEN(5);
c61ada9b 378 cygpsid psid;
73d97618
CV
379
380 if (!InitializeAcl (acl, acl_len, ACL_REVISION))
381 {
382 debug_printf ("InitializeAcl %E");
383 return FALSE;
384 }
73d97618
CV
385 if (sid1)
386 if (!AddAccessAllowedAce (acl, ACL_REVISION,
387 GENERIC_ALL, sid1))
b7e66454 388 debug_printf ("AddAccessAllowedAce(sid1) %E");
c61ada9b
PH
389 if (original && (psid = cygheap->user.orig_sid ())
390 && psid != sid1 && psid != well_known_system_sid)
391 if (!AddAccessAllowedAce (acl, ACL_REVISION,
392 GENERIC_ALL, psid))
393 debug_printf ("AddAccessAllowedAce(original) %E");
394 if (sid2)
395 if (!AddAccessAllowedAce (acl, ACL_REVISION,
396 access2, sid2))
397 debug_printf ("AddAccessAllowedAce(sid2) %E");
73d97618
CV
398 if (admins)
399 if (!AddAccessAllowedAce (acl, ACL_REVISION,
400 GENERIC_ALL, well_known_admins_sid))
401 debug_printf ("AddAccessAllowedAce(admin) %E");
402 if (!AddAccessAllowedAce (acl, ACL_REVISION,
403 GENERIC_ALL, well_known_system_sid))
404 debug_printf ("AddAccessAllowedAce(system) %E");
73d97618
CV
405 return TRUE;
406}
407
408PSECURITY_ATTRIBUTES __stdcall
c61ada9b 409__sec_user (PVOID sa_buf, PSID sid1, PSID sid2, DWORD access2, BOOL inherit)
73d97618
CV
410{
411 PSECURITY_ATTRIBUTES psa = (PSECURITY_ATTRIBUTES) sa_buf;
412 PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR)
413 ((char *) sa_buf + sizeof (*psa));
414 PACL acl = (PACL) ((char *) sa_buf + sizeof (*psa) + sizeof (*psd));
415
c61ada9b 416 if (!wincap.has_security () || !sec_acl (acl, true, true, sid1, sid2, access2))
73d97618
CV
417 return inherit ? &sec_none : &sec_none_nih;
418
419 if (!InitializeSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION))
420 debug_printf ("InitializeSecurityDescriptor %E");
421
422/*
423 * Setting the owner lets the created security attribute not work
424 * on NT4 SP3 Server. Don't know why, but the function still does
425 * what it should do also if the owner isn't set.
426*/
427#if 0
428 if (!SetSecurityDescriptorOwner (psd, sid, FALSE))
429 debug_printf ("SetSecurityDescriptorOwner %E");
430#endif
431
432 if (!SetSecurityDescriptorDacl (psd, TRUE, acl, FALSE))
433 debug_printf ("SetSecurityDescriptorDacl %E");
434
435 psa->nLength = sizeof (SECURITY_ATTRIBUTES);
436 psa->lpSecurityDescriptor = psd;
437 psa->bInheritHandle = inherit;
438 return psa;
439}
This page took 0.171601 seconds and 5 git commands to generate.