ปัญหาด้านความปลอดภัยด้วย CreateProcess API

วัตถุประสงค์ : ฉันกำลังพยายามส่งไฟล์บางไฟล์จากไคลเอนต์ของฉันไปยังเซิร์ฟเวอร์ ฉันใช้ "rsync" เพื่อถ่ายโอนข้อมูล ฉันใช้ CreateProcess API และส่งเส้นทาง rsync พร้อมกับพารามิเตอร์

กรณีที่เป็นบวก: เมื่อฉันส่งข้อมูลจากไดรฟ์ในเครื่อง เช่น "C:" คือตำแหน่งที่ติดตั้ง Windows ของฉัน วิธีการข้างต้นจะทำงานได้อย่างถูกต้องและถ่ายโอนข้อมูล

ปัญหา : เมื่อฉันพยายามส่งข้อมูลของไดรฟ์ที่แมป (ไดรฟ์เครือข่ายที่ใช้ร่วมกัน) CreateProcess เสร็จสมบูรณ์ แต่ข้อผิดพลาดที่ฉันได้รับคือ rsync ไม่พบไฟล์ คำสั่ง rsync เดียวกัน เมื่อฉันรันบนพรอมต์คำสั่ง ไฟล์ทั้งหมดจะถูกถ่ายโอนได้สำเร็จโดยไม่มีข้อผิดพลาดใด ๆ แต่ล้มเหลวในการถ่ายโอนไฟล์ด้วย CreateProcess

รหัส :

    int CreateRsyncProcess(const wchar_t * ptrCommand)
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;
        SECURITY_ATTRIBUTES sap,sat,sao;
        HANDLE out;
        DWORD pwExit;

        //init the STARTUPINFO struct
        memset(&si,0,sizeof(si));
        si.cb=sizeof(si);

        wstring cmd = L"";
        cmd.append(ptrCommand);


        //proc sec attributes
        sap.nLength=sizeof(SECURITY_ATTRIBUTES);
        sap.lpSecurityDescriptor= NULL;
        sap.bInheritHandle=1;

        //thread sec attributes
        sat.nLength=sizeof(SECURITY_ATTRIBUTES);
        sat.lpSecurityDescriptor= NULL;
        sat.bInheritHandle=1;


        //create the proc
        if(!CreateProcess(NULL,(LPWSTR)cmd.c_str(),&sap,&sat,1,CREATE_NO_WINDOW,NULL,NULL,&si,&pi))
        {
            DWORD err = GetLastError();
            if(out != INVALID_HANDLE_VALUE)
                CloseHandle(out);

            return 1;
        }

        //wait till the proc ends

        WaitForSingleObject(pi.hProcess,INFINITE);

        GetExitCodeProcess(pi.hProcess,&pwExit);

        //close all
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
        if(out != INVALID_HANDLE_VALUE)
            CloseHandle(out);
        TerminateProcess(pi.hProcess,0);


        return pwExit;

}

Rsync Cmd : "C:\Program Files\cwRsync\bin\rsync.exe" -cvriHPDkREL --no-implied-dirs --stats -e '"C:\Program Files\cwRsync\bin \ssh" -o StrictHostKeyChecking=no -i "C:\Program Files\cwRsync\bin\rsync-key"' "/cygdrive/Z/64Bit" [email protected]:~/6a90c592-2b3b-4088-8942- 2106776c863a/

มันเกิดขึ้นเนื่องจากปัญหาด้านความปลอดภัยหรือปัญหาด้านสิทธิ์กับ CreateProcess หรืออย่างอื่นหรือไม่ โปรดช่วยในขณะที่ฉันติดอยู่กับเรื่องนี้

ขอบคุณ

แก้ไข: : สิ่งนี้ทำงานได้ดีตามกระบวนการปกติ แต่เมื่อฉันเรียกใช้ในบริการ มันจะล้มเหลว โดยพื้นฐานแล้วปัญหาในขณะนี้คือบริการไม่สามารถเข้าถึงการแชร์เครือข่าย มีวิธีแก้ไขปัญหาใดบ้าง?


person singh    schedule 13.02.2014    source แหล่งที่มา
comment
คุณกำลังเรียกใช้กระบวนการเป็นบริการหรือไม่?   -  person João Augusto    schedule 13.02.2014
comment
ไม่ใช่เป็นกระบวนการปกติ   -  person singh    schedule 13.02.2014
comment
ลองโดยไม่ต้อง CREATE_NO_WINDOW อาจเป็นเพียงการพยายามเขียนถึง STDERR หรืออะไรบางอย่าง   -  person Ben    schedule 13.02.2014
comment
ลองตั้งค่าบัญชีของบริการเป็นบริการเครือข่าย หน้านี้อาจช่วยได้   -  person wacky6    schedule 13.02.2014
comment
บริการทำงานภายใต้บัญชีผู้ดูแลระบบ หากฉันเรียกใช้เป็นบริการเครือข่าย บางอย่างจะไม่ทำงาน   -  person singh    schedule 13.02.2014
comment
แล้วมันทำงานเป็นบริการหรือเปล่า?   -  person João Augusto    schedule 13.02.2014
comment
ใช่..มันทำงานเป็นบริการภายใต้บัญชีผู้ใช้   -  person singh    schedule 20.02.2014


คำตอบ (3)


เนื่องจากเห็นได้ชัดว่าคุณกำลังใช้บริการ คุณอาจต้องโหลดสภาพแวดล้อมเพื่อให้สามารถเข้าถึงโฟลเดอร์ที่แมปได้

