From ba1976d3cee42fb4247d23c49ee29dfc1e0fbe74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net> Date: Sat, 14 Aug 1999 02:00:42 -0700 Subject: [PATCH] file permission functions implemented... Rev: src/modules/system/nt.c:1.13 --- src/modules/system/nt.c | 572 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 561 insertions(+), 11 deletions(-) diff --git a/src/modules/system/nt.c b/src/modules/system/nt.c index bfe096f681..eff3c54fd6 100644 --- a/src/modules/system/nt.c +++ b/src/modules/system/nt.c @@ -1,5 +1,5 @@ /* - * $Id: nt.c,v 1.12 1999/06/19 20:26:54 hubbe Exp $ + * $Id: nt.c,v 1.13 1999/08/14 09:00:42 hubbe Exp $ * * NT system calls for Pike * @@ -18,6 +18,7 @@ #include "threads.h" #include "module_support.h" #include "array.h" +#include "mapping.h" #include "constants.h" #include "builtin_functions.h" @@ -25,6 +26,7 @@ #include <windows.h> #include <winbase.h> #include <lm.h> +#include <accctrl.h> static void f_cp(INT32 args) { @@ -116,8 +118,115 @@ typedef DWORD (WINAPI *getlengthsidtype)(PSID); static logonusertype logonuser; static getlengthsidtype getlengthsid; + +#define LINKFUNC(RET,NAME,TYPE) \ + typedef RET (WINAPI * PIKE_CONCAT(NAME,type)) TYPE ; \ + static PIKE_CONCAT(NAME,type) NAME + +LINKFUNC(BOOL,equalsid, (PSID,PSID) ); +LINKFUNC(BOOL,lookupaccountname, + (LPCTSTR,LPCTSTR,PSID,LPDWORD,LPTSTR,LPDWORD,PSID_NAME_USE) ); +LINKFUNC(BOOL,lookupaccountsid, + (LPCTSTR,PSID,LPTSTR,LPDWORD,LPTSTR,LPDWORD,PSID_NAME_USE) ); +LINKFUNC(BOOL,setnamedsecurityinfo, + (LPTSTR,SE_OBJECT_TYPE,SECURITY_INFORMATION,PSID,PSID,PACL,PACL) ); +LINKFUNC(DWORD,getnamedsecurityinfo, + (LPTSTR,SE_OBJECT_TYPE,SECURITY_INFORMATION,PSID*,PSID*,PACL*,PACL*,PSECURITY_DESCRIPTOR) ); + +LINKFUNC(BOOL,initializeacl, (PACL,DWORD,DWORD) ); +LINKFUNC(BOOL,addaccessallowedace, (PACL,DWORD,DWORD,PSID) ); +LINKFUNC(BOOL,addaccessdeniedace, (PACL,DWORD,DWORD,PSID) ); +LINKFUNC(BOOL,addauditaccessace, (PACL,DWORD,DWORD,PSID,BOOL,BOOL) ); + HINSTANCE advapilib; +#define THIS_PSID (*(PSID *)fp->current_storage) +static struct program *sid_program; +static void init_sid(struct object *o) +{ + THIS_PSID=0; +} + +static void exit_sid(struct object *o) +{ + if(THIS_PSID) + { + free((char *)THIS_PSID); + THIS_PSID=0; + } +} + +static void f_sid_eq(INT32 args) +{ + check_all_args("system.SID->`==",args,BIT_MIXED,0); + if(sp[-1].type == T_OBJECT) + { + PSID *tmp=(PSID *)get_storage(sp[-1].u.object,sid_program); + if(tmp) + { + if( (!THIS_PSID && !*tmp) || + (THIS_PSID && *tmp && equalsid(THIS_PSID, *tmp) )) + { + pop_stack(); + push_int(1); + return; + } + } + } + pop_stack(); + push_int(0); +} + +static void f_sid_account(INT32 args) +{ + char foo[1]; + DWORD namelen=0; + DWORD domainlen=0; + char *sys=0; + SID_NAME_USE type; + + check_all_args("SID->account",args,BIT_STRING|BIT_VOID, 0); + if(args) sys=sp[-1].u.string->str; + + if(!THIS_PSID) error("SID->account on uninitialized SID.\n"); + lookupaccountsid(sys, + THIS_PSID, + foo, + &namelen, + foo, + &domainlen, + &type); + + + if(namelen && domainlen) + { + struct pike_string *dom=begin_shared_string(domainlen-1); + struct pike_string *name=begin_shared_string(namelen-1); + + if(lookupaccountsid(sys, + THIS_PSID, + STR0(name), + &namelen, + STR0(dom), + &domainlen, + &type)) + { + push_string(end_shared_string(name)); + push_string(end_shared_string(dom)); + push_int(type); + f_aggregate(3); + return; + } + free((char *)dom); + free((char *)name); + } + errno=GetLastError(); + pop_n_elems(args); + push_array(allocate_array(3)); + +} + + void f_LogonUser(INT32 args) { LPTSTR username, domain, pw; @@ -423,11 +532,18 @@ static void encode_localgroup_users_info(BYTE *u, int level) static void low_encode_localgroup_members_info_0(LOCALGROUP_MEMBERS_INFO_0 *tmp) { -#define SAFE_PUSH_SID(X) \ - if(getlengthsid && (X)) \ - push_string(make_shared_binary_string((char *)(X),getlengthsid((X)))); \ - else \ - push_int(0) + +#define SAFE_PUSH_SID(X) do { \ + if(getlengthsid && (X) && sid_program) { \ + int lentmp=getlengthsid( (X) ); \ + PSID psidtmp=(PSID)xalloc(lentmp); \ + struct object *o=low_clone(sid_program); \ + MEMCPY( psidtmp, (X), lentmp); \ + (*(PSID *)(o->storage))=psidtmp; \ + push_object(o); \ + } else { \ + push_int(0); \ + } } while(0) SAFE_PUSH_SID(tmp->lgrmi0_sid); } @@ -1216,12 +1332,391 @@ void f_NetLocalGroupGetMembers(INT32 args) if(to_free2) free(to_free2); } +static void f_GetFileAttributes(INT32 args) +{ + char *file; + DWORD ret; + get_all_args("GetFileAttributes",args,"%s",&file); + ret=GetFileAttributes( (LPCTSTR) file); + pop_stack(); + errno=GetLastError(); + push_int(ret); +} + +static void f_SetFileAttributes(INT32 args) +{ + char *file; + INT32 attr,ret; + DWORD tmp; + get_all_args("SetFileAttributes",args,"%s%d",&file,&attr); + tmp=attr; + ret=SetFileAttributes( (LPCTSTR) file, tmp); + pop_stack(); + errno=GetLastError(); + push_int(ret); +} + +static void f_LookupAccountName(INT32 args) +{ + LPCTSTR sys=0; + LPCTSTR acc; + DWORD sidlen, domainlen; + SID_NAME_USE tmp; + char buffer[1]; + + check_all_args("LookupAccountName",args,BIT_INT|BIT_STRING, BIT_STRING,0); + if(sp[-args].type == T_STRING) + { + if(sp[-args].u.string->size_shift != 0) + error("LookupAccountName: System name is wide string.\n"); + sys=STR0(sp[-args].u.string); + } + if(sp[1-args].u.string->size_shift != 0) + error("LookupAccountName: Account name is wide string.\n"); + + acc=STR0(sp[1-args].u.string); + + sidlen=0; + domainlen=0; + + /* Find size required */ + lookupaccountname(sys, + acc, + (PSID)buffer, + &sidlen, + (LPTSTR)buffer, + &domainlen, + &tmp); + + if(sidlen && domainlen) + { + PSID sid=(PSID)xalloc(sidlen); + struct pike_string *dom=begin_shared_string(domainlen-1); + + if(lookupaccountname(sys, + acc, + sid, + &sidlen, + (LPTSTR)(STR0(dom)), + &domainlen, + &tmp)) + { + struct object *o; + pop_n_elems(args); + o=low_clone(sid_program); + (*(PSID *)(o->storage))=sid; + push_object(o); + push_string(end_shared_string(dom)); + push_int(tmp); + f_aggregate(3); + return; + } + free((char *)dom); + free((char *)sid); + } + errno=GetLastError(); + pop_n_elems(args); + push_array(allocate_array(3)); +} + + +static struct array *encode_acl(PACL acl) +{ + ACL_SIZE_INFORMATION tmp; + if(GetAclInformation(acl, &tmp, sizeof(tmp), AclSizeInformation)) + { + int e; + check_stack(tmp.AceCount + 4); + for(e=0;e<tmp.AceCount;e++) + { + void *ace; + if(!GetAce(acl, e, &ace)) break; + switch(((ACE_HEADER *)ace)->AceType) + { + case ACCESS_ALLOWED_ACE_TYPE: + push_constant_text("allow"); + push_int(((ACE_HEADER *)ace)->AceFlags); + push_int( ((ACCESS_ALLOWED_ACE *)ace)->Mask ); + SAFE_PUSH_SID( & ((ACCESS_ALLOWED_ACE *)ace)->SidStart ); + f_aggregate(4); + break; + + case ACCESS_DENIED_ACE_TYPE: + push_constant_text("deny"); + push_int(((ACE_HEADER *)ace)->AceFlags); + push_int( ((ACCESS_DENIED_ACE *)ace)->Mask ); + SAFE_PUSH_SID( & ((ACCESS_DENIED_ACE *)ace)->SidStart ); + f_aggregate(4); + break; + + case SYSTEM_AUDIT_ACE_TYPE: + push_constant_text("audit"); + push_int(((ACE_HEADER *)ace)->AceFlags); + push_int( ((SYSTEM_AUDIT_ACE *)ace)->Mask ); + SAFE_PUSH_SID( & ((SYSTEM_AUDIT_ACE *)ace)->SidStart ); + f_aggregate(4); + break; + + default: + push_constant_text("unknown"); + f_aggregate(1); + break; + + } + } + return aggregate_array(e); + } + return 0; +} + +static PACL decode_acl(struct array *arr) +{ + PACL ret; + int a; + int size=sizeof(ACL); + char *str; + PSID *sid; + + for(a=0;a<arr->size;a++) + { + if(arr->item[a].type != T_ARRAY) + error("Index %d in ACL is not an array.\n",a); + + if(arr->item[a].u.array->size != 4) + error("Index %d in ACL is not of size 4.\n",a); + + if(arr->item[a].u.array->item[0].type != T_STRING) + error("ACE[%d][%d] is not a string.\n",a,0); + + if(arr->item[a].u.array->item[1].type != T_INT) + error("ACE[%d][%d] is not an integer.\n",a,1); + + if(arr->item[a].u.array->item[2].type != T_INT) + error("ACE[%d][%d] is not an integer.\n",a,2); + + if(arr->item[a].u.array->item[3].type != T_OBJECT) + error("ACE[%d][%d] is not a SID class.\n",a,3); + + sid=(PSID *)get_storage(arr->item[a].u.array->item[3].u.object,sid_program); + if(!sid || !*sid) + error("ACE[%d][%d] is not a SID class.\n",a,3); + + str=arr->item[a].u.array->item[0].u.string->str; + switch( ( str[0] << 8 ) + str[1] ) + { + case ( 'a' << 8 ) + 'c': size += sizeof(ACCESS_ALLOWED_ACE); break; + case ( 'd' << 8 ) + 'e': size += sizeof(ACCESS_DENIED_ACE); break; + case ( 'a' << 8 ) + 'u': size += sizeof(SYSTEM_AUDIT_ACE); break; + default: + error("ACE[%d][0] is not a known ACE type.\n"); + } + size += getlengthsid( *sid ) - sizeof(DWORD); + } + + ret=(PACL)xalloc( size ); + + if(!initializeacl(ret, size, ACL_REVISION)) + error("InitializeAcl failed!\n"); + + for(a=0;a<arr->size;a++) + { + str=arr->item[a].u.array->item[0].u.string->str; + sid=(PSID *)get_storage(arr->item[a].u.array->item[3].u.object,sid_program); + + switch( ( str[0] << 8 ) + str[1] ) + { + case ( 'a' << 8 ) + 'c': + if(!addaccessallowedace(ret, ACL_REVISION, + arr->item[a].u.array->item[2].u.integer, + sid)) + error("AddAccessAllowedAce failed!\n"); + break; + + case ( 'd' << 8 ) + 'e': + if(!addaccessdeniedace(ret, ACL_REVISION, + arr->item[a].u.array->item[2].u.integer, + sid)) + error("AddAccessDeniedAce failed!\n"); + break; + + case ( 'a' << 8 ) + 'u': + /* FIXME, what to do with the last two arguments ?? */ + if(!addauditaccessace(ret, ACL_REVISION, + arr->item[a].u.array->item[2].u.integer, + sid,1,1)) + error("AddAuditAccessAce failed!\n"); + break; + } + } + return ret; +} + +/* + * Note, this function does not use errno!! + * (Time to learn how to autodoc... /Hubbe) + */ +static void f_SetNamedSecurityInfo(INT32 args) +{ + struct svalue *sval; + char *name; + struct mapping *m; + SECURITY_INFORMATION flags=0; + PSID owner=0; + PSID group=0; + PACL dacl=0; + PACL sacl=0; + DWORD ret; + SE_OBJECT_TYPE type=SE_FILE_OBJECT; + + get_all_args("SetNamedSecurityInfo",args,"%s%m",&name,&m); + + if((sval=simple_mapping_string_lookup(m, "type"))) + { + if(sval->type != T_INT) + error("Bad 'type' in SetNamedSecurityInfo.\n"); + type=sval->u.integer; + } + + if((sval=simple_mapping_string_lookup(m,"owner"))) + { + if(sval->type != T_OBJECT || + !get_storage(sval->u.object, sid_program)) + error("Bad 'owner' in SetNamedSecurityInfo.\n"); + owner=*(PSID *)get_storage(sval->u.object, sid_program); + flags |= OWNER_SECURITY_INFORMATION; + } + + if((sval=simple_mapping_string_lookup(m,"group"))) + { + if(sval->type != T_OBJECT || + !get_storage(sval->u.object, sid_program)) + error("Bad 'group' in SetNamedSecurityInfo.\n"); + group=*(PSID *)get_storage(sval->u.object, sid_program); + flags |= GROUP_SECURITY_INFORMATION; + } + + if((sval=simple_mapping_string_lookup(m,"dacl"))) + { + if(sval->type != T_ARRAY) + error("Bad 'dacl' in SetNamedSecurityInfo.\n"); + dacl=decode_acl(sval->u.array); + flags |= DACL_SECURITY_INFORMATION; + } + + if((sval=simple_mapping_string_lookup(m,"sacl"))) + { + if(sval->type != T_ARRAY) + error("Bad 'sacl' in SetNamedSecurityInfo.\n"); + sacl=decode_acl(sval->u.array); + flags |= SACL_SECURITY_INFORMATION; + } + + /* FIXME, add dacl and sacl!!!! */ + + ret=setnamedsecurityinfo(name, + type, + flags, + owner, + group, + dacl, + sacl); + pop_n_elems(args); + push_int(ret); +} + +static void f_GetNamedSecurityInfo(INT32 args) +{ + PSID owner=0, group=0; + PACL dacl=0, sacl=0; + PSECURITY_DESCRIPTOR desc=0; + DWORD ret; + SECURITY_INFORMATION flags= + OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION; + + SE_OBJECT_TYPE type = SE_FILE_OBJECT; + check_all_args("GetSecurityInfo",args,BIT_STRING, BIT_VOID|BIT_INT, BIT_VOID|BIT_INT, 0); + + switch(args) + { + default: flags=sp[2-args].u.integer; + case 2: type=sp[1-args].u.integer; + case 1: break; + } + + if(!(ret=getnamedsecurityinfo(sp[-args].u.string->str, + type, + flags, + &owner, + &group, + &dacl, + &sacl, + &desc))) + { + int tmp=0; + pop_n_elems(args); + + if(owner) + { + push_constant_text("owner"); + SAFE_PUSH_SID(owner); + tmp++; + } + if(group) + { + push_constant_text("group"); + SAFE_PUSH_SID(group); + tmp++; + } + if(sacl) + { + push_constant_text("sacl"); + push_array( encode_acl( sacl )); + tmp++; + } + if(dacl) + { + push_constant_text("dacl"); + push_array( encode_acl( dacl )); + tmp++; + } + f_aggregate_mapping(tmp * 2); + }else{ + pop_n_elems(args); + push_int(0); + errno=ret; /* magic */ + } + if(desc) LocalFree(desc); +} + +#define ADD_GLOBAL_INTEGER_CONSTANT(X,Y) \ + push_int((long)(Y)); low_add_constant(X,sp-1); pop_stack(); +#define SIMPCONST(X) \ + add_integer_constant(#X,X,0); + void init_nt_system_calls(void) { /* function(string,string:int) */ + + ADD_FUNCTION("GetFileAttributes",f_GetFileAttributes,tFunc(tStr,tInt),0); + ADD_FUNCTION("SetFileAttributes",f_SetFileAttributes,tFunc(tStr tInt,tInt),0); + + SIMPCONST(FILE_ATTRIBUTE_ARCHIVE); + SIMPCONST(FILE_ATTRIBUTE_HIDDEN); + SIMPCONST(FILE_ATTRIBUTE_NORMAL); + SIMPCONST(FILE_ATTRIBUTE_OFFLINE); + SIMPCONST(FILE_ATTRIBUTE_READONLY); + SIMPCONST(FILE_ATTRIBUTE_SYSTEM); + SIMPCONST(FILE_ATTRIBUTE_TEMPORARY); + + SIMPCONST(FILE_ATTRIBUTE_COMPRESSED); + SIMPCONST(FILE_ATTRIBUTE_DIRECTORY); + SIMPCONST(FILE_ATTRIBUTE_ENCRYPTED); + SIMPCONST(FILE_ATTRIBUTE_REPARSE_POINT); + SIMPCONST(FILE_ATTRIBUTE_SPARSE_FILE); + ADD_FUNCTION("cp",f_cp,tFunc(tStr tStr,tInt), 0); -#define ADD_GLOBAL_INTEGER_CONSTANT(X,Y) \ - push_int((long)(Y)); low_add_constant(X,sp-1); pop_stack(); ADD_GLOBAL_INTEGER_CONSTANT("HKEY_LOCAL_MACHINE",HKEY_LOCAL_MACHINE); ADD_GLOBAL_INTEGER_CONSTANT("HKEY_CURRENT_USER",HKEY_CURRENT_USER); @@ -1242,8 +1737,6 @@ void init_nt_system_calls(void) /* function(string,string,string,int|void,void|int:object) */ ADD_FUNCTION("LogonUser",f_LogonUser,tFunc(tStr tStr tStr tOr(tInt,tVoid) tOr(tVoid,tInt),tObj),0); -#define SIMPCONST(X) \ - add_integer_constant(#X,X,0); SIMPCONST(LOGON32_LOGON_BATCH); SIMPCONST(LOGON32_LOGON_INTERACTIVE); @@ -1260,10 +1753,59 @@ void init_nt_system_calls(void) token_program->flags |= PROGRAM_DESTRUCT_IMMEDIATE; } + if(proc=GetProcAddress(advapilib, "LookupAccountNameA")) + lookupaccountname=(lookupaccountnametype)proc; + + if(proc=GetProcAddress(advapilib, "LookupAccountSidA")) + lookupaccountsid=(lookupaccountsidtype)proc; + + if(proc=GetProcAddress(advapilib, "SetNamedSecurityInfoA")) + setnamedsecurityinfo=(setnamedsecurityinfotype)proc; + + if(proc=GetProcAddress(advapilib, "GetNamedSecurityInfoA")) + getnamedsecurityinfo=(getnamedsecurityinfotype)proc; + + if(proc=GetProcAddress(advapilib, "EqualSid")) + equalsid=(equalsidtype)proc; + + if(proc=GetProcAddress(advapilib, "InitializeAcl")) + initializeacl=(initializeacltype)proc; + + if(proc=GetProcAddress(advapilib, "AddAccessAllowedAce")) + addaccessallowedace=(addaccessallowedacetype)proc; + + if(proc=GetProcAddress(advapilib, "AddAccessDeniedAce")) + addaccessdeniedace=(addaccessdeniedacetype)proc; + + if(proc=GetProcAddress(advapilib, "AddAuditAccessAce")) + addauditaccessace=(addauditaccessacetype)proc; + if(proc=GetProcAddress(advapilib, "GetLengthSid")) - { getlengthsid=(getlengthsidtype)proc; + + if(lookupaccountname && + equalsid && + getlengthsid) + { + start_new_program(); + set_init_callback(init_sid); + set_init_callback(exit_sid); + ADD_STORAGE(PSID); + add_function("`==",f_sid_eq,"function(mixed:int)",0); + add_function("account",f_sid_account,"function(:array(string|int))",0); + add_program_constant("SID",sid_program=end_program(),0); + + add_function("LookupAccountName",f_LookupAccountName, + "function(string,string:array)",0); + + add_function("SetNamedSecurityInfo",f_SetNamedSecurityInfo, + "function(string,mapping(string:mixed):array)",0); + add_function("GetNamedSecurityInfo",f_GetNamedSecurityInfo, + "function(string,void|int:mapping)",0); + + /* FIXME: add ACE constants */ } + } /* NetUserGetInfo only exists on NT, link it dynamically */ @@ -1393,6 +1935,14 @@ void exit_nt_system_calls(void) advapilib=0; logonuser=0; getlengthsid=0; + initializeacl=0; + addaccessallowedace=0; + addaccessdeniedace=0; + addauditaccessace=0; + getnamedsecurityinfo=0; + setnamedsecurityinfo=0; + lookupaccountname=0; + equalsid=0; } } if(netapilib) -- GitLab