1 /* security.h: security declarations
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
14 /* Special file attribute set in set_created_file_access to flag that a file
15 has just been created. Used in get_posix_access. */
16 #define S_JUSTCREATED 0x80000000
20 bool check_token_membership (PSID
);
22 #define ILLEGAL_UID ((uid_t)-1)
23 #define ILLEGAL_GID ((gid_t)-1)
25 /* Offset for accounts in the primary domain of the machine. */
26 #define PRIMARY_POSIX_OFFSET (0x00100000)
28 /* Fake POSIX offsets used in scenarios in which the account has no permission
29 to fetch the POSIX offset, or when the admins have set the offset to an
30 unreasonable low value. The values are chosen in the hope that they won't
31 collide with "real" offsets. */
32 #define NOACCESS_POSIX_OFFSET (0xfe500000)
33 #define UNUSABLE_POSIX_OFFSET (0xfea00000)
35 /* For UNIX accounts not mapped to Windows accounts via winbind, Samba returns
36 SIDs of the form S-1-22-x-y, with x == 1 for users and x == 2 for groups,
37 and y == UNIX uid/gid. NFS returns no SIDs at all, but the plain UNIX
40 UNIX uid/gid values are mapped to Cygwin uid/gid values 0xff000000 +
41 unix uid/gid. This *might* collide with a posix_offset of some trusted
42 domain, but it's *very* unlikely. Define the mapping as macro. */
43 #define UNIX_POSIX_OFFSET (0xff000000)
44 #define UNIX_POSIX_MASK (0x00ffffff)
45 #define MAP_UNIX_TO_CYGWIN_ID(id) (UNIX_POSIX_OFFSET \
46 | ((id) & UNIX_POSIX_MASK))
48 #define MAX_DACL_LEN(n) (sizeof (ACL) \
49 + (n) * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) \
50 + SECURITY_MAX_SID_SIZE))
51 #define SD_MIN_SIZE (sizeof (SECURITY_DESCRIPTOR) + MAX_DACL_LEN (1))
52 #define ACL_MAXIMUM_SIZE 65532 /* Yeah, right. 64K - sizeof (DWORD). */
53 #define SD_MAXIMUM_SIZE 65536
54 #define NO_SID ((PSID)NULL)
56 #ifndef SE_CREATE_TOKEN_PRIVILEGE
57 #define SE_CREATE_TOKEN_PRIVILEGE 2U
58 #define SE_ASSIGNPRIMARYTOKEN_PRIVILEGE 3U
59 #define SE_LOCK_MEMORY_PRIVILEGE 4U
60 #define SE_INCREASE_QUOTA_PRIVILEGE 5U
61 #define SE_MACHINE_ACCOUNT_PRIVILEGE 6U
62 #define SE_TCB_PRIVILEGE 7U
63 #define SE_SECURITY_PRIVILEGE 8U
64 #define SE_TAKE_OWNERSHIP_PRIVILEGE 9U
65 #define SE_LOAD_DRIVER_PRIVILEGE 10U
66 #define SE_SYSTEM_PROFILE_PRIVILEGE 11U
67 #define SE_SYSTEMTIME_PRIVILEGE 12U
68 #define SE_PROF_SINGLE_PROCESS_PRIVILEGE 13U
69 #define SE_INC_BASE_PRIORITY_PRIVILEGE 14U
70 #define SE_CREATE_PAGEFILE_PRIVILEGE 15U
71 #define SE_CREATE_PERMANENT_PRIVILEGE 16U
72 #define SE_BACKUP_PRIVILEGE 17U
73 #define SE_RESTORE_PRIVILEGE 18U
74 #define SE_SHUTDOWN_PRIVILEGE 19U
75 #define SE_DEBUG_PRIVILEGE 20U
76 #define SE_AUDIT_PRIVILEGE 21U
77 #define SE_SYSTEM_ENVIRONMENT_PRIVILEGE 22U
78 #define SE_CHANGE_NOTIFY_PRIVILEGE 23U
79 #define SE_REMOTE_SHUTDOWN_PRIVILEGE 24U
80 #define SE_UNDOCK_PRIVILEGE 25U
81 #define SE_SYNC_AGENT_PRIVILEGE 26U
82 #define SE_ENABLE_DELEGATION_PRIVILEGE 27U
83 #define SE_MANAGE_VOLUME_PRIVILEGE 28U
84 #define SE_IMPERSONATE_PRIVILEGE 29U
85 #define SE_CREATE_GLOBAL_PRIVILEGE 30U
86 #define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE 31U
87 #define SE_RELABEL_PRIVILEGE 32U
88 #define SE_INCREASE_WORKING_SET_PRIVILEGE 33U
89 #define SE_TIME_ZONE_PRIVILEGE 34U
90 #define SE_CREATE_SYMBOLIC_LINK_PRIVILEGE 35U
92 #define SE_MAX_WELL_KNOWN_PRIVILEGE SE_CREATE_SYMBOLIC_LINK_PRIVILEGE
94 #endif /* ! SE_CREATE_TOKEN_PRIVILEGE */
96 /* Added for debugging purposes. */
99 BYTE SubAuthorityCount
;
100 SID_IDENTIFIER_AUTHORITY IdentifierAuthority
;
101 DWORD SubAuthority
[SID_MAX_SUB_AUTHORITIES
];
104 /* Macro to define variable length SID structures */
105 #define MKSID(name, comment, authority, count, rid...) \
106 static NO_COPY struct { \
108 BYTE SubAuthorityCount; \
109 SID_IDENTIFIER_AUTHORITY IdentifierAuthority; \
110 DWORD SubAuthority[count]; \
111 } name##_struct = { SID_REVISION, count, {authority}, {rid}}; \
112 cygpsid NO_COPY name = (PSID) &name##_struct;
114 #define FILE_READ_BITS (FILE_READ_DATA | GENERIC_READ | GENERIC_ALL)
115 #define FILE_WRITE_BITS (FILE_WRITE_DATA | GENERIC_WRITE | GENERIC_ALL)
116 #define FILE_EXEC_BITS (FILE_EXECUTE | GENERIC_EXECUTE | GENERIC_ALL)
118 /* Convenience macros. The Windows SID access functions are crude. */
119 #define sid_id_auth(s) \
120 (RtlIdentifierAuthoritySid (s)->Value[5])
121 #define sid_sub_auth_count(s) \
122 (*RtlSubAuthorityCountSid ((s)))
123 #define sid_sub_auth(s,i) \
124 (*RtlSubAuthoritySid ((s),(i)))
125 #define sid_sub_auth_rid(s) \
126 (*RtlSubAuthoritySid ((s), (*RtlSubAuthorityCountSid ((s)) - 1)))
132 /* We need these declarations, otherwise g++ complains that the below
133 inline methods use an undefined function, if ntdll.h isn't included. */
134 BOOLEAN
RtlEqualSid (PSID
, PSID
);
135 NTSTATUS
RtlCopySid (ULONG
, PSID
, PSID
);
147 cygpsid (PSID nsid
) { psid
= nsid
; }
148 operator PSID () const { return psid
; }
149 const PSID
operator= (PSID nsid
) { return psid
= nsid
;}
150 uid_t
get_id (BOOL search_grp
, int *type
, cyg_ldap
*pldap
);
151 int get_uid (cyg_ldap
*pldap
) { return get_id (FALSE
, NULL
, pldap
); }
152 int get_gid (cyg_ldap
*pldap
) { return get_id (TRUE
, NULL
, pldap
); }
154 PWCHAR
pstring (PWCHAR nsidstr
) const;
155 PWCHAR
string (PWCHAR nsidstr
) const;
156 char *pstring (char *nsidstr
) const;
157 char *string (char *nsidstr
) const;
159 bool operator== (const PSID nsid
) const
163 return RtlEqualSid (psid
, nsid
);
165 bool operator!= (const PSID nsid
) const
166 { return !(*this == nsid
); }
167 bool operator== (const char *nsidstr
) const;
168 bool operator!= (const char *nsidstr
) const
169 { return !(*this == nsidstr
); }
171 void debug_print (const char *prefix
= NULL
) const
173 char buf
[256] __attribute__ ((unused
));
174 debug_printf ("%s %s", prefix
?: "", string (buf
) ?: "NULL");
178 class cygsid
: public cygpsid
{
179 char sbuf
[SECURITY_MAX_SID_SIZE
];
182 const PSID
getfromstr (PCWSTR nsidstr
, bool well_known
);
183 const PSID
getfromstr (const char *nsidstr
, bool well_known
);
184 PSID
get_sid (DWORD s
, DWORD cnt
, DWORD
*r
, bool well_known
);
186 inline const PSID
assign (const PSID nsid
, bool well_known
)
193 RtlCopySid (SECURITY_MAX_SID_SIZE
, psid
, nsid
);
194 well_known_sid
= well_known
;
200 inline operator const PSID () { return psid
; }
201 inline bool is_well_known_sid () { return well_known_sid
; }
203 /* Both, = and *= are assignment operators. = creates a "normal" SID,
204 *= marks the SID as being a well-known SID. This difference is
205 important when creating a SID list for LSA authentication. */
206 inline const PSID
operator= (cygsid
&nsid
)
207 { return assign (nsid
, nsid
.well_known_sid
); }
208 inline const PSID
operator= (const PSID nsid
)
209 { return assign (nsid
, false); }
210 inline const PSID
operator= (PCWSTR nsidstr
)
211 { return getfromstr (nsidstr
, false); }
212 inline const PSID
operator= (const char *nsidstr
)
213 { return getfromstr (nsidstr
, false); }
214 inline const PSID
operator*= (cygsid
&nsid
)
215 { return assign (nsid
, true); }
216 inline const PSID
operator*= (const PSID nsid
)
217 { return assign (nsid
, true); }
218 inline const PSID
operator*= (PCWSTR nsidstr
)
219 { return getfromstr (nsidstr
, true); }
220 inline const PSID
operator*= (const char *nsidstr
)
221 { return getfromstr (nsidstr
, true); }
223 inline cygsid () : cygpsid ((PSID
) sbuf
), well_known_sid (false) {}
224 inline cygsid (const PSID nsid
) { *this = nsid
; }
225 inline cygsid (const char *nstrsid
) { *this = nstrsid
; }
226 inline cygsid (cygsid
&nsid
) { *this = nsid
; }
228 inline PSID
set () { return psid
= (PSID
) sbuf
; }
230 inline BOOL
getfrompw_gecos (const struct passwd
*pw
)
232 char *sp
= (pw
&& pw
->pw_gecos
) ? strrchr (pw
->pw_gecos
, ',') : NULL
;
233 return (*this = sp
? sp
+ 1 : sp
) != NO_SID
;
235 inline BOOL
getfromgr_passwd (const struct group
*gr
)
237 char *sp
= (gr
&& gr
->gr_passwd
) ? gr
->gr_passwd
: NULL
;
238 return (*this = sp
) != NO_SID
;
241 const PSID
create (DWORD auth
, DWORD subauth_cnt
, ...);
242 bool append (DWORD rid
);
244 /* Implemented in pwdgrp.h. */
245 BOOL
getfrompw (const struct passwd
*pw
);
246 BOOL
getfromgr (const struct group
*gr
);
248 void debug_print (const char *prefix
= NULL
) const
250 char buf
[256] __attribute__ ((unused
));
251 debug_printf ("%s %s%s", prefix
?: "", string (buf
) ?: "NULL", well_known_sid
? " (*)" : " (+)");
255 typedef enum { cygsidlist_empty
, cygsidlist_alloc
, cygsidlist_auto
} cygsidlist_type
;
260 BOOL
add (const PSID nsi
, bool well_known
); /* Only with auto for now */
264 cygsidlist_type type
;
266 cygsidlist (cygsidlist_type t
, int m
)
267 : maxcnt (m
), cnt (0), type (t
)
269 if (t
== cygsidlist_alloc
)
270 sids
= alloc_sids (m
);
272 sids
= new cygsid
[m
];
274 ~cygsidlist () { if (type
== cygsidlist_auto
) delete [] sids
; }
276 BOOL
addfromgr (struct group
*gr
) /* Only with alloc */
277 { return sids
[cnt
].getfromgr (gr
) && ++cnt
; }
279 /* += adds a "normal" SID, *= adds a well-known SID. See comment in class
281 BOOL
operator+= (cygsid
&si
) { return add ((PSID
) si
,
282 si
.is_well_known_sid ()); }
283 BOOL
operator+= (const char *sidstr
) { cygsid
nsi (sidstr
);
284 return add ((PSID
) nsi
,
285 nsi
.is_well_known_sid ());
287 BOOL
operator+= (const PSID psid
) { return add (psid
, false); }
288 BOOL
operator*= (cygsid
&si
) { return add ((PSID
) si
, true); }
289 BOOL
operator*= (const char *sidstr
) { cygsid
nsi (sidstr
);
290 return add ((PSID
) nsi
, true); }
291 BOOL
operator*= (const PSID psid
) { return add (psid
, true); }
293 void count (int ncnt
)
295 int count () const { return cnt
; }
296 int position (const PSID sid
) const
298 for (int i
= 0; i
< cnt
; ++i
)
304 BOOL
contains (const PSID sid
) const { return position (sid
) >= 0; }
305 cygsid
*alloc_sids (int n
);
307 void debug_print (const char *prefix
= NULL
) const
309 debug_printf ("-- begin sidlist ---");
311 debug_printf ("No elements");
312 for (int i
= 0; i
< cnt
; ++i
)
313 sids
[i
].debug_print (prefix
);
314 debug_printf ("-- ende sidlist ---");
318 /* Wrapper class to allow simple deleting of buffer space allocated
320 class security_descriptor
{
322 PSECURITY_DESCRIPTOR psd
;
325 security_descriptor () : psd (NULL
), sd_size (0) {}
326 ~security_descriptor () { free (); }
328 PSECURITY_DESCRIPTOR
malloc (size_t nsize
);
329 PSECURITY_DESCRIPTOR
realloc (size_t nsize
);
332 inline DWORD
size () const { return sd_size
; }
333 inline DWORD
copy (void *buf
, DWORD buf_size
) const {
334 if (buf_size
< size ())
336 memcpy (buf
, psd
, sd_size
);
339 inline operator const PSECURITY_DESCRIPTOR () { return psd
; }
340 inline operator PSECURITY_DESCRIPTOR
*() { return &psd
; }
341 inline void operator =(PSECURITY_DESCRIPTOR nsd
) { psd
= nsd
; }
350 BOOL
issetgroups () const { return (sgsids
.type
== cygsidlist_alloc
); }
351 void update_supp (const cygsidlist
&newsids
)
365 void update_pgrp (const PSID sid
)
372 extern cygpsid well_known_null_sid
;
373 extern cygpsid well_known_world_sid
;
374 extern cygpsid well_known_local_sid
;
375 extern cygpsid well_known_console_logon_sid
;
376 extern cygpsid well_known_creator_owner_sid
;
377 extern cygpsid well_known_creator_group_sid
;
378 extern cygpsid well_known_dialup_sid
;
379 extern cygpsid well_known_network_sid
;
380 extern cygpsid well_known_batch_sid
;
381 extern cygpsid well_known_interactive_sid
;
382 extern cygpsid well_known_service_sid
;
383 extern cygpsid well_known_authenticated_users_sid
;
384 extern cygpsid well_known_this_org_sid
;
385 extern cygpsid well_known_system_sid
;
386 extern cygpsid well_known_local_service_sid
;
387 extern cygpsid well_known_network_service_sid
;
388 extern cygpsid well_known_builtin_sid
;
389 extern cygpsid well_known_admins_sid
;
390 extern cygpsid well_known_users_sid
;
391 extern cygpsid trusted_installer_sid
;
392 extern cygpsid mandatory_medium_integrity_sid
;
393 extern cygpsid mandatory_high_integrity_sid
;
394 extern cygpsid mandatory_system_integrity_sid
;
395 extern cygpsid well_known_samba_unix_user_fake_sid
;
397 bool privilege_luid (const PWCHAR pname
, LUID
&luid
, bool &high_integrity
);
400 well_known_sid_type (SID_NAME_USE type
)
402 return type
== SidTypeAlias
|| type
== SidTypeWellKnownGroup
;
406 legal_sid_type (SID_NAME_USE type
)
408 return type
== SidTypeUser
|| type
== SidTypeGroup
409 || type
== SidTypeAlias
|| type
== SidTypeWellKnownGroup
;
413 /* File manipulation */
414 int get_file_attribute (HANDLE
, path_conv
&, mode_t
&,
416 int set_created_file_access (HANDLE
, path_conv
&, mode_t
);
417 int get_object_sd (HANDLE
, security_descriptor
&);
418 int get_object_attribute (HANDLE
, uid_t
*, gid_t
*, mode_t
&);
419 int set_object_attribute (HANDLE
, uid_t
, gid_t
, mode_t
);
420 int create_object_sd_from_attribute (uid_t
, gid_t
, mode_t
,
421 security_descriptor
&);
422 int set_object_sd (HANDLE
, security_descriptor
&, bool);
424 int get_reg_attribute (HKEY hkey
, mode_t
&, uid_t
*, gid_t
*);
425 LONG
get_file_sd (HANDLE fh
, path_conv
&, security_descriptor
&, bool);
426 LONG
set_file_sd (HANDLE fh
, path_conv
&, security_descriptor
&, bool);
427 bool add_access_allowed_ace (PACL
, DWORD
, PSID
, size_t &, DWORD
);
428 bool add_access_denied_ace (PACL
, DWORD
, PSID
, size_t &, DWORD
);
429 int check_file_access (path_conv
&, int, bool);
430 int check_registry_access (HANDLE
, int, bool);
432 void set_security_attribute (path_conv
&pc
, int attribute
,
433 PSECURITY_ATTRIBUTES psa
,
434 security_descriptor
&sd_buf
);
436 bool authz_get_user_attribute (mode_t
*attribute
, PSECURITY_DESCRIPTOR psd
,
441 int searchace (struct acl
*, int, int, uid_t id
= ILLEGAL_UID
);
442 PSECURITY_DESCRIPTOR
set_posix_access (mode_t
, uid_t
, gid_t
, struct acl
*, int,
443 security_descriptor
&, bool);
444 int get_posix_access (PSECURITY_DESCRIPTOR
, mode_t
&, uid_t
*, gid_t
*,
445 struct acl
*, int, bool * = NULL
);
446 int getacl (HANDLE
, path_conv
&, int, struct acl
*);
447 int setacl (HANDLE
, path_conv
&, int, struct acl
*, bool &);
449 /* Set impersonation or restricted token. */
450 void set_imp_token (HANDLE token
, int type
);
451 /* LSA private key storage authentication, same as when using service logons. */
452 HANDLE
lsaprivkeyauth (struct passwd
*pw
);
453 /* Kerberos or MsV1 S4U logon. */
454 HANDLE
s4uauth (bool logon
, PCWSTR domain
, PCWSTR user
, NTSTATUS
&ret_status
);
455 /* Verify an existing token */
456 bool verify_token (HANDLE token
, cygsid
&usersid
, user_groups
&groups
, bool *pintern
= NULL
);
457 /* Get groups of a user */
458 enum acct_disabled_chk_t
{
463 bool get_server_groups (cygsidlist
&grp_list
, PSID usersid
,
464 acct_disabled_chk_t check_account_disabled
);
466 /* Extract U-domain\user field from passwd entry. */
467 void extract_nt_dom_user (const struct passwd
*pw
, PWCHAR domain
, PWCHAR user
);
468 /* Get default logonserver for a domain. */
469 bool get_logon_server (PCWSTR domain
, PWCHAR wserver
, ULONG flags
);
471 /* Fetch user profile path from registry, if it already exists. */
472 PWCHAR
get_user_profile_directory (PCWSTR sidstr
, PWCHAR path
, SIZE_T path_len
);
474 /* Load user profile if it's not already loaded. */
475 HANDLE
load_user_profile (HANDLE token
, struct passwd
*pw
, cygpsid
&sid
);
477 HANDLE
lsa_open_policy (PWCHAR server
, ACCESS_MASK access
);
478 void lsa_close_policy (HANDLE lsa
);
480 /* sec_helper.cc: Security helper functions. */
481 int set_privilege (HANDLE token
, DWORD privilege
, bool enable
);
482 void set_cygwin_privileges (HANDLE token
);
484 #define _push_thread_privilege(_priv, _val, _check) { \
485 HANDLE _dup_token = NULL; \
486 HANDLE _token = (cygheap->user.issetuid () && (_check)) \
487 ? cygheap->user.primary_token () : hProcToken; \
488 if (!DuplicateTokenEx (_token, MAXIMUM_ALLOWED, NULL, \
489 SecurityImpersonation, TokenImpersonation, \
491 debug_printf ("DuplicateTokenEx: %E"); \
492 else if (!ImpersonateLoggedOnUser (_dup_token)) \
493 debug_printf ("ImpersonateLoggedOnUser: %E"); \
495 set_privilege (_dup_token, (_priv), (_val));
497 #define push_thread_privilege(_priv, _val) _push_thread_privilege(_priv,_val,1)
498 #define push_self_privilege(_priv, _val) _push_thread_privilege(_priv,_val,0)
500 #define pop_thread_privilege() \
503 if (!cygheap->user.issetuid ()) \
506 cygheap->user.reimpersonate (); \
507 CloseHandle (_dup_token); \
511 #define pop_self_privilege() pop_thread_privilege()
515 /* Various types of security attributes for use in Create* functions. */
516 extern SECURITY_ATTRIBUTES sec_none
, sec_none_nih
, sec_all
, sec_all_nih
;
517 extern SECURITY_ATTRIBUTES
*__sec_user (PVOID
, PSID
, PSID
,
520 extern PSECURITY_DESCRIPTOR
_recycler_sd (void *buf
, bool users
, bool dir
);
521 #define recycler_sd(users,dir) \
522 (_recycler_sd (alloca (sizeof (SECURITY_DESCRIPTOR) + MAX_DACL_LEN (3)), \
526 extern PSECURITY_DESCRIPTOR
_everyone_sd (void *buf
, ACCESS_MASK access
);
527 #define everyone_sd(access) (_everyone_sd (alloca (SD_MIN_SIZE), (access)))
529 #define sec_none_cloexec(f) (((f) & O_CLOEXEC ? &sec_none_nih : &sec_none))
531 extern bool sec_acl (PACL acl
, bool original
, bool admins
, PSID sid1
= NO_SID
,
532 PSID sid2
= NO_SID
, DWORD access2
= 0);
534 ssize_t
read_ea (HANDLE
, path_conv
&, const char *,
536 int write_ea (HANDLE
, path_conv
&, const char *, const char *,
539 /* Note: sid1 is usually (read: currently always) the current user's
540 effective sid (cygheap->user.sid ()). */
541 extern inline SECURITY_ATTRIBUTES
*
542 sec_user_nih (SECURITY_ATTRIBUTES
*sa_buf
, PSID sid1
, PSID sid2
= NULL
,
545 return __sec_user (sa_buf
, sid1
, sid2
, access2
, FALSE
);
548 extern inline SECURITY_ATTRIBUTES
*
549 sec_user (SECURITY_ATTRIBUTES
*sa_buf
, PSID sid1
, PSID sid2
= NULL
,
552 return __sec_user (sa_buf
, sid1
, sid2
, access2
, TRUE
);