บางอย่างเช่นนี้

    DWORD dwIdCurrentSession = 0xFFFFFFFF;

    WTS_SESSION_INFO* pSessionInfo = NULL;          
    DWORD dwSessionsCount = 0;
    if(WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwSessionsCount))
    {   
        for(int i=0; i<(int)dwSessionsCount; i++)
        {
            WTS_SESSION_INFO &si = pSessionInfo[i];
            if(si.State == WTSActive)
            {                                                       
                dwIdCurrentSession = si.SessionId;
                break;
            }
        }

        WTSFreeMemory(pSessionInfo);    
    }

    if(dwIdCurrentSession != 0xFFFFFFFF)
    {
        HANDLE hLoggedOnUserToken = NULL;           
        // Get Session User Token   
        if(WTSQueryUserToken(dwIdCurrentSession, &hLoggedOnUserToken))                          
        {                   
            LPVOID lpEnviroment = NULL;
            if(CreateEnvironmentBlock(&lpEnviroment, hLoggedOnUserToken, false))
            {               
                STARTUPINFO si;
                PROCESS_INFORMATION pi;

                ZeroMemory( &si, sizeof(si) );
                si.cb = sizeof(si);
                ZeroMemory( &pi, sizeof(pi) );

                // Create Process
                if(CreateProcessAsUser(hLoggedOnUserToken,
                    NULL,
                    (LPWSTR)cmd.c_str(),
                    NULL,
                    NULL,
                    FALSE,
                    CREATE_UNICODE_ENVIRONMENT,
                    lpEnviroment,
                    NULL,
                    &si,
                    &pi )
                ) 
                {   
                    // Wait for finish......

                    // Clean up
                    CloseHandle( pi.hProcess );
                    CloseHandle( pi.hThread );                                  
                }

                DestroyEnvironmentBlock(lpEnviroment);
            }

            CloseHandle(hLoggedOnUserToken);    
        }
    }
person João Augusto    schedule 13.02.2014
comment
ฉันจะพยายามแจ้งให้คุณทราบ - person singh; 14.02.2014
comment
รหัสนี้ใช้งานได้เมื่อฉันเรียกใช้บริการภายใต้บัญชีระบบ แต่ล้มเหลวเมื่อฉันเรียกใช้บริการภายใต้บัญชีผู้ใช้ - person singh; 20.02.2014
comment
WTSQueryUserToken ใช้งานได้กับบัญชี LocalSystem เท่านั้น - person João Augusto; 20.02.2014
comment
ข้อมูลที่เป็นประโยชน์สำหรับปัญหาของคุณ msdn .microsoft.com/en-us/library/windows/desktop/ - person João Augusto; 20.02.2014

ไดรฟ์ที่แมปเป็นต่อเซสชัน - บริการในเซสชันที่แยกไม่สามารถเข้าถึงไดรฟ์ที่แมปในเซสชันผู้ใช้ คุณจะต้องแมปไดรฟ์ในเซสชันบริการ หรือใช้เส้นทาง UNC (แทนอักษรระบุไดรฟ์ที่แมป) และให้สิทธิ์ผู้ใช้บริการในการเข้าถึงการแชร์

person nobody    schedule 13.02.2014

คุณใช้ระบบปฏิบัติการใด เช่น Windows 7 32 บิต, Windows 7 64 บิต ฯลฯ นอกจากนี้คุณเปิดใช้งาน UAC หรือไม่ หากคุณเปิดใช้งาน UAC ปัญหาจะหายไปเมื่อคุณเรียกใช้แอปพลิเคชันในฐานะผู้ดูแลระบบ

เราอาจจะให้ความช่วยเหลือเพิ่มเติมได้ ทั้งนี้ขึ้นอยู่กับคำตอบของคุณสำหรับคำถามเหล่านี้ ฉันคงต้องทำวิจัยบ้างแล้ว

ในขณะนี้ หาก UAC เป็นปัญหาของคุณจริงๆ คำแนะนำเดียวของฉันคือให้คุณตรวจสอบความเป็นไปได้ในการใช้ ShellExecuteEx แทน พบฟังก์ชัน RunElevated ได้ที่ การขี่ Vista UAC ลิฟต์ขึ้นและลงอาจเป็นประโยชน์กับคุณ เพื่อความสะดวกฉันจะรวมฟังก์ชันไว้ที่นี่

BOOL RunElevated(
  HWND hwnd, LPCTSTR pszPath,
  LPCTSTR pszParameters = NULL, LPCTSTR pszDirectory = NULL)
{
  SHELLEXECUTEINFO shex;
  memset( &shex, 0, sizeof( shex) );

  shex.cbSize = sizeof(SHELLEXECUTEINFO);
  shex.fMask = 0;
  shex.hwnd = hwnd;
  shex.lpVerb = _T("runas");
  shex.lpFile = pszPath;
  shex.lpParameters = pszParameters;
  shex.lpDirectory = pszDirectory;
  shex.nShow = SW_NORMAL;
  return ::ShellExecuteEx(&shex);
}

หากใช้ ShellExecuteEx ไม่ใช่ตัวเลือก คุณสามารถลองใช้ฟังก์ชัน CreateProcessElevated ได้ที่ Vista UAC: คู่มือฉบับสมบูรณ์

person Ben Key    schedule 13.02.2014