From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25648 invoked by alias); 16 Oct 2014 21:34:32 -0000 Mailing-List: contact cygwin-developers-help@cygwin.com; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-developers-owner@cygwin.com Mail-Followup-To: cygwin-developers@cygwin.com Received: (qmail 25637 invoked by uid 89); 16 Oct 2014 21:34:32 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=AWL,BAYES_00,RCVD_IN_BL_SPAMCOP_NET,RCVD_IN_DNSWL_NONE,T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mailout04.t-online.de Received: from mailout04.t-online.de (HELO mailout04.t-online.de) (194.25.134.18) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 16 Oct 2014 21:34:30 +0000 Received: from fwd32.aul.t-online.de (fwd32.aul.t-online.de [172.20.26.144]) by mailout04.t-online.de (Postfix) with SMTP id 48F4C5DA8AE for ; Thu, 16 Oct 2014 23:34:27 +0200 (CEST) Received: from [192.168.2.108] (S98qJBZaghJcz4GsZUBgUF7la1M+1T8-QtXLE60sK7asQltgH6pIX3C1rxfukUmZU3@[79.224.127.148]) by fwd32.t-online.de with (TLSv1.2:ECDHE-RSA-AES256-SHA encrypted) esmtp id 1Xesgl-4bYSqu0; Thu, 16 Oct 2014 23:34:27 +0200 Message-ID: <544039E2.2040908@t-online.de> Date: Thu, 16 Oct 2014 21:34:00 -0000 From: Christian Franke User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20100101 Firefox/29.0 SeaMonkey/2.26.1 MIME-Version: 1.0 To: cygwin-developers@cygwin.com Subject: Cygwin AF_UNIX emulation Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2014-10/txt/msg00006.txt.bz2 Hi Corinna, Corinna Vinschen wrote: > On Oct 13 07:37, Christian Franke wrote: >>> I >>> also added a comment to explain why we do this and a FIXME comment so we >>> don't forget we're still looking for a more generic solution for the >>> SO_PEERCRED exchange. >> Definitely, at least because the current AF_LOCAL emulation has some >> security issues. > -v? With the secret+cred exchange, the current implementation is IMO reasonably safe. The client cannot connect without access to the socket file. Nasty detail: At least postfix sets the all AF_UNIX sockets to rw-rw-rw- and relies only on directory permissions (private: rwx------, public: rwx--x---) for access control. This is not effective on Cygwin. Due to the rw-rw-rw-, the 'secret' is world readable on Cygwin and another Cygwin specific patch is required :-) After new setsockopt(sd, ., SO_PEERCRED, .), AF_UNIX sockets are definitely vulnerable. Any local process could "guess" the TCP port and connect to any emulated AF_UNIX server regardless of user account. Two draft ideas for a new AF_UNIX emulation: 1) Keep the current secret+cred exchange, but handle accept() and connect() differently: After actual accept(): if (! recv client secret+cred) return abort_connection(); send(server secret+cred); set_state(connected). After actual connect(): send(client secret+cred); set_state(connected_but_secret_missing) Before actual recv() and getpeerid(): if (state == connected_but_secret_missing) { if (! recv server secret+cred) return abort_connection() set_state(connected) } Before actual send(): Do nothing special. Secrets should be different such that knowledge of client secret (send unconditionally) does not expose the server secret. In contrast to my first more 'symmetric' approach, this should support 'client send() before server accept()'. Could not test it with postfix yet. Unfortunately this leaves one security issue open: Client may send confidential data to malicious server if original server died. The client will recognize it too late in first receive. 2) Don't exchange anything over TCP. Rely on a connection table in the socket file. Use 'bind before connect()' to avoid races. local_bind: bind(localhost:0); getsockname(&server_port); create_socket_file(path); lock_socket_file(path) { socket_file.slot[0] = (server_port, my_creds); } local_connect: bind(localhost:0) getsockname(&client_port); lock_socket_file(path) { server_port = socket_file.slot[0].port; peer_creds = socket_file.slot[0].credentials; i = find_free_slot(); socket_file.slot[i] = (client_port, my_creds, timestamp); } return connect(localhost:serverport); local_accept: accept(&client_port); lock_socket_file(path) { i = find_slot(client_port)); peer_creds = socket_file.slot[i].credentials; } Problem: There is no real proof that the TCP peer is the actual peer listed in the file. Christian