newlib-cygwin/winsup/cygwin/sec_acl.cc

1042 lines
24 KiB
C++
Raw Normal View History

/* sec_acl.cc: Sun compatible ACL functions.
Copyright 2000, 2001, 2002, 2003 Red Hat, Inc.
Written by Corinna Vinschen <corinna@vinschen.de>
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
#include <grp.h>
#include <pwd.h>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/acl.h>
#include <ctype.h>
#include <wingdi.h>
#include <winuser.h>
#include "cygerrno.h"
#include "security.h"
#include "fhandler.h"
#include "path.h"
#include "dtable.h"
#include "pinfo.h"
#include "cygheap.h"
2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> * pwdgrp.h (pwdgrp_check::pwdgrp_state): Replace by pwdgrp_check::isinitializing (). (pwdgrp_check::isinitializing): Create. * passwd.cc (grab_int): Change type to unsigned, use strtoul and set the pointer content to 0 if the field is invalid. (parse_pwd): Move validity test after getting pw_gid. (read_etc_passwd): Replace "passwd_state <= " by passwd_state::isinitializing (). (internal_getpwuid): Ditto. (internal_getpwnam): Ditto. (getpwent): Ditto. (getpass): Ditto. * grp.cc (parse_grp): Use strtoul for gr_gid and verify the validity. (read_etc_group): Replace "group_state <= " by group_state::isinitializing (). (internal_getgrgid): Ditto. (getgrent32): Ditto. (internal_getgrent): Ditto. 2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> * security.h: Move declarations of internal_getgrent, internal_getpwsid and internal_getgrsid to pwdgrp.h. * pwdgrp.h: Declare internal_getpwsid, internal_getpwnam, internal_getpwuid, internal_getgrsid, internal_getgrgid, internal_getgrnam, internal_getgrent and internal_getgroups. Delete "emulated" from enum pwdgrp_state. (pwdgrp_check::isuninitialized): Create. (pwdgrp_check::pwdgrp_state): Change state to initializing rather than to uninitialized. (pwdgrp_read::gets): Remove trailing CRs. * passwd.cc (grab_string): Don't look for NLs. (grab_int): Ditto. (parse_pwd): Don't look for CRs. Return 0 if entry is too short. (search_for): Delete. (read_etc_passwd): Simplify tests to actually read the file. Set state to loaded before making internal_getpwXX calls. Replace search_for calls by equivalent internal_pwgetXX calls. (internal_getpwsid): Use passwd_state.isuninitialized to decide to call read_etc_passwd. (internal_getpwuid): Create. (internal_getpwnam): Create. (getpwuid32): Simply call internal_getpwuid. (getpwuid_r32): Call internal_getpwuid. (getpwnam): Simply call internal_getpwnam. (getpwnam_r): Call internal_getpwnam. * grp.cc (parse_grp): Don't look for CRs. Adjust blank space. (add_grp_line): Adjust blank space. (class group_lock): Ditto. (read_etc_group): Simplify tests to actually read the file. Set state to loaded before making internal_getgrXX calls. Replace getgrXX calls by equivalent internal calls. (internal_getgrsid): Use group_state.isuninitialized to decide to call read_etc_group. (internal_getgrgid): Create. (internal_getgrnam): Create. (getgroups32): Simply call internal_getgrgid. (getgrnam32): Simply call internal_getgrnam. (internal_getgrent): Call group_state.isuninitialized. (internal_getgroups): Create from the former getgroups32, using two of the four arguments. Set gid to myself->gid and username to cygheap->user.name (). (getgroups32): Simply call internal_getgroup. (getgroups): Call internal_getgroup instead of getgroups32. (setgroups32): Call internal versions of get{pw,gr}XX. * sec_helper.cc: Include pwdgrp.h. (is_grp_member): Call internal versions of get{pw,gr}XX. * security.cc: Include pwdgrp.h. (alloc_sd): Call internal versions of get{pw,gr}XX. * syscalls.cc: Include pwdgrp.h. (seteuid32): Call internal versions of get{pw,gr}XX. (setegid32): Ditto. * uinfo.cc: Include pwdgrp.h. (internal_getlogin): Call internal versions of get{pw,gr}XX. (cygheap_user::ontherange): Ditto. * sec_acl.cc: Include pwdgrp.h. (setacl): Call internal versions of get{pw,gr}XX. (acl_access): Ditto and simplify logic. (aclfromtext): Ditto.
2002-12-10 20:43:49 +08:00
#include "pwdgrp.h"
2003-02-06 00:15:22 +08:00
extern "C" int aclsort32 (int nentries, int, __aclent32_t *aclbufp);
extern "C" int acl32 (const char *path, int cmd, int nentries, __aclent32_t *aclbufp);
static int
2003-02-06 00:15:22 +08:00
searchace (__aclent32_t *aclp, int nentries, int type, __uid32_t id = ILLEGAL_UID)
{
int i;
for (i = 0; i < nentries; ++i)
2003-02-06 00:15:22 +08:00
if ((aclp[i].a_type == type && (id == ILLEGAL_UID || aclp[i].a_id == id))
|| !aclp[i].a_type)
return i;
return -1;
}
static int
2003-02-06 00:15:22 +08:00
setacl (const char *file, int nentries, __aclent32_t *aclbufp)
{
DWORD sd_size = 4096;
char sd_buf[4096];
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
if (read_sd (file, psd, &sd_size) <= 0)
{
debug_printf ("read_sd %E");
return -1;
}
BOOL dummy;
/* Get owner SID. */
2003-02-06 00:15:22 +08:00
PSID owner_sid;
if (!GetSecurityDescriptorOwner (psd, &owner_sid, &dummy))
{
__seterrno ();
return -1;
}
cygsid owner (owner_sid);
/* Get group SID. */
2003-02-06 00:15:22 +08:00
PSID group_sid;
if (!GetSecurityDescriptorGroup (psd, &group_sid, &dummy))
{
__seterrno ();
return -1;
}
cygsid group (group_sid);
/* Initialize local security descriptor. */
SECURITY_DESCRIPTOR sd;
if (!InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION))
{
__seterrno ();
return -1;
}
if (!SetSecurityDescriptorOwner (&sd, owner, FALSE))
{
__seterrno ();
return -1;
}
2003-02-06 00:15:22 +08:00
if (!SetSecurityDescriptorGroup (&sd, group, FALSE))
{
__seterrno ();
return -1;
}
/* Fill access control list. */
char acl_buf[3072];
PACL acl = (PACL) acl_buf;
size_t acl_len = sizeof (ACL);
int ace_off = 0;
cygsid sid;
struct passwd *pw;
struct __group32 *gr;
int pos;
if (!InitializeAcl (acl, 3072, ACL_REVISION))
{
__seterrno ();
return -1;
}
for (int i = 0; i < nentries; ++i)
{
2003-02-06 00:15:22 +08:00
DWORD allow;
/* Owner has more standard rights set. */
if ((aclbufp[i].a_type & ~ACL_DEFAULT) == USER_OBJ)
allow = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA;
2003-02-06 00:15:22 +08:00
else
allow = STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES | FILE_READ_EA;
if (aclbufp[i].a_perm & S_IROTH)
allow |= FILE_GENERIC_READ;
if (aclbufp[i].a_perm & S_IWOTH)
allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE;
if (aclbufp[i].a_perm & S_IXOTH)
allow |= FILE_GENERIC_EXECUTE;
if ((aclbufp[i].a_perm & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH))
allow |= FILE_DELETE_CHILD;
/* Set inherit property. */
DWORD inheritance = (aclbufp[i].a_type & ACL_DEFAULT)
? (SUB_CONTAINERS_AND_OBJECTS_INHERIT | INHERIT_ONLY)
: NO_INHERITANCE;
/*
* If a specific acl contains a corresponding default entry with
* identical permissions, only one Windows ACE with proper
* inheritance bits is created.
*/
if (!(aclbufp[i].a_type & ACL_DEFAULT)
&& aclbufp[i].a_type & (USER|GROUP|OTHER_OBJ)
&& (pos = searchace (aclbufp + i + 1, nentries - i - 1,
aclbufp[i].a_type | ACL_DEFAULT,
(aclbufp[i].a_type & (USER|GROUP))
2003-02-06 00:15:22 +08:00
? aclbufp[i].a_id : ILLEGAL_UID)) >= 0
&& aclbufp[i].a_perm == aclbufp[pos].a_perm)
{
inheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
/* This invalidates the corresponding default entry. */
aclbufp[pos].a_type = USER|GROUP|ACL_DEFAULT;
}
switch (aclbufp[i].a_type)
{
case USER_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
owner, acl_len, inheritance))
return -1;
break;
case DEF_USER_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
well_known_creator_owner_sid, acl_len, inheritance))
return -1;
break;
case USER:
case DEF_USER:
2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> * pwdgrp.h (pwdgrp_check::pwdgrp_state): Replace by pwdgrp_check::isinitializing (). (pwdgrp_check::isinitializing): Create. * passwd.cc (grab_int): Change type to unsigned, use strtoul and set the pointer content to 0 if the field is invalid. (parse_pwd): Move validity test after getting pw_gid. (read_etc_passwd): Replace "passwd_state <= " by passwd_state::isinitializing (). (internal_getpwuid): Ditto. (internal_getpwnam): Ditto. (getpwent): Ditto. (getpass): Ditto. * grp.cc (parse_grp): Use strtoul for gr_gid and verify the validity. (read_etc_group): Replace "group_state <= " by group_state::isinitializing (). (internal_getgrgid): Ditto. (getgrent32): Ditto. (internal_getgrent): Ditto. 2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> * security.h: Move declarations of internal_getgrent, internal_getpwsid and internal_getgrsid to pwdgrp.h. * pwdgrp.h: Declare internal_getpwsid, internal_getpwnam, internal_getpwuid, internal_getgrsid, internal_getgrgid, internal_getgrnam, internal_getgrent and internal_getgroups. Delete "emulated" from enum pwdgrp_state. (pwdgrp_check::isuninitialized): Create. (pwdgrp_check::pwdgrp_state): Change state to initializing rather than to uninitialized. (pwdgrp_read::gets): Remove trailing CRs. * passwd.cc (grab_string): Don't look for NLs. (grab_int): Ditto. (parse_pwd): Don't look for CRs. Return 0 if entry is too short. (search_for): Delete. (read_etc_passwd): Simplify tests to actually read the file. Set state to loaded before making internal_getpwXX calls. Replace search_for calls by equivalent internal_pwgetXX calls. (internal_getpwsid): Use passwd_state.isuninitialized to decide to call read_etc_passwd. (internal_getpwuid): Create. (internal_getpwnam): Create. (getpwuid32): Simply call internal_getpwuid. (getpwuid_r32): Call internal_getpwuid. (getpwnam): Simply call internal_getpwnam. (getpwnam_r): Call internal_getpwnam. * grp.cc (parse_grp): Don't look for CRs. Adjust blank space. (add_grp_line): Adjust blank space. (class group_lock): Ditto. (read_etc_group): Simplify tests to actually read the file. Set state to loaded before making internal_getgrXX calls. Replace getgrXX calls by equivalent internal calls. (internal_getgrsid): Use group_state.isuninitialized to decide to call read_etc_group. (internal_getgrgid): Create. (internal_getgrnam): Create. (getgroups32): Simply call internal_getgrgid. (getgrnam32): Simply call internal_getgrnam. (internal_getgrent): Call group_state.isuninitialized. (internal_getgroups): Create from the former getgroups32, using two of the four arguments. Set gid to myself->gid and username to cygheap->user.name (). (getgroups32): Simply call internal_getgroup. (getgroups): Call internal_getgroup instead of getgroups32. (setgroups32): Call internal versions of get{pw,gr}XX. * sec_helper.cc: Include pwdgrp.h. (is_grp_member): Call internal versions of get{pw,gr}XX. * security.cc: Include pwdgrp.h. (alloc_sd): Call internal versions of get{pw,gr}XX. * syscalls.cc: Include pwdgrp.h. (seteuid32): Call internal versions of get{pw,gr}XX. (setegid32): Ditto. * uinfo.cc: Include pwdgrp.h. (internal_getlogin): Call internal versions of get{pw,gr}XX. (cygheap_user::ontherange): Ditto. * sec_acl.cc: Include pwdgrp.h. (setacl): Call internal versions of get{pw,gr}XX. (acl_access): Ditto and simplify logic. (aclfromtext): Ditto.
2002-12-10 20:43:49 +08:00
if (!(pw = internal_getpwuid (aclbufp[i].a_id))
|| !sid.getfrompw (pw)
|| !add_access_allowed_ace (acl, ace_off++, allow,
2003-02-06 00:15:22 +08:00
sid, acl_len, inheritance))
return -1;
break;
case GROUP_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
2003-02-06 00:15:22 +08:00
group, acl_len, inheritance))
return -1;
break;
case DEF_GROUP_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
well_known_creator_group_sid, acl_len, inheritance))
return -1;
break;
case GROUP:
case DEF_GROUP:
2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> * pwdgrp.h (pwdgrp_check::pwdgrp_state): Replace by pwdgrp_check::isinitializing (). (pwdgrp_check::isinitializing): Create. * passwd.cc (grab_int): Change type to unsigned, use strtoul and set the pointer content to 0 if the field is invalid. (parse_pwd): Move validity test after getting pw_gid. (read_etc_passwd): Replace "passwd_state <= " by passwd_state::isinitializing (). (internal_getpwuid): Ditto. (internal_getpwnam): Ditto. (getpwent): Ditto. (getpass): Ditto. * grp.cc (parse_grp): Use strtoul for gr_gid and verify the validity. (read_etc_group): Replace "group_state <= " by group_state::isinitializing (). (internal_getgrgid): Ditto. (getgrent32): Ditto. (internal_getgrent): Ditto. 2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> * security.h: Move declarations of internal_getgrent, internal_getpwsid and internal_getgrsid to pwdgrp.h. * pwdgrp.h: Declare internal_getpwsid, internal_getpwnam, internal_getpwuid, internal_getgrsid, internal_getgrgid, internal_getgrnam, internal_getgrent and internal_getgroups. Delete "emulated" from enum pwdgrp_state. (pwdgrp_check::isuninitialized): Create. (pwdgrp_check::pwdgrp_state): Change state to initializing rather than to uninitialized. (pwdgrp_read::gets): Remove trailing CRs. * passwd.cc (grab_string): Don't look for NLs. (grab_int): Ditto. (parse_pwd): Don't look for CRs. Return 0 if entry is too short. (search_for): Delete. (read_etc_passwd): Simplify tests to actually read the file. Set state to loaded before making internal_getpwXX calls. Replace search_for calls by equivalent internal_pwgetXX calls. (internal_getpwsid): Use passwd_state.isuninitialized to decide to call read_etc_passwd. (internal_getpwuid): Create. (internal_getpwnam): Create. (getpwuid32): Simply call internal_getpwuid. (getpwuid_r32): Call internal_getpwuid. (getpwnam): Simply call internal_getpwnam. (getpwnam_r): Call internal_getpwnam. * grp.cc (parse_grp): Don't look for CRs. Adjust blank space. (add_grp_line): Adjust blank space. (class group_lock): Ditto. (read_etc_group): Simplify tests to actually read the file. Set state to loaded before making internal_getgrXX calls. Replace getgrXX calls by equivalent internal calls. (internal_getgrsid): Use group_state.isuninitialized to decide to call read_etc_group. (internal_getgrgid): Create. (internal_getgrnam): Create. (getgroups32): Simply call internal_getgrgid. (getgrnam32): Simply call internal_getgrnam. (internal_getgrent): Call group_state.isuninitialized. (internal_getgroups): Create from the former getgroups32, using two of the four arguments. Set gid to myself->gid and username to cygheap->user.name (). (getgroups32): Simply call internal_getgroup. (getgroups): Call internal_getgroup instead of getgroups32. (setgroups32): Call internal versions of get{pw,gr}XX. * sec_helper.cc: Include pwdgrp.h. (is_grp_member): Call internal versions of get{pw,gr}XX. * security.cc: Include pwdgrp.h. (alloc_sd): Call internal versions of get{pw,gr}XX. * syscalls.cc: Include pwdgrp.h. (seteuid32): Call internal versions of get{pw,gr}XX. (setegid32): Ditto. * uinfo.cc: Include pwdgrp.h. (internal_getlogin): Call internal versions of get{pw,gr}XX. (cygheap_user::ontherange): Ditto. * sec_acl.cc: Include pwdgrp.h. (setacl): Call internal versions of get{pw,gr}XX. (acl_access): Ditto and simplify logic. (aclfromtext): Ditto.
2002-12-10 20:43:49 +08:00
if (!(gr = internal_getgrgid (aclbufp[i].a_id))
|| !sid.getfromgr (gr)
|| !add_access_allowed_ace (acl, ace_off++, allow,
2003-02-06 00:15:22 +08:00
sid, acl_len, inheritance))
return -1;
break;
case OTHER_OBJ:
case DEF_OTHER_OBJ:
if (!add_access_allowed_ace (acl, ace_off++, allow,
well_known_world_sid,
acl_len, inheritance))
return -1;
break;
}
}
/* Set AclSize to computed value. */
acl->AclSize = acl_len;
debug_printf ("ACL-Size: %d", acl_len);
/* Create DACL for local security descriptor. */
if (!SetSecurityDescriptorDacl (&sd, TRUE, acl, FALSE))
{
__seterrno ();
return -1;
}
/* Make self relative security descriptor in psd. */
sd_size = 0;
MakeSelfRelativeSD (&sd, psd, &sd_size);
if (sd_size <= 0)
{
__seterrno ();
return -1;
}
if (!MakeSelfRelativeSD (&sd, psd, &sd_size))
{
__seterrno ();
return -1;
}
debug_printf ("Created SD-Size: %d", sd_size);
return write_sd (file, psd, sd_size);
}
/* Temporary access denied bits */
#define DENY_R 040000
#define DENY_W 020000
#define DENY_X 010000
static void
2003-02-06 00:15:22 +08:00
getace (__aclent32_t &acl, int type, int id, DWORD win_ace_mask,
DWORD win_ace_type)
{
acl.a_type = type;
acl.a_id = id;
if ((win_ace_mask & FILE_READ_DATA) && !(acl.a_perm & (S_IROTH | DENY_R)))
if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
acl.a_perm |= S_IROTH;
else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
acl.a_perm |= DENY_R;
if ((win_ace_mask & FILE_WRITE_DATA) && !(acl.a_perm & (S_IWOTH | DENY_W)))
if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
acl.a_perm |= S_IWOTH;
else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
acl.a_perm |= DENY_W;
if ((win_ace_mask & FILE_EXECUTE) && !(acl.a_perm & (S_IXOTH | DENY_X)))
if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
acl.a_perm |= S_IXOTH;
else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
acl.a_perm |= DENY_X;
}
static int
2003-02-06 00:15:22 +08:00
getacl (const char *file, DWORD attr, int nentries, __aclent32_t *aclbufp)
{
DWORD sd_size = 4096;
char sd_buf[4096];
PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
int ret;
if ((ret = read_sd (file, psd, &sd_size)) <= 0)
{
debug_printf ("read_sd %E");
return ret;
}
2003-02-06 00:15:22 +08:00
cygpsid owner_sid;
cygpsid group_sid;
BOOL dummy;
__uid32_t uid;
__gid32_t gid;
2003-02-06 00:15:22 +08:00
if (!GetSecurityDescriptorOwner (psd, (PSID *) &owner_sid, &dummy))
{
debug_printf ("GetSecurityDescriptorOwner %E");
__seterrno ();
return -1;
}
2003-02-06 00:15:22 +08:00
uid = owner_sid.get_uid ();
2003-02-06 00:15:22 +08:00
if (!GetSecurityDescriptorGroup (psd, (PSID *) &group_sid, &dummy))
{
debug_printf ("GetSecurityDescriptorGroup %E");
__seterrno ();
return -1;
}
2003-02-06 00:15:22 +08:00
gid = group_sid.get_gid ();
2003-02-06 00:15:22 +08:00
__aclent32_t lacl[MAX_ACL_ENTRIES];
memset (&lacl, 0, MAX_ACL_ENTRIES * sizeof (__aclent32_t));
lacl[0].a_type = USER_OBJ;
lacl[0].a_id = uid;
lacl[1].a_type = GROUP_OBJ;
lacl[1].a_id = gid;
lacl[2].a_type = OTHER_OBJ;
lacl[2].a_id = ILLEGAL_GID;
lacl[3].a_type = CLASS_OBJ;
lacl[3].a_id = ILLEGAL_GID;
lacl[3].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
PACL acl;
BOOL acl_exists;
if (!GetSecurityDescriptorDacl (psd, &acl_exists, &acl, &dummy))
{
__seterrno ();
debug_printf ("GetSecurityDescriptorDacl %E");
return -1;
}
int pos, i, types_def = 0;
if (!acl_exists || !acl)
for (pos = 0; pos < 3; ++pos) /* Don't change CLASS_OBJ entry */
lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
else
{
for (i = 0; i < acl->AceCount; ++i)
{
ACCESS_ALLOWED_ACE *ace;
2002-12-12 11:09:38 +08:00
if (!GetAce (acl, i, (PVOID *) &ace))
continue;
2003-02-06 00:15:22 +08:00
cygpsid ace_sid ((PSID) &ace->SidStart);
int id;
int type = 0;
if (ace_sid == well_known_world_sid)
{
type = OTHER_OBJ;
id = ILLEGAL_GID;
}
else if (ace_sid == group_sid)
{
type = GROUP_OBJ;
id = gid;
}
else if (ace_sid == owner_sid)
{
type = USER_OBJ;
id = uid;
}
else if (ace_sid == well_known_creator_group_sid)
{
type = GROUP_OBJ | ACL_DEFAULT;
id = ILLEGAL_GID;
}
else if (ace_sid == well_known_creator_owner_sid)
{
type = USER_OBJ | ACL_DEFAULT;
id = ILLEGAL_GID;
}
else
2003-02-06 00:15:22 +08:00
id = ace_sid.get_id (TRUE, &type);
if (!type)
continue;
if (!(ace->Header.AceFlags & INHERIT_ONLY || type & ACL_DEFAULT))
{
if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
}
if ((ace->Header.AceFlags & SUB_CONTAINERS_AND_OBJECTS_INHERIT)
&& (attr & FILE_ATTRIBUTE_DIRECTORY))
{
if (type == USER_OBJ)
type = USER;
else if (type == GROUP_OBJ)
type = GROUP;
type |= ACL_DEFAULT;
types_def |= type;
if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
}
}
/* Include DEF_CLASS_OBJ if any default ace exists */
2002-12-12 11:09:38 +08:00
if ((types_def & (USER|GROUP))
&& ((pos = searchace (lacl, MAX_ACL_ENTRIES, DEF_CLASS_OBJ)) >= 0))
{
lacl[pos].a_type = DEF_CLASS_OBJ;
lacl[pos].a_id = ILLEGAL_GID;
lacl[pos].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
}
}
if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0)
pos = MAX_ACL_ENTRIES;
if (aclbufp) {
2003-02-06 00:15:22 +08:00
if (owner_sid == group_sid)
lacl[0].a_perm = lacl[1].a_perm;
if (pos > nentries)
{
set_errno (ENOSPC);
return -1;
}
2003-02-06 00:15:22 +08:00
memcpy (aclbufp, lacl, pos * sizeof (__aclent32_t));
for (i = 0; i < pos; ++i)
aclbufp[i].a_perm &= ~(DENY_R | DENY_W | DENY_X);
2003-02-06 00:15:22 +08:00
aclsort32 (pos, 0, aclbufp);
}
syscall_printf ("%d = getacl (%s)", pos, file);
return pos;
}
static int
2003-02-06 00:15:22 +08:00
acl_worker (const char *path, int cmd, int nentries, __aclent32_t *aclbufp,
int nofollow)
{
extern suffix_info stat_suffixes[];
path_conv real_path (path, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_FULL, stat_suffixes);
if (real_path.error)
{
set_errno (real_path.error);
syscall_printf ("-1 = acl (%s)", path);
return -1;
}
if (!real_path.has_acls () || !allow_ntsec)
{
* cygwin.din (fstat64): New symbol. (ftruncate64): Ditto. (lseek64): Ditto. (lstat64): Ditto. (mmap64): Ditto. (seekdir64): Ditto. (stat64): Ditto. (telldir64): Ditto. (truncate64): Ditto. * dir.cc (telldir64): New function. (telldir): Call telldir64(). (seekdir64): New function. (seekdir): Call seekdir64(). * fhandler.h: Redefine all methods using __off32_t to use __off64_t. * fhandler.cc: Use __off64_t and struct __stat64 throughout. * fhandler_clipboard.cc: Ditto. * fhandler_disk_file.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_floppy.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_socket.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_zero.cc: Ditto. * pipe.cc: Ditto. * glob.c: Ditto, call lstat64 and stat64 in Cygwin. * mmap.cc: Use __off64_t throughout. (mmap64): New function. * sec_acl.cc (acl_worker): Use struct __stat64, call stat64 and lstat64. * syscalls.cc (lseek64): New function. (stat64_to_stat32): Ditto. (fstat64): Ditto. (stat64): Ditto. (lstat64): Ditto. (ftruncate64): Ditto. (truncate64): Ditto. (_fstat): Call fstat64. (_stat): Call stat64. (cygwin_lstat): Rename to avoid declaration problem. Call lstat64. (stat_worker): Use struct __stat64. (access): Ditto. (ftruncate): Call ftruncate64. (truncate): Call truncate64. * wincap.cc: Set flag has_64bit_file_access appropriately. * wincap.h: Add flag has_64bit_file_access. * winsup.h (ILLEGAL_SEEK): Define as __off64_t. (stat_dev): Declare using struct __stat64. (stat_worker): Ditto. * include/cygwin/stat.h (struct __stat32): Define if compiling Cygwin. (struct __stat64): Ditto. (struct stat): Revert definition with explicitly sized datatypes. Eliminate sized field names. * include/cygwin/types.h (blksize_t): New type. (__blkcnt32_t): Ditto. (__blkcnt64_t): Ditto. (blkcnt_t): Ditto.
2002-02-26 01:47:51 +08:00
struct __stat64 st;
int ret = -1;
switch (cmd)
{
case SETACL:
set_errno (ENOSYS);
break;
case GETACL:
if (!aclbufp)
set_errno(EFAULT);
else if (nentries < MIN_ACL_ENTRIES)
set_errno (ENOSPC);
* cygwin.din (fstat64): New symbol. (ftruncate64): Ditto. (lseek64): Ditto. (lstat64): Ditto. (mmap64): Ditto. (seekdir64): Ditto. (stat64): Ditto. (telldir64): Ditto. (truncate64): Ditto. * dir.cc (telldir64): New function. (telldir): Call telldir64(). (seekdir64): New function. (seekdir): Call seekdir64(). * fhandler.h: Redefine all methods using __off32_t to use __off64_t. * fhandler.cc: Use __off64_t and struct __stat64 throughout. * fhandler_clipboard.cc: Ditto. * fhandler_disk_file.cc: Ditto. * fhandler_dsp.cc: Ditto. * fhandler_floppy.cc: Ditto. * fhandler_mem.cc: Ditto. * fhandler_random.cc: Ditto. * fhandler_socket.cc: Ditto. * fhandler_tape.cc: Ditto. * fhandler_zero.cc: Ditto. * pipe.cc: Ditto. * glob.c: Ditto, call lstat64 and stat64 in Cygwin. * mmap.cc: Use __off64_t throughout. (mmap64): New function. * sec_acl.cc (acl_worker): Use struct __stat64, call stat64 and lstat64. * syscalls.cc (lseek64): New function. (stat64_to_stat32): Ditto. (fstat64): Ditto. (stat64): Ditto. (lstat64): Ditto. (ftruncate64): Ditto. (truncate64): Ditto. (_fstat): Call fstat64. (_stat): Call stat64. (cygwin_lstat): Rename to avoid declaration problem. Call lstat64. (stat_worker): Use struct __stat64. (access): Ditto. (ftruncate): Call ftruncate64. (truncate): Call truncate64. * wincap.cc: Set flag has_64bit_file_access appropriately. * wincap.h: Add flag has_64bit_file_access. * winsup.h (ILLEGAL_SEEK): Define as __off64_t. (stat_dev): Declare using struct __stat64. (stat_worker): Ditto. * include/cygwin/stat.h (struct __stat32): Define if compiling Cygwin. (struct __stat64): Ditto. (struct stat): Revert definition with explicitly sized datatypes. Eliminate sized field names. * include/cygwin/types.h (blksize_t): New type. (__blkcnt32_t): Ditto. (__blkcnt64_t): Ditto. (blkcnt_t): Ditto.
2002-02-26 01:47:51 +08:00
else if ((nofollow && !lstat64 (path, &st))
|| (!nofollow && !stat64 (path, &st)))
{
aclbufp[0].a_type = USER_OBJ;
aclbufp[0].a_id = st.st_uid;
aclbufp[0].a_perm = (st.st_mode & S_IRWXU) >> 6;
aclbufp[1].a_type = GROUP_OBJ;
aclbufp[1].a_id = st.st_gid;
aclbufp[1].a_perm = (st.st_mode & S_IRWXG) >> 3;
aclbufp[2].a_type = OTHER_OBJ;
aclbufp[2].a_id = ILLEGAL_GID;
aclbufp[2].a_perm = st.st_mode & S_IRWXO;
aclbufp[3].a_type = CLASS_OBJ;
aclbufp[3].a_id = ILLEGAL_GID;
aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
ret = MIN_ACL_ENTRIES;
}
break;
case GETACLCNT:
ret = MIN_ACL_ENTRIES;
break;
}
syscall_printf ("%d = acl (%s)", ret, path);
return ret;
}
switch (cmd)
{
case SETACL:
2003-02-06 00:15:22 +08:00
if (!aclsort32 (nentries, 0, aclbufp))
return setacl (real_path.get_win32 (),
nentries, aclbufp);
break;
case GETACL:
if (!aclbufp)
set_errno(EFAULT);
else
return getacl (real_path.get_win32 (),
real_path.file_attributes (),
nentries, aclbufp);
break;
case GETACLCNT:
return getacl (real_path.get_win32 (),
real_path.file_attributes (),
0, NULL);
default:
set_errno (EINVAL);
break;
}
syscall_printf ("-1 = acl (%s)", path);
return -1;
}
extern "C" int
2003-02-06 00:15:22 +08:00
acl32 (const char *path, int cmd, int nentries, __aclent32_t *aclbufp)
{
return acl_worker (path, cmd, nentries, aclbufp, 0);
}
extern "C" int
2003-02-06 00:15:22 +08:00
lacl32 (const char *path, int cmd, int nentries, __aclent32_t *aclbufp)
{
return acl_worker (path, cmd, nentries, aclbufp, 1);
}
extern "C" int
2003-02-06 00:15:22 +08:00
facl32 (int fd, int cmd, int nentries, __aclent32_t *aclbufp)
{
cygheap_fdget cfd (fd);
if (cfd < 0)
{
syscall_printf ("-1 = facl (%d)", fd);
return -1;
}
const char *path = cfd->get_name ();
if (path == NULL)
{
syscall_printf ("-1 = facl (%d) (no name)", fd);
set_errno (ENOSYS);
return -1;
}
syscall_printf ("facl (%d): calling acl (%s)", fd, path);
return acl_worker (path, cmd, nentries, aclbufp, 0);
}
extern "C" int
2003-02-06 00:15:22 +08:00
aclcheck32 (__aclent32_t *aclbufp, int nentries, int *which)
{
BOOL has_user_obj = FALSE;
BOOL has_group_obj = FALSE;
BOOL has_other_obj = FALSE;
BOOL has_class_obj = FALSE;
BOOL has_ug_objs = FALSE;
BOOL has_def_user_obj = FALSE;
BOOL has_def_group_obj = FALSE;
BOOL has_def_other_obj = FALSE;
BOOL has_def_class_obj = FALSE;
BOOL has_def_ug_objs = FALSE;
int pos2;
for (int pos = 0; pos < nentries; ++pos)
switch (aclbufp[pos].a_type)
{
case USER_OBJ:
if (has_user_obj)
{
if (which)
*which = pos;
return USER_ERROR;
}
has_user_obj = TRUE;
break;
case GROUP_OBJ:
if (has_group_obj)
{
if (which)
*which = pos;
return GRP_ERROR;
}
has_group_obj = TRUE;
break;
case OTHER_OBJ:
if (has_other_obj)
{
if (which)
*which = pos;
return OTHER_ERROR;
}
has_other_obj = TRUE;
break;
case CLASS_OBJ:
if (has_class_obj)
{
if (which)
*which = pos;
return CLASS_ERROR;
}
has_class_obj = TRUE;
break;
case USER:
case GROUP:
if ((pos2 = searchace (aclbufp + pos + 1, nentries - pos - 1,
aclbufp[pos].a_type, aclbufp[pos].a_id)) >= 0)
{
if (which)
*which = pos2;
return DUPLICATE_ERROR;
}
has_ug_objs = TRUE;
break;
case DEF_USER_OBJ:
if (has_def_user_obj)
{
if (which)
*which = pos;
return USER_ERROR;
}
has_def_user_obj = TRUE;
break;
case DEF_GROUP_OBJ:
if (has_def_group_obj)
{
if (which)
*which = pos;
return GRP_ERROR;
}
has_def_group_obj = TRUE;
break;
case DEF_OTHER_OBJ:
if (has_def_other_obj)
{
if (which)
*which = pos;
return OTHER_ERROR;
}
has_def_other_obj = TRUE;
break;
case DEF_CLASS_OBJ:
if (has_def_class_obj)
{
if (which)
*which = pos;
return CLASS_ERROR;
}
has_def_class_obj = TRUE;
break;
case DEF_USER:
case DEF_GROUP:
if ((pos2 = searchace (aclbufp + pos + 1, nentries - pos - 1,
aclbufp[pos].a_type, aclbufp[pos].a_id)) >= 0)
{
if (which)
*which = pos2;
return DUPLICATE_ERROR;
}
has_def_ug_objs = TRUE;
break;
default:
return ENTRY_ERROR;
}
if (!has_user_obj
|| !has_group_obj
|| !has_other_obj
#if 0
/* These checks are not ok yet since CLASS_OBJ isn't fully implemented. */
|| (has_ug_objs && !has_class_obj)
|| (has_def_ug_objs && !has_def_class_obj)
#endif
)
{
if (which)
*which = -1;
return MISS_ERROR;
}
return 0;
}
static int
acecmp (const void *a1, const void *a2)
{
2003-02-06 00:15:22 +08:00
#define ace(i) ((const __aclent32_t *) a##i)
int ret = ace (1)->a_type - ace (2)->a_type;
if (!ret)
ret = ace (1)->a_id - ace (2)->a_id;
return ret;
#undef ace
}
extern "C" int
2003-02-06 00:15:22 +08:00
aclsort32 (int nentries, int, __aclent32_t *aclbufp)
{
2003-02-06 00:15:22 +08:00
if (aclcheck32 (aclbufp, nentries, NULL))
return -1;
if (!aclbufp || nentries < 1)
{
set_errno (EINVAL);
return -1;
}
2003-02-06 00:15:22 +08:00
qsort ((void *) aclbufp, nentries, sizeof (__aclent32_t), acecmp);
return 0;
}
extern "C" int
2003-02-06 00:15:22 +08:00
acltomode32 (__aclent32_t *aclbufp, int nentries, mode_t *modep)
{
int pos;
if (!aclbufp || nentries < 1 || !modep)
{
set_errno (EINVAL);
return -1;
}
*modep = 0;
if ((pos = searchace (aclbufp, nentries, USER_OBJ)) < 0
|| !aclbufp[pos].a_type)
{
set_errno (EINVAL);
return -1;
}
*modep |= (aclbufp[pos].a_perm & S_IRWXO) << 6;
if ((pos = searchace (aclbufp, nentries, GROUP_OBJ)) < 0
|| !aclbufp[pos].a_type)
{
set_errno (EINVAL);
return -1;
}
*modep |= (aclbufp[pos].a_perm & S_IRWXO) << 3;
int cpos;
if ((cpos = searchace (aclbufp, nentries, CLASS_OBJ)) >= 0
&& aclbufp[cpos].a_type == CLASS_OBJ)
*modep |= ((aclbufp[pos].a_perm & S_IRWXO) & aclbufp[cpos].a_perm) << 3;
if ((pos = searchace (aclbufp, nentries, OTHER_OBJ)) < 0
|| !aclbufp[pos].a_type)
{
set_errno (EINVAL);
return -1;
}
*modep |= aclbufp[pos].a_perm & S_IRWXO;
return 0;
}
extern "C" int
2003-02-06 00:15:22 +08:00
aclfrommode32 (__aclent32_t *aclbufp, int nentries, mode_t *modep)
{
int pos;
if (!aclbufp || nentries < 1 || !modep)
{
set_errno (EINVAL);
return -1;
}
if ((pos = searchace (aclbufp, nentries, USER_OBJ)) < 0
|| !aclbufp[pos].a_type)
{
set_errno (EINVAL);
return -1;
}
aclbufp[pos].a_perm = (*modep & S_IRWXU) >> 6;
if ((pos = searchace (aclbufp, nentries, GROUP_OBJ)) < 0
|| !aclbufp[pos].a_type)
{
set_errno (EINVAL);
return -1;
}
aclbufp[pos].a_perm = (*modep & S_IRWXG) >> 3;
if ((pos = searchace (aclbufp, nentries, CLASS_OBJ)) >= 0
&& aclbufp[pos].a_type == CLASS_OBJ)
aclbufp[pos].a_perm = (*modep & S_IRWXG) >> 3;
if ((pos = searchace (aclbufp, nentries, OTHER_OBJ)) < 0
|| !aclbufp[pos].a_type)
{
set_errno (EINVAL);
return -1;
}
aclbufp[pos].a_perm = (*modep & S_IRWXO);
return 0;
}
extern "C" int
2003-02-06 00:15:22 +08:00
acltopbits32 (__aclent32_t *aclbufp, int nentries, mode_t *pbitsp)
{
2003-02-06 00:15:22 +08:00
return acltomode32 (aclbufp, nentries, pbitsp);
}
extern "C" int
2003-02-06 00:15:22 +08:00
aclfrompbits32 (__aclent32_t *aclbufp, int nentries, mode_t *pbitsp)
{
2003-02-06 00:15:22 +08:00
return aclfrommode32 (aclbufp, nentries, pbitsp);
}
static char *
permtostr (mode_t perm)
{
static char pbuf[4];
pbuf[0] = (perm & S_IROTH) ? 'r' : '-';
pbuf[1] = (perm & S_IWOTH) ? 'w' : '-';
pbuf[2] = (perm & S_IXOTH) ? 'x' : '-';
pbuf[3] = '\0';
return pbuf;
}
extern "C" char *
2003-02-06 00:15:22 +08:00
acltotext32 (__aclent32_t *aclbufp, int aclcnt)
{
if (!aclbufp || aclcnt < 1 || aclcnt > MAX_ACL_ENTRIES
2003-02-06 00:15:22 +08:00
|| aclcheck32 (aclbufp, aclcnt, NULL))
{
set_errno (EINVAL);
return NULL;
}
char buf[32000];
buf[0] = '\0';
BOOL first = TRUE;
for (int pos = 0; pos < aclcnt; ++pos)
{
if (!first)
strcat (buf, ",");
first = FALSE;
if (aclbufp[pos].a_type & ACL_DEFAULT)
strcat (buf, "default");
switch (aclbufp[pos].a_type)
{
case USER_OBJ:
__small_sprintf (buf + strlen (buf), "user::%s",
permtostr (aclbufp[pos].a_perm));
break;
case USER:
__small_sprintf (buf + strlen (buf), "user:%d:%s",
aclbufp[pos].a_id, permtostr (aclbufp[pos].a_perm));
break;
case GROUP_OBJ:
__small_sprintf (buf + strlen (buf), "group::%s",
permtostr (aclbufp[pos].a_perm));
break;
case GROUP:
__small_sprintf (buf + strlen (buf), "group:%d:%s",
aclbufp[pos].a_id, permtostr (aclbufp[pos].a_perm));
break;
case CLASS_OBJ:
__small_sprintf (buf + strlen (buf), "mask::%s",
permtostr (aclbufp[pos].a_perm));
break;
case OTHER_OBJ:
__small_sprintf (buf + strlen (buf), "other::%s",
permtostr (aclbufp[pos].a_perm));
break;
default:
set_errno (EINVAL);
return NULL;
}
}
return strdup (buf);
}
static mode_t
permfromstr (char *perm)
{
mode_t mode = 0;
if (strlen (perm) != 3)
return 01000;
if (perm[0] == 'r')
mode |= S_IROTH;
else if (perm[0] != '-')
return 01000;
if (perm[1] == 'w')
mode |= S_IWOTH;
else if (perm[1] != '-')
return 01000;
if (perm[2] == 'x')
mode |= S_IXOTH;
else if (perm[2] != '-')
return 01000;
return mode;
}
extern "C" __aclent32_t *
2003-02-06 00:15:22 +08:00
aclfromtext32 (char *acltextp, int *)
{
if (!acltextp)
{
set_errno (EINVAL);
return NULL;
}
char buf[strlen (acltextp) + 1];
2003-02-06 00:15:22 +08:00
__aclent32_t lacl[MAX_ACL_ENTRIES];
memset (lacl, 0, sizeof lacl);
int pos = 0;
strcpy (buf, acltextp);
char *lasts;
for (char *c = strtok_r (buf, ",", &lasts);
c;
c = strtok_r (NULL, ",", &lasts))
{
if (!strncmp (c, "default", 7))
{
lacl[pos].a_type |= ACL_DEFAULT;
c += 7;
}
if (!strncmp (c, "user:", 5))
{
if (c[5] == ':')
lacl[pos].a_type |= USER_OBJ;
else
{
lacl[pos].a_type |= USER;
c += 5;
if (isalpha (*c))
{
2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> * pwdgrp.h (pwdgrp_check::pwdgrp_state): Replace by pwdgrp_check::isinitializing (). (pwdgrp_check::isinitializing): Create. * passwd.cc (grab_int): Change type to unsigned, use strtoul and set the pointer content to 0 if the field is invalid. (parse_pwd): Move validity test after getting pw_gid. (read_etc_passwd): Replace "passwd_state <= " by passwd_state::isinitializing (). (internal_getpwuid): Ditto. (internal_getpwnam): Ditto. (getpwent): Ditto. (getpass): Ditto. * grp.cc (parse_grp): Use strtoul for gr_gid and verify the validity. (read_etc_group): Replace "group_state <= " by group_state::isinitializing (). (internal_getgrgid): Ditto. (getgrent32): Ditto. (internal_getgrent): Ditto. 2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> * security.h: Move declarations of internal_getgrent, internal_getpwsid and internal_getgrsid to pwdgrp.h. * pwdgrp.h: Declare internal_getpwsid, internal_getpwnam, internal_getpwuid, internal_getgrsid, internal_getgrgid, internal_getgrnam, internal_getgrent and internal_getgroups. Delete "emulated" from enum pwdgrp_state. (pwdgrp_check::isuninitialized): Create. (pwdgrp_check::pwdgrp_state): Change state to initializing rather than to uninitialized. (pwdgrp_read::gets): Remove trailing CRs. * passwd.cc (grab_string): Don't look for NLs. (grab_int): Ditto. (parse_pwd): Don't look for CRs. Return 0 if entry is too short. (search_for): Delete. (read_etc_passwd): Simplify tests to actually read the file. Set state to loaded before making internal_getpwXX calls. Replace search_for calls by equivalent internal_pwgetXX calls. (internal_getpwsid): Use passwd_state.isuninitialized to decide to call read_etc_passwd. (internal_getpwuid): Create. (internal_getpwnam): Create. (getpwuid32): Simply call internal_getpwuid. (getpwuid_r32): Call internal_getpwuid. (getpwnam): Simply call internal_getpwnam. (getpwnam_r): Call internal_getpwnam. * grp.cc (parse_grp): Don't look for CRs. Adjust blank space. (add_grp_line): Adjust blank space. (class group_lock): Ditto. (read_etc_group): Simplify tests to actually read the file. Set state to loaded before making internal_getgrXX calls. Replace getgrXX calls by equivalent internal calls. (internal_getgrsid): Use group_state.isuninitialized to decide to call read_etc_group. (internal_getgrgid): Create. (internal_getgrnam): Create. (getgroups32): Simply call internal_getgrgid. (getgrnam32): Simply call internal_getgrnam. (internal_getgrent): Call group_state.isuninitialized. (internal_getgroups): Create from the former getgroups32, using two of the four arguments. Set gid to myself->gid and username to cygheap->user.name (). (getgroups32): Simply call internal_getgroup. (getgroups): Call internal_getgroup instead of getgroups32. (setgroups32): Call internal versions of get{pw,gr}XX. * sec_helper.cc: Include pwdgrp.h. (is_grp_member): Call internal versions of get{pw,gr}XX. * security.cc: Include pwdgrp.h. (alloc_sd): Call internal versions of get{pw,gr}XX. * syscalls.cc: Include pwdgrp.h. (seteuid32): Call internal versions of get{pw,gr}XX. (setegid32): Ditto. * uinfo.cc: Include pwdgrp.h. (internal_getlogin): Call internal versions of get{pw,gr}XX. (cygheap_user::ontherange): Ditto. * sec_acl.cc: Include pwdgrp.h. (setacl): Call internal versions of get{pw,gr}XX. (acl_access): Ditto and simplify logic. (aclfromtext): Ditto.
2002-12-10 20:43:49 +08:00
struct passwd *pw = internal_getpwnam (c);
if (!pw)
{
set_errno (EINVAL);
return NULL;
}
lacl[pos].a_id = pw->pw_uid;
2003-02-06 00:15:22 +08:00
c = strechr (c, ':');
}
else if (isdigit (*c))
lacl[pos].a_id = strtol (c, &c, 10);
2003-02-06 00:15:22 +08:00
if (*c != ':')
{
set_errno (EINVAL);
return NULL;
}
}
}
else if (!strncmp (c, "group:", 6))
{
if (c[5] == ':')
lacl[pos].a_type |= GROUP_OBJ;
else
{
lacl[pos].a_type |= GROUP;
c += 5;
if (isalpha (*c))
{
2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> * pwdgrp.h (pwdgrp_check::pwdgrp_state): Replace by pwdgrp_check::isinitializing (). (pwdgrp_check::isinitializing): Create. * passwd.cc (grab_int): Change type to unsigned, use strtoul and set the pointer content to 0 if the field is invalid. (parse_pwd): Move validity test after getting pw_gid. (read_etc_passwd): Replace "passwd_state <= " by passwd_state::isinitializing (). (internal_getpwuid): Ditto. (internal_getpwnam): Ditto. (getpwent): Ditto. (getpass): Ditto. * grp.cc (parse_grp): Use strtoul for gr_gid and verify the validity. (read_etc_group): Replace "group_state <= " by group_state::isinitializing (). (internal_getgrgid): Ditto. (getgrent32): Ditto. (internal_getgrent): Ditto. 2002-12-10 Pierre Humblet <pierre.humblet@ieee.org> * security.h: Move declarations of internal_getgrent, internal_getpwsid and internal_getgrsid to pwdgrp.h. * pwdgrp.h: Declare internal_getpwsid, internal_getpwnam, internal_getpwuid, internal_getgrsid, internal_getgrgid, internal_getgrnam, internal_getgrent and internal_getgroups. Delete "emulated" from enum pwdgrp_state. (pwdgrp_check::isuninitialized): Create. (pwdgrp_check::pwdgrp_state): Change state to initializing rather than to uninitialized. (pwdgrp_read::gets): Remove trailing CRs. * passwd.cc (grab_string): Don't look for NLs. (grab_int): Ditto. (parse_pwd): Don't look for CRs. Return 0 if entry is too short. (search_for): Delete. (read_etc_passwd): Simplify tests to actually read the file. Set state to loaded before making internal_getpwXX calls. Replace search_for calls by equivalent internal_pwgetXX calls. (internal_getpwsid): Use passwd_state.isuninitialized to decide to call read_etc_passwd. (internal_getpwuid): Create. (internal_getpwnam): Create. (getpwuid32): Simply call internal_getpwuid. (getpwuid_r32): Call internal_getpwuid. (getpwnam): Simply call internal_getpwnam. (getpwnam_r): Call internal_getpwnam. * grp.cc (parse_grp): Don't look for CRs. Adjust blank space. (add_grp_line): Adjust blank space. (class group_lock): Ditto. (read_etc_group): Simplify tests to actually read the file. Set state to loaded before making internal_getgrXX calls. Replace getgrXX calls by equivalent internal calls. (internal_getgrsid): Use group_state.isuninitialized to decide to call read_etc_group. (internal_getgrgid): Create. (internal_getgrnam): Create. (getgroups32): Simply call internal_getgrgid. (getgrnam32): Simply call internal_getgrnam. (internal_getgrent): Call group_state.isuninitialized. (internal_getgroups): Create from the former getgroups32, using two of the four arguments. Set gid to myself->gid and username to cygheap->user.name (). (getgroups32): Simply call internal_getgroup. (getgroups): Call internal_getgroup instead of getgroups32. (setgroups32): Call internal versions of get{pw,gr}XX. * sec_helper.cc: Include pwdgrp.h. (is_grp_member): Call internal versions of get{pw,gr}XX. * security.cc: Include pwdgrp.h. (alloc_sd): Call internal versions of get{pw,gr}XX. * syscalls.cc: Include pwdgrp.h. (seteuid32): Call internal versions of get{pw,gr}XX. (setegid32): Ditto. * uinfo.cc: Include pwdgrp.h. (internal_getlogin): Call internal versions of get{pw,gr}XX. (cygheap_user::ontherange): Ditto. * sec_acl.cc: Include pwdgrp.h. (setacl): Call internal versions of get{pw,gr}XX. (acl_access): Ditto and simplify logic. (aclfromtext): Ditto.
2002-12-10 20:43:49 +08:00
struct __group32 *gr = internal_getgrnam (c);
if (!gr)
{
set_errno (EINVAL);
return NULL;
}
lacl[pos].a_id = gr->gr_gid;
2003-02-06 00:15:22 +08:00
c = strechr (c, ':');
}
else if (isdigit (*c))
lacl[pos].a_id = strtol (c, &c, 10);
2003-02-06 00:15:22 +08:00
if (*c != ':')
{
set_errno (EINVAL);
return NULL;
}
}
}
else if (!strncmp (c, "mask:", 5))
{
if (c[5] == ':')
lacl[pos].a_type |= CLASS_OBJ;
else
{
set_errno (EINVAL);
return NULL;
}
}
else if (!strncmp (c, "other:", 6))
{
if (c[5] == ':')
lacl[pos].a_type |= OTHER_OBJ;
else
{
set_errno (EINVAL);
return NULL;
}
}
if ((lacl[pos].a_perm = permfromstr (c)) == 01000)
{
set_errno (EINVAL);
return NULL;
}
++pos;
}
2003-02-06 00:15:22 +08:00
__aclent32_t *aclp = (__aclent32_t *) malloc (pos * sizeof (__aclent32_t));
if (aclp)
2003-02-06 00:15:22 +08:00
memcpy (aclp, lacl, pos * sizeof (__aclent32_t));
return aclp;
}
2003-02-06 00:15:22 +08:00
/* __aclent16_t and __aclent32_t have same size and same member offsets */
static __aclent32_t *
acl16to32 (__aclent16_t *aclbufp, int nentries)
{
__aclent32_t *aclbufp32 = (__aclent32_t *) aclbufp;
if (aclbufp32)
for (int i = 0; i < nentries; i++)
aclbufp32[i].a_id &= USHRT_MAX;
return aclbufp32;
}
extern "C" int
2003-02-06 00:15:22 +08:00
acl (const char *path, int cmd, int nentries, __aclent16_t *aclbufp)
{
return acl32 (path, cmd, nentries, acl16to32 (aclbufp, nentries));
}
extern "C" int
2003-02-06 00:15:22 +08:00
facl (int fd, int cmd, int nentries, __aclent16_t *aclbufp)
{
return facl32 (fd, cmd, nentries, acl16to32 (aclbufp, nentries));
}
extern "C" int
2003-02-06 00:15:22 +08:00
lacl (const char *path, int cmd, int nentries, __aclent16_t *aclbufp)
{
return lacl32 (path, cmd, nentries, acl16to32 (aclbufp, nentries));
}
extern "C" int
2003-02-06 00:15:22 +08:00
aclcheck (__aclent16_t *aclbufp, int nentries, int *which)
{
return aclcheck32 (acl16to32 (aclbufp, nentries), nentries, which);
}
extern "C" int
2003-02-06 00:15:22 +08:00
aclsort (int nentries, int i, __aclent16_t *aclbufp)
{
return aclsort32 (nentries, i, acl16to32 (aclbufp, nentries));
}
extern "C" int
2003-02-06 00:15:22 +08:00
acltomode (__aclent16_t *aclbufp, int nentries, mode_t *modep)
{
return acltomode32 (acl16to32 (aclbufp, nentries), nentries, modep);
}
extern "C" int
2003-02-06 00:15:22 +08:00
aclfrommode (__aclent16_t *aclbufp, int nentries, mode_t *modep)
{
return aclfrommode32 ((__aclent32_t *)aclbufp, nentries, modep);
}
extern "C" int
2003-02-06 00:15:22 +08:00
acltopbits (__aclent16_t *aclbufp, int nentries, mode_t *pbitsp)
{
return acltopbits32 (acl16to32 (aclbufp, nentries), nentries, pbitsp);
}
extern "C" int
2003-02-06 00:15:22 +08:00
aclfrompbits (__aclent16_t *aclbufp, int nentries, mode_t *pbitsp)
{
return aclfrompbits32 ((__aclent32_t *)aclbufp, nentries, pbitsp);
}
extern "C" char *
2003-02-06 00:15:22 +08:00
acltotext (__aclent16_t *aclbufp, int aclcnt)
{
return acltotext32 (acl16to32 (aclbufp, aclcnt), aclcnt);
}
extern "C" __aclent16_t *
2003-02-06 00:15:22 +08:00
aclfromtext (char *acltextp, int * aclcnt)
{
return (__aclent16_t *) aclfromtext32 (acltextp, aclcnt);
}