diff --git a/src/modules/system/nt.c b/src/modules/system/nt.c index 20479f80eb7246fcae13cb6ff52f50ee95f68630..48811e5f14203fae2bd312b2bd814e19c1eb95fa 100644 --- a/src/modules/system/nt.c +++ b/src/modules/system/nt.c @@ -1,5 +1,5 @@ /* - * $Id: nt.c,v 1.14 1999/05/13 17:52:42 marcus Exp $ + * $Id: nt.c,v 1.15 1999/05/17 22:50:37 marcus Exp $ * * NT system calls for Pike * @@ -114,8 +114,10 @@ static struct program *token_program; #define THIS_TOKEN (*(HANDLE *)(fp->current_storage)) typedef BOOL WINAPI (*logonusertype)(LPSTR,LPSTR,LPSTR,DWORD,DWORD,PHANDLE); +typedef DWORD WINAPI (*getlengthsidtype)(PSID); static logonusertype logonuser; +static getlengthsidtype getlengthsid; HINSTANCE advapilib; void f_LogonUser(INT32 args) @@ -421,6 +423,56 @@ 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) + + SAFE_PUSH_SID(tmp->lgrmi0_sid); +} + +static void low_encode_localgroup_members_info_1(LOCALGROUP_MEMBERS_INFO_1 *tmp) +{ + low_encode_localgroup_members_info_0((LOCALGROUP_MEMBERS_INFO_0 *)tmp); + push_int(tmp->lgrmi1_sidusage); + SAFE_PUSH_WSTR(tmp->lgrmi1_name); + /* 3 entries */ +} + +static void low_encode_localgroup_members_info_2(LOCALGROUP_MEMBERS_INFO_2 *tmp) +{ + low_encode_localgroup_members_info_0((LOCALGROUP_MEMBERS_INFO_0 *)tmp); + push_int(tmp->lgrmi2_sidusage); + SAFE_PUSH_WSTR(tmp->lgrmi2_domainandname); + /* 3 entries */ +} + +static void low_encode_localgroup_members_info_3(LOCALGROUP_MEMBERS_INFO_3 *tmp) +{ + SAFE_PUSH_WSTR(tmp->lgrmi3_domainandname); +} + +static void encode_localgroup_members_info(BYTE *u, int level) +{ + if(!u) + { + push_int(0); + return; + } + switch(level) + { + case 0: low_encode_localgroup_members_info_0 ((LOCALGROUP_MEMBERS_INFO_0 *) u);break; + case 1: low_encode_localgroup_members_info_1 ((LOCALGROUP_MEMBERS_INFO_1 *) u);f_aggregate(3);break; + case 2: low_encode_localgroup_members_info_2 ((LOCALGROUP_MEMBERS_INFO_2 *) u);f_aggregate(3);break; + case 3: low_encode_localgroup_members_info_3 ((LOCALGROUP_MEMBERS_INFO_3 *) u);break; + default: + error("Unsupported LOCALGROUPMEMBERSINFO level.\n"); + } +} + static int sizeof_user_info(int level) { switch(level) @@ -476,11 +528,24 @@ static int sizeof_localgroup_users_info(int level) } } +static int sizeof_localgroup_members_info(int level) +{ + switch(level) + { + case 0: return sizeof(LOCALGROUP_MEMBERS_INFO_0); + case 1: return sizeof(LOCALGROUP_MEMBERS_INFO_1); + case 2: return sizeof(LOCALGROUP_MEMBERS_INFO_2); + case 3: return sizeof(LOCALGROUP_MEMBERS_INFO_3); + default: return -1; + } +} + typedef NET_API_STATUS WINAPI (*netusergetinfotype)(LPWSTR,LPWSTR,DWORD,LPBYTE *); typedef NET_API_STATUS WINAPI (*netuserenumtype)(LPWSTR,DWORD,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD); typedef NET_API_STATUS WINAPI (*netusergetgroupstype)(LPWSTR,LPWSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD); typedef NET_API_STATUS WINAPI (*netusergetlocalgroupstype)(LPWSTR,LPWSTR,DWORD,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD); typedef NET_API_STATUS WINAPI (*netgroupenumtype)(LPWSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD); +typedef NET_API_STATUS WINAPI (*netgroupgetuserstype)(LPWSTR,LPWSTR,DWORD,LPBYTE*,DWORD,LPDWORD,LPDWORD,LPDWORD); typedef NET_API_STATUS WINAPI (*netapibufferfreetype)(LPVOID); static netusergetinfotype netusergetinfo; @@ -488,13 +553,14 @@ static netuserenumtype netuserenum; static netusergetgroupstype netusergetgroups; static netusergetlocalgroupstype netusergetlocalgroups; static netgroupenumtype netgroupenum, netlocalgroupenum; +static netgroupgetuserstype netgroupgetusers, netlocalgroupgetmembers; static netapibufferfreetype netapibufferfree; HINSTANCE netapilib; void f_NetUserGetInfo(INT32 args) { - char *to_free1,*to_free2; + char *to_free1=NULL,*to_free2=NULL; BYTE *tmp=0; DWORD level; LPWSTR server, user; @@ -565,7 +631,7 @@ void f_NetUserGetInfo(INT32 args) void f_NetUserEnum(INT32 args) { - char *to_free1; + char *to_free1=NULL; DWORD level=0; DWORD filter=0; LPWSTR server=NULL; @@ -653,7 +719,7 @@ void f_NetUserEnum(INT32 args) void f_NetGroupEnum(INT32 args) { - char *to_free1, *tmp_server=NULL; + char *to_free1=NULL, *tmp_server=NULL; DWORD level=0; LPWSTR server=NULL; INT32 pos=0,e; @@ -730,7 +796,7 @@ void f_NetGroupEnum(INT32 args) void f_NetLocalGroupEnum(INT32 args) { - char *to_free1, *tmp_server=NULL; + char *to_free1=NULL, *tmp_server=NULL; DWORD level=0; LPWSTR server=NULL; INT32 pos=0,e; @@ -807,7 +873,7 @@ void f_NetLocalGroupEnum(INT32 args) void f_NetUserGetGroups(INT32 args) { - char *to_free1, *to_free2, *tmp_server=NULL, *tmp_user; + char *to_free1=NULL, *to_free2=NULL, *tmp_server=NULL, *tmp_user; DWORD level=0; LPWSTR server=NULL; LPWSTR user=NULL; @@ -884,7 +950,7 @@ void f_NetUserGetGroups(INT32 args) void f_NetUserGetLocalGroups(INT32 args) { - char *to_free1, *to_free2, *tmp_server=NULL, *tmp_user; + char *to_free1=NULL, *to_free2=NULL, *tmp_server=NULL, *tmp_user; DWORD level=0; DWORD flags=0; LPWSTR server=NULL; @@ -964,6 +1030,193 @@ void f_NetUserGetLocalGroups(INT32 args) if(to_free2) free(to_free2); } +void f_NetGroupGetUsers(INT32 args) +{ + char *to_free1=NULL, *to_free2=NULL, *tmp_server=NULL; + DWORD level=0; + LPWSTR server=NULL; + LPWSTR group=NULL; + INT32 pos=0,e; + struct array *a=0; + DWORD resume=0; + + check_all_args("NetGroupGetUsers",args,BIT_STRING|BIT_INT|BIT_VOID, BIT_STRING, BIT_INT|BIT_VOID,0); + + if(args && sp[-args].type==T_STRING) + server=(LPWSTR)require_wstring1(sp[-args].u.string,&to_free1); + + if(args>1 && sp[1-args].type==T_STRING) + group=(LPWSTR)require_wstring1(sp[1-args].u.string,&to_free2); + + if(args>2 && sp[2-args].type==T_INT) { + level = sp[2-args].u.integer; + switch(level) + { + case 0: case 1: + break; + default: + error("Unsupported information level in NetGroupGetUsers.\n"); + } + } + + pop_n_elems(args); + + while(1) + { + DWORD read=0, total=0; + NET_API_STATUS ret; + LPBYTE buf=0,ptr; + + THREADS_ALLOW(); + ret=netgroupgetusers(server, + group, + level, + &buf, + 0x10000, + &read, + &total, + &resume); + THREADS_DISALLOW(); + if(!a) + push_array(a=allocate_array(total)); + + switch(ret) + { + case ERROR_ACCESS_DENIED: + if(to_free1) free(to_free1); + if(to_free2) free(to_free2); + error("NetGroupGetUsers: Access denied.\n"); + break; + + case NERR_InvalidComputer: + if(to_free1) free(to_free1); + if(to_free2) free(to_free2); + error("NetGroupGetUsers: Invalid computer.\n"); + break; + + case NERR_GroupNotFound: + if(to_free1) free(to_free1); + if(to_free2) free(to_free2); + error("NetGroupGetUsers: Group not found.\n"); + break; + + case NERR_Success: + case ERROR_MORE_DATA: + ptr=buf; + for(e=0;e<read;e++) + { + encode_group_users_info(ptr,level); + a->item[pos]=sp[-1]; + sp--; + pos++; + if(pos>=a->size) break; + ptr+=sizeof_group_users_info(level); + } + netapibufferfree(buf); + if(ret==ERROR_MORE_DATA) continue; + } + break; + } + if(to_free1) free(to_free1); + if(to_free2) free(to_free2); +} + +void f_NetLocalGroupGetMembers(INT32 args) +{ + char *to_free1=NULL, *to_free2=NULL, *tmp_server=NULL; + DWORD level=0; + LPWSTR server=NULL; + LPWSTR group=NULL; + INT32 pos=0,e; + struct array *a=0; + DWORD resume=0; + + check_all_args("NetLocalGroupGetMembers",args,BIT_STRING|BIT_INT|BIT_VOID, BIT_STRING, BIT_INT|BIT_VOID,0); + + if(args && sp[-args].type==T_STRING) + server=(LPWSTR)require_wstring1(sp[-args].u.string,&to_free1); + + if(args>1 && sp[1-args].type==T_STRING) + group=(LPWSTR)require_wstring1(sp[1-args].u.string,&to_free2); + + if(args>2 && sp[2-args].type==T_INT) { + level = sp[2-args].u.integer; + switch(level) + { + case 0: case 1: case 2: case 3: + break; + default: + error("Unsupported information level in NetLocalGroupGetMembers.\n"); + } + } + + pop_n_elems(args); + + while(1) + { + DWORD read=0, total=0; + NET_API_STATUS ret; + LPBYTE buf=0,ptr; + + THREADS_ALLOW(); + ret=netlocalgroupgetmembers(server, + group, + level, + &buf, + 0x10000, + &read, + &total, + &resume); + THREADS_DISALLOW(); + if(!a) + push_array(a=allocate_array(total)); + + switch(ret) + { + case ERROR_ACCESS_DENIED: + if(to_free1) free(to_free1); + if(to_free2) free(to_free2); + error("NetLocalGroupGetMembers: Access denied.\n"); + break; + + case NERR_InvalidComputer: + if(to_free1) free(to_free1); + if(to_free2) free(to_free2); + error("NetLocalGroupGetMembers: Invalid computer.\n"); + break; + + case NERR_GroupNotFound: + if(to_free1) free(to_free1); + if(to_free2) free(to_free2); + error("NetLocalGroupGetMembers: Group not found.\n"); + break; + + case ERROR_NO_SUCH_ALIAS: + if(to_free1) free(to_free1); + if(to_free2) free(to_free2); + error("NetLocalGroupGetMembers: No such alias.\n"); + break; + + case NERR_Success: + case ERROR_MORE_DATA: + ptr=buf; + for(e=0;e<read;e++) + { + encode_localgroup_members_info(ptr,level); + a->item[pos]=sp[-1]; + sp--; + pos++; + if(pos>=a->size) break; + ptr+=sizeof_localgroup_members_info(level); + } + netapibufferfree(buf); + if(ret==ERROR_MORE_DATA) continue; + } + break; + } + if(to_free1) free(to_free1); + if(to_free2) free(to_free2); +} void init_nt_system_calls(void) { @@ -1004,6 +1257,11 @@ void init_nt_system_calls(void) add_program_constant("UserToken",token_program,0); token_program->flags |= PROGRAM_DESTRUCT_IMMEDIATE; } + + if(proc=GetProcAddress(advapilib, "GetLengthSid")) + { + getlengthsid=(getlengthsidtype)proc; + } } /* NetUserGetInfo only exists on NT, link it dynamically */ @@ -1090,6 +1348,29 @@ void init_nt_system_calls(void) SIMPCONST(LG_INCLUDE_INDIRECT); } + + if(proc=GetProcAddress(netapilib, "NetGroupGetUsers")) + { + netgroupgetusers=(netgroupgetuserstype)proc; + + add_function("NetGroupGetUsers",f_NetGroupGetUsers,"function(string|int,string,int|void:array(string|array(int|string)))",0); + } + + if(proc=GetProcAddress(netapilib, "NetLocalGroupGetMembers")) + { + netlocalgroupgetmembers=(netgroupgetuserstype)proc; + + add_function("NetLocalGroupGetMembers",f_NetLocalGroupGetMembers,"function(string|int,string,int|void:array(string|array(int|string)))",0); + + SIMPCONST(SidTypeUser); + SIMPCONST(SidTypeGroup); + SIMPCONST(SidTypeDomain); + SIMPCONST(SidTypeAlias); + SIMPCONST(SidTypeWellKnownGroup); + SIMPCONST(SidTypeDeletedAccount); + SIMPCONST(SidTypeInvalid); + SIMPCONST(SidTypeUnknown); + } } } } @@ -1107,6 +1388,7 @@ void exit_nt_system_calls(void) { advapilib=0; logonuser=0; + getlengthsid=0; } } if(netapilib) @@ -1121,6 +1403,8 @@ void exit_nt_system_calls(void) netgroupenum=0; netlocalgroupenum=0; netapibufferfree=0; + netgroupgetusers=0; + netlocalgroupgetmembers=0; } } }