windows - c++: Let user process write to LOCAL_SYSTEM named pipe - Custom Security Descriptor -


i have service running localsystem creates processes in logged on users' session. service creates named pipe client connects read , write. according https://msdn.microsoft.com/en-us/library/aa365600%28v=vs.85%29.aspx client can read pipe (it's no admin, not creator, neither localsystem ).

i created security descriptor grant user read & write access. didn't work. tried giving read & write-access everyone-group. not work. error code client returns access_denied (5).

i glad know doing wrong.

edit: if don't create custom security descriptor , open pipe generic_read works (but reading).

edit2 want learn how right. , still want logged on user able write. not (this testing).

service-code (commented-out code getting user sid):

psid everyonesid                      = nullptr;         sid_identifier_authority sidauthworld = security_world_sid_authority;         if(!allocateandinitializesid(&sidauthworld, 1,                                  security_world_rid,                                  0, 0, 0, 0, 0, 0, 0,                                  &everyonesid))         {             throw(std::runtime_error("failed initialize group sid: " + std::to_string(getlasterror())));         }          //token_user* tokeninfo     = nullptr;         //dword tokeninfolen        = 0;         //dword outlen              = 0;         //// query token info size         //if(!gettokeninformation(usertoken,         //                  tokenuser,         //                  tokeninfo,         //                  tokeninfolen,         //                  &outlen))         //{         //  throw(std::runtime_error("failed obtain user token size: " + std::to_string(getlasterror())));         //}         //// allocate enough space hold token user information         //tokeninfo    = (token_user*) localalloc(lptr, outlen);         //tokeninfolen = outlen;          //// sid user token         //if(!gettokeninformation(usertoken,         //                  tokenuser,         //                  tokeninfo,         //                  tokeninfolen,         //                  &outlen))         //{         //  throw(std::runtime_error("failed obtain user token info: " + std::to_string(getlasterror())));         //}          //auto usersid = tokeninfo->user.sid;         //localfree(tokeninfo);          security_attributes sa = {0};         zeromemory(&sa, sizeof(security_attributes));         sa.nlength = sizeof(security_attributes);         sa.binherithandle = false;          // set ace         explicit_access ace      = {0};         ace.grfaccessmode        = set_access;         ace.grfaccesspermissions = pipe_access_duplex;  // generic_read | generic_write | synchronize         ace.grfinheritance       = no_inheritance;         ace.trustee.trusteeform  = trustee_is_sid;         ace.trustee.trusteetype  = trustee_is_well_known_group;         ace.trustee.ptstrname    = (lptstr) everyonesid;          pacl acl = nullptr;         if(error_success != setentriesinacl(1, &ace, nullptr, &acl))             throw(std::runtime_error("failed set acl entries: " + std::to_string(getlasterror())));          // create security descriptor.         auto sd = (psecurity_descriptor) localalloc(lptr, security_descriptor_min_length);         if(!initializesecuritydescriptor(sd, security_descriptor_revision))             throw(std::runtime_error("failed initialize security descriptor: " + std::to_string(getlasterror())));         if(!setsecuritydescriptordacl(sd, true, acl, false))             throw(std::runtime_error("failed set dacl: " + std::to_string(getlasterror())));          // set security descriptor in security attributes         sa.lpsecuritydescriptor = sd;          // create named pipe user-session application         // connects.         auto pipe = createnamedpipe(local_pipe_name,                          pipe_access_duplex,                          pipe_type_byte | pipe_readmode_byte | pipe_reject_remote_clients | pipe_wait,                          1,                          256,                          256,                          null,                          &sa);         if(pipe == invalid_handle_value)             throw std::runtime_error("failed create named pipe");          localfree(acl);         localfree(sd); 

user-process-code:

auto pipe = createfile(local_pipe_name,                            generic_read | generic_write,    // read access                              0,              // no sharing                              null,           // default security attributes                             open_existing,  // opens existing pipe                              0,              // default attributes                              null);          // no template file      if (pipe == invalid_handle_value)         throw(std::runtime_error("failed open local pipe: " + std::to_string(getlasterror()))); 

this first problem:

    ace.grfaccesspermissions = pipe_access_duplex; 

the pipe_access_duplex constant meant used argument createnamedpipe(), not valid access permission. (by coincidence, equal file_read_data|file_write_data access rights not allow connect pipe.)

according named pipe security , access rights, following access rights assigned server end of duplex pipe, implying sufficient open client end:

    ace.grfaccesspermissions = file_generic_read | file_generic_write | synchronize; 

however, file_generic_write broad grant client; in particular, allows client create new instance of server end of pipe. unlikely desirable. instead, duplex pipe, should use

    ace.grfaccesspermissions = file_generic_read | file_write_data; 

of course, access request when opening client end must consistent:

auto pipe = createfile(local_pipe_name,                        generic_read | file_write_data,    // read-write access                         0,              // no sharing                         null,           // default security attributes                        open_existing,  // opens existing pipe                         0,              // default attributes                         null);          // no template file  

details

experimentally, on windows 7 sp1 x64, in order connect pipe (even if request no access in call createfile) must have read_attributes , synchronize rights. note file_generic_read constant incorporates both of these.

to read data pipe must have (and request) file_read_data. (this incorporated in file_generic_read.)

to write data pipe must have (and request) file_write_data.


Comments

Popular posts from this blog

php - failed to open stream: HTTP request failed! HTTP/1.0 400 Bad Request -

java - How to filter a backspace keyboard input -

java - Show Soft Keyboard when EditText Appears -