How to create a named channel in Windows so that you can read from it and write data to it without any logins and passwords from computers in the local network? Security flaws when using such a channel do not bother me, as this is a training program. I would like to do without complex settings in the OS. It is necessary that it works at least in Windows XP and 7.
Here is an example that works on one computer, but not on several. Server code:
#include <windows.h> #include <iostream> char msg1[]="Message1"; char msg2[]="Message2"; int main(){ std::string c; SECURITY_ATTRIBUTES sa={0}; SECURITY_DESCRIPTOR sd={0}; InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl( &sd, TRUE, NULL, FALSE); sa.bInheritHandle=false; sa.lpSecurityDescriptor=&sd; sa.nLength=sizeof(sa); HANDLE ch1=CreateNamedPipe ( "\\\\.\\pipe\\testpipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE| PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, sizeof msg1, 4, 0, &sa ); if(ch1==INVALID_HANDLE_VALUE){ std::cout<<"ch1 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } HANDLE ch2=CreateNamedPipe( "\\\\.\\pipe\\testpipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE| PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, sizeof msg1, 4, 0, &sa ); if(ch2==INVALID_HANDLE_VALUE){ std::cout<<"ch2 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } ConnectNamedPipe(ch1, 0); ConnectNamedPipe(ch2, 0); unsigned long foo; if(TransactNamedPipe(ch1, msg1, sizeof msg1, &foo, sizeof foo, &foo, 0)==0){ std::cout<<"transact1 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } if(TransactNamedPipe(ch2, msg2, sizeof msg2, &foo, sizeof foo, &foo, 0)==0){ std::cout<<"transact2 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } std::cout<<"Finished\n"; std::getline(std::cin, c); return 0; } Client code:
#include <windows.h> #include <iostream> char msg1[]="Message1\n"; char msg2[]="Message2\n"; int main(){ std::string c; std::cout<<"Server name:\n"; std::string sname; std::cin>>sname; std::cin.ignore(); NETRESOURCE nr={0}; if(sname!="."){ std::string sname2=std::string("\\\\")+sname; nr.dwType = RESOURCETYPE_ANY; nr.lpRemoteName = &sname2[0]; DWORD ret=WNetAddConnection2( &nr, "", "", 0); if(ret!=NO_ERROR){ std::cout<<"WNetAddConnection2 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } } std::string pname=std::string("\\\\")+sname+std::string("\\pipe\\testpipe"); HANDLE phandle1=CreateFile ( pname.c_str(), GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0,0 ); if(phandle1==INVALID_HANDLE_VALUE){ std::cout<<"CreateFile1 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } HANDLE phandle2=CreateFile ( pname.c_str(), GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0,0 ); if(phandle2==INVALID_HANDLE_VALUE){ std::cout<<"CreateFile2 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } char msg[sizeof(msg1)]; unsigned long s; unsigned long foo=0; if(ReadFile(phandle1, &msg, sizeof msg1, &s, 0)==0){ std::cout<<"ReadFile1 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } std::cout<<msg<<"\n"; if(WriteFile (phandle1, &foo, sizeof foo, &foo, 0)==0){ std::cout<<"WriteFile1 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } if(ReadFile(phandle2, &msg, sizeof msg1, &s, 0)==0){ std::cout<<"ReadFile2 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } std::cout<<msg<<"\n"; if(WriteFile (phandle2, &foo, sizeof foo, &foo, 0)==0){ std::cout<<"WriteFile2 "<<GetLastError()<<"\n"; std::getline(std::cin, c); return 1; } std::cout<<"Finished\n"; std::getline(std::cin, c); return 0; } Specific error: 5 (ERROR_ACCESS_DENIED) during the first call to CreateFile in the client program.
Update
I figured out a bit with named pipes. It is also necessary to add on the machine where the server is running, in the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters NullSessionPipes in NullSessionPipes the channel name. Then the above code works if the server is Win XP and the client is Win 7. But on the contrary, for some reason it works only for reading ( GENERIC_READ instead of GENERIC_READ|GENERIC_WRITE in CreateFile ), otherwise ERROR_ACCESS_DENIED.
I also found an article about anonymous channels on MSDN. There is a much more complicated example, but it provides only read access, and I did not succeed in changing the code for the recording to work. I installed PIPE_ACCESS_DUPLEX instead of PIPE_ACCESS_OUTBOUND in CreateNamedPipe , GENERIC_READ | GENERIC_WRITE GENERIC_READ | GENERIC_WRITE instead of FILE_GENERIC_READ in AddAccessAllowedAce , GENERIC_READ | GENERIC_WRITE GENERIC_READ | GENERIC_WRITE instead of GENERIC_READ in CreateFile , but error 5 also occurs if the server is Win 7.
That's what's in the registry of Windows 7 (maybe somewhere there is an error?) The NullSessionPipes value contains the strings "testpipe" and "AnonymousPipe".
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\LanmanServer\Parameters] "ServiceDll"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,\ 00,74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,\ 73,00,72,00,76,00,73,00,76,00,63,00,2e,00,64,00,6c,00,6c,00,00,00 "ServiceDllUnloadOnStop"=dword:00000001 "EnableAuthenticateUserSharing"=dword:00000001 "NullSessionPipes"=hex(7):74,00,65,00,73,00,74,00,70,00,69,00,70,00,65,00,00,\ 00,41,00,6e,00,6f,00,6e,00,79,00,6d,00,6f,00,75,00,73,00,50,00,69,00,70,00,\ 65,00,00,00,00,00 "autodisconnect"=dword:0000000f "enableforcedlogoff"=dword:00000001 "enablesecuritysignature"=dword:00000000 "requiresecuritysignature"=dword:00000000 "restrictnullsessaccess"=dword:00000000 "Lmannounce"=dword:00000000 "Size"=dword:00000001 "AdjustedNullSessionPipes"=dword:00000003 "Guid"=hex:eb,c5,75,fd,46,51,ce,4c,8f,64,a9,70,12,f6,05,6e Tell me how to properly create an anonymous named channel?
Update 2
If you enable the “Network access: allow the use of“ For all ”permissions to anonymous users” setting or add the “Imitation of client after authentication” permission for the ANONYMOUS LOGON group, then my example and MSDN example work without errors. It is just not clear why - after all, impersonation functions are not called anywhere.
Update 3
Finally, I found articles explaining what was happening: https://blogs.technet.microsoft.com/nettracer/2010/07/23/why-does-anonymous-pipe-access-fail-on-windows-vista- 2008-windows-7-or-windows-2008-r2 / , http://blog.m-ri.de/index.php/2009/12/08/windows-integrity-control-schreibzugriff-auf-eine-named -pipe-eines-services-ueber-anonymen-zugriff-auf-vista-windows-2008-server-und-windows-7 / (in German, can be read in translation into English) The example given in the last article works without giving an error without the above settings! (You just need to add the channel name to NullSessionPipes )
Since I still announced a contest and the topic was practically not covered anywhere, it would be nice if someone wrote a detailed answer based on the articles listed.
//Define SDDL for the security descriptor PCWSTR szSDDL = L"D:" //Discretionary ACL // L"(A;OICI;GA;;;AN)" // L"(A;OICI;GA;;;AU)" //allow read/write to authenticated users // L"(A;OICI;GA;;;BA)" //allow full control to administrators // ; L"("(A;;GA;;;"))" L"(A;;GWGR;;;AN)" L"(A;;GWGR;;;WD)";//Define SDDL for the security descriptor PCWSTR szSDDL = L"D:" //Discretionary ACL // L"(A;OICI;GA;;;AN)" // L"(A;OICI;GA;;;AU)" //allow read/write to authenticated users // L"(A;OICI;GA;;;BA)" //allow full control to administrators // ; L"("(A;;GA;;;"))" L"(A;;GWGR;;;AN)" L"(A;;GWGR;;;WD)";then it will work. PS Sorry, I can’t format the code in stupid comments! - SeNS