Winapi 在调用ImpersonalLoggedOnUser()之后,是否应该创建重定向IO句柄和lpEnvironment?
我现在查看wininetd的源代码:,第408行。在调用ImpersonalLoggeDonUser()之后填充CreateProcessAsUserA()参数:lpEnvironment、si.hStdInput等,从而创建不必要的代码重复,这似乎很奇怪 它有什么特别的意义吗?例如,影响句柄继承还是破坏安全性Winapi 在调用ImpersonalLoggedOnUser()之后,是否应该创建重定向IO句柄和lpEnvironment?,winapi,service,Winapi,Service,我现在查看wininetd的源代码:,第408行。在调用ImpersonalLoggeDonUser()之后填充CreateProcessAsUserA()参数:lpEnvironment、si.hStdInput等,从而创建不必要的代码重复,这似乎很奇怪 它有什么特别的意义吗?例如,影响句柄继承还是破坏安全性 if (!ImpersonateLoggedOnUser(husr)) { winet_log(WINET_LOG_ERROR, "[%s] unable to imperson
if (!ImpersonateLoggedOnUser(husr)) {
winet_log(WINET_LOG_ERROR, "[%s] unable to impersonate user: user='%s' err='%s'\n",
WINET_APPNAME, pm->user, emsg = winet_get_syserror());
free(emsg);
CloseHandle(husr);
return -1;
}
if (winet_create_stdhandles(asock, &si.hStdInput, &si.hStdOutput, &si.hStdError) < 0) {
RevertToSelf();
CloseHandle(husr);
return -1;
}
if (!(env = winet_prepare_env(pm, asock, saddr))) {
RevertToSelf();
CloseHandle(husr);
CloseHandle(si.hStdError);
CloseHandle(si.hStdOutput);
CloseHandle(si.hStdInput);
return -1;
}
if (!CreateProcessAsUserA(husr, NULL, pm->cmdline, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
env, NULL, &si, &pi)) {
winet_log(WINET_LOG_ERROR, "[%s] unable to create process as user: cmdln='%s' user='%s' err='%s'\n",
WINET_APPNAME, pm->cmdline, pm->user, emsg = winet_get_syserror());
free(emsg);
FreeEnvironmentStrings(env);
RevertToSelf();
CloseHandle(husr);
CloseHandle(si.hStdError);
CloseHandle(si.hStdOutput);
CloseHandle(si.hStdInput);
return -1;
}
RevertToSelf();
CloseHandle(husr);
if(!ImpersonalLoggeDonUser(husr)){
winet_日志(winet_日志错误,“[%s]无法模拟用户:用户='%s'错误='%s'\n”,
WINET_APPNAME,pm->user,emsg=WINET_get_syserror();
免费(emsg);
闭合手柄(husr);
返回-1;
}
if(winet\u create\u stdhandles(asock,&si.hStdInput,&si.hStdOutput,&si.hStdError)<0){
restortoself();
闭合手柄(husr);
返回-1;
}
如果(!(环境=葡萄酒准备环境(pm、asock、SADD))){
restortoself();
闭合手柄(husr);
闭合手柄(si.hStdError);
闭合手柄(si.HST输出);
闭合手柄(si.HST输入);
返回-1;
}
如果(!CreateProcessAsUserA(husr,NULL,pm->cmdline,NULL,NULL,TRUE,CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,
env、NULL、si和pi){
winet_日志(winet_日志错误,“[%s]无法以用户身份创建进程:cmdln='%s'用户='%s'错误='%s'\n”,
WINET_APPNAME,pm->cmdline,pm->user,emsg=WINET_get_syserror());
免费(emsg);
FreeEnvironmentStrings(env);
restortoself();
闭合手柄(husr);
闭合手柄(si.hStdError);
闭合手柄(si.HST输出);
闭合手柄(si.HST输入);
返回-1;
}
restortoself();
闭合手柄(husr);
管道和环境块的创建对调用线程的当前用户很敏感,因此需要首先模拟。此外,代码正在调用CreateProcess()
vsCreateProcessAsUser()
,这取决于是否正在使用模拟。因此,代码的某些部分被复制是有意义的。另一方面,代码的编写方式当然可以减少代码的重复,而不会改变原始代码的总体含义,例如:
static int winet_serve_client(portmap_t *pm, SOCKET asock, struct sockaddr_in *saddr) {
HANDLE husr = NULL;
char *emsg;
LPVOID env;
STARTUPINFOA si;
PROCESS_INFORMATION pi;
BOOL impersonating = FALSE;
BOOL created;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.lpDesktop = "";
si.dwFlags = STARTF_USESTDHANDLES;
if (winet_user_handle(pm, &husr) >= 0) {
if (!ImpersonateLoggedOnUser(husr)) {
winet_log(WINET_LOG_ERROR, "[%s] unable to impersonate user: user='%s' err='%s'\n", WINET_APPNAME, pm->user, emsg = winet_get_syserror());
free(emsg);
CloseHandle(husr);
return -1;
}
impersonating = TRUE;
}
if (winet_create_stdhandles(asock, &si.hStdInput, &si.hStdOutput, &si.hStdError) < 0) {
if (impersonating) RevertToSelf();
if (husr) CloseHandle(husr);
return -1;
}
if (!(env = winet_prepare_env(pm, asock, saddr))) {
if (impersonating) RevertToSelf();
if (husr) CloseHandle(husr);
CloseHandle(si.hStdError);
CloseHandle(si.hStdOutput);
CloseHandle(si.hStdInput);
return -1;
}
if (husr) {
created = CreateProcessAsUserA(husr, NULL, pm->cmdline, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, env, NULL, &si, &pi));
} else {
created = CreateProcessA(NULL, pm->cmdline, NULL, NULL, TRUE, CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, env, NULL, &si, &pi));
}
if (!created) {
emsg = winet_get_syserror();
if (husr) {
winet_log(WINET_LOG_ERROR, "[%s] unable to create process as user: cmdln='%s' user='%s' err='%s'\n", WINET_APPNAME, pm->cmdline, pm->user, emsg);
} else {
winet_log(WINET_LOG_ERROR, "[%s] unable to create process: cmdln='%s' err='%s'\n", WINET_APPNAME, pm->cmdline, emsg);
}
free(emsg);
FreeEnvironmentStrings(env);
if (impersonating) RevertToSelf();
if (husr) CloseHandle(husr);
CloseHandle(si.hStdError);
CloseHandle(si.hStdOutput);
CloseHandle(si.hStdInput);
return -1;
}
if (impersonating) RevertToSelf();
if (husr) CloseHandle(husr);
if (impersonating) {
winet_log(WINET_LOG_MESSAGE, "[%s] process created: user='%s' cmdln='%s'\n", WINET_APPNAME, pm->user, pm->cmdline);
} else {
winet_log(WINET_LOG_MESSAGE, "[%s] process created: cmdln='%s'\n", WINET_APPNAME, pm->cmdline);
}
WaitForSingleObject(pi.hProcess, INFINITE);
FreeEnvironmentStrings(env);
CloseHandle(si.hStdError);
CloseHandle(si.hStdOutput);
CloseHandle(si.hStdInput);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return 0;
}
static int-winet\u-service\u客户端(portmap\u-t*pm、SOCKET-asock、struct-sockaddr\u-in*saddr){
HANDLE husr=NULL;
char*emsg;
LPVOID-env;
新创资讯科技有限公司;
处理信息;
布尔模拟=假;
布尔创造;
memset(&si,0,sizeof(si));
si.cb=sizeof(si);
si.lpDesktop=“”;
si.dwFlags=STARTF_USESTDHANDLES;
如果(winet\u用户\u句柄(pm和husr)>=0){
if(!ImpersonalLoggedOnUser(husr)){
winet_日志(winet_日志错误,[%s]无法模拟用户:用户='%s'错误='%s'\n',winet_应用程序名,pm->user,emsg=winet_get_syserror());
免费(emsg);
闭合手柄(husr);
返回-1;
}
模仿=真实;
}
if(winet\u create\u stdhandles(asock,&si.hStdInput,&si.hStdOutput,&si.hStdError)<0){
if(模拟)retertoself();
if(husr)闭合手柄(husr);
返回-1;
}
如果(!(环境=葡萄酒准备环境(pm、asock、SADD))){
if(模拟)retertoself();
if(husr)闭合手柄(husr);
闭合手柄(si.hStdError);
闭合手柄(si.HST输出);
闭合手柄(si.HST输入);
返回-1;
}
如果(husr){
created=CreateProcessAsUserA(husr,NULL,pm->cmdline,NULL,NULL,TRUE,CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,env,NULL,&si,&pi));
}否则{
created=CreateProcessA(NULL,pm->cmdline,NULL,NULL,TRUE,CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS,env,NULL,&si,&pi));
}
如果(!已创建){
emsg=winet_get_syserror();
如果(husr){
winet_日志(winet_日志错误,[%s]无法以用户身份创建进程:cmdln='%s'用户='%s'错误='%s'\n],winet_应用程序名,pm->cmdline,pm->user,emsg);
}否则{
winet_日志(winet_日志错误,[%s]无法创建进程:cmdln='%s'err='%s'\n',winet_APPNAME,pm->cmdline,emsg);
}
免费(emsg);
FreeEnvironmentStrings(env);
if(模拟)retertoself();
if(husr)闭合手柄(husr);
闭合手柄(si.hStdError);
闭合手柄(si.HST输出);
闭合手柄(si.HST输入);
返回-1;
}
if(模拟)retertoself();
if(husr)闭合手柄(husr);
如果(模拟){
winet_日志(winet_日志消息,[%s]进程已创建:用户=“%s”cmdln=“%s”\n”,winet_应用程序名,pm->user,pm->cmdline);
}否则{
winet_日志(winet_日志消息,[%s]进程已创建:cmdln='%s'\n],winet_APPNAME,pm->cmdline);
}
WaitForSingleObject(pi.hProcess,无限);
FreeEnvironmentStrings(env);
闭合手柄(si.hStdError);
闭合手柄(si.HST输出);
闭合手柄(si.HST输入);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
返回0;
}
测试:管道和环境。继承罚款,即使在ImpersonalLoggedOnUser之前调用。由于wininetd不加载用户配置文件,因此继承了“本地系统”环境。对我来说似乎很安全。