0

我现在正在查看 wininetd 的来源:http://4coder.org/cc-source-code/27/wininetd-0.7/wininetd.c.html 第 408 行。 CreateProcessAsUserA() 参数似乎很奇怪:lpEnvironment , si.hStdInput 等在调用 ImpersonateLoggedOnUser() 之后被填充,从而创建了不需要的代码重复。

它有什么特殊含义吗?例如,影响句柄继承或破坏安全性?

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);
4

1 回答 1

0

管道和环境块的创建对调用线程的当前用户很敏感,因此需要先模拟。此外,代码调用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;
}
于 2013-08-11T07:48:01.760 回答