1 // Copyright 2006 Alp Toker <alp@atoker.com> 2 // This software is made available under the MIT License 3 // See COPYING for details 4 5 //We send BSD-style credentials on all platforms 6 //Doesn't seem to break Linux (but is redundant there) 7 //This may turn out to be a bad idea 8 #define HAVE_CMSGCRED 9 10 using System; 11 using System.IO; 12 using System.Text; 13 using System.Runtime.InteropServices; 14 using DBus.Unix; 15 using DBus.Protocol; 16 17 namespace DBus.Transports 18 { 19 class UnixNativeTransport : UnixTransport 20 { 21 internal UnixSocket socket; 22 AuthString()23 public override string AuthString () 24 { 25 long uid = Mono.Unix.Native.Syscall.geteuid (); 26 return uid.ToString (); 27 } 28 Open(string path, bool @abstract)29 public override void Open (string path, bool @abstract) 30 { 31 if (String.IsNullOrEmpty (path)) 32 throw new ArgumentException ("path"); 33 34 if (@abstract) 35 socket = OpenAbstractUnix (path); 36 else 37 socket = OpenUnix (path); 38 39 //socket.Blocking = true; 40 SocketHandle = (long)socket.Handle; 41 //Stream = new UnixStream ((int)socket.Handle); 42 Stream = new UnixStream (socket); 43 } 44 45 //send peer credentials null byte 46 //different platforms do this in different ways 47 #if HAVE_CMSGCRED WriteBsdCred()48 unsafe void WriteBsdCred () 49 { 50 //null credentials byte 51 byte buf = 0; 52 53 IOVector iov = new IOVector (); 54 //iov.Base = (IntPtr)(&buf); 55 iov.Base = &buf; 56 iov.Length = 1; 57 58 msghdr msg = new msghdr (); 59 msg.msg_iov = &iov; 60 msg.msg_iovlen = 1; 61 62 cmsg cm = new cmsg (); 63 msg.msg_control = (IntPtr)(&cm); 64 msg.msg_controllen = (uint)sizeof (cmsg); 65 cm.hdr.cmsg_len = (uint)sizeof (cmsg); 66 cm.hdr.cmsg_level = 0xffff; //SOL_SOCKET 67 cm.hdr.cmsg_type = 0x03; //SCM_CREDS 68 69 int written = socket.SendMsg (&msg, 0); 70 if (written != 1) 71 throw new Exception ("Failed to write credentials"); 72 } 73 #endif 74 WriteCred()75 public override void WriteCred () 76 { 77 #if HAVE_CMSGCRED 78 try { 79 WriteBsdCred (); 80 return; 81 } catch { 82 if (ProtocolInformation.Verbose) 83 Console.Error.WriteLine ("Warning: WriteBsdCred() failed; falling back to ordinary WriteCred()"); 84 } 85 #endif 86 //null credentials byte 87 byte buf = 0; 88 Stream.WriteByte (buf); 89 } 90 GetSockAddr(string path)91 public static byte[] GetSockAddr (string path) 92 { 93 byte[] p = Encoding.Default.GetBytes (path); 94 95 byte[] sa = new byte[2 + p.Length + 1]; 96 97 sa[0] = (byte) sa.Length; 98 sa[1] = 1; /* AF_UNIX */ 99 100 for (int i = 0 ; i != p.Length ; i++) 101 sa[2 + i] = p[i]; 102 sa[2 + p.Length] = 0; //null suffix for domain socket addresses, see unix(7) 103 104 return sa; 105 } 106 GetSockAddrAbstract(string path)107 public static byte[] GetSockAddrAbstract (string path) 108 { 109 byte[] p = Encoding.Default.GetBytes (path); 110 111 byte[] sa = new byte[2 + 1 + p.Length]; 112 113 sa[0] = (byte) sa.Length; 114 sa[1] = 1; /* AF_UNIX */ 115 116 sa[2] = 0; //null prefix for abstract domain socket addresses, see unix(7) 117 for (int i = 0 ; i != p.Length ; i++) 118 sa[3 + i] = p[i]; 119 120 return sa; 121 } 122 OpenUnix(string path)123 internal UnixSocket OpenUnix (string path) 124 { 125 byte[] sa = GetSockAddr (path); 126 UnixSocket client = new UnixSocket (); 127 client.Connect (sa); 128 return client; 129 } 130 OpenAbstractUnix(string path)131 internal UnixSocket OpenAbstractUnix (string path) 132 { 133 byte[] sa = GetSockAddrAbstract (path); 134 UnixSocket client = new UnixSocket (); 135 client.Connect (sa); 136 return client; 137 } 138 } 139 140 #if HAVE_CMSGCRED 141 unsafe struct msghdr 142 { 143 public IntPtr msg_name; //optional address 144 public uint msg_namelen; //size of address 145 public IOVector *msg_iov; //scatter/gather array 146 public int msg_iovlen; //# elements in msg_iov 147 public IntPtr msg_control; //ancillary data, see below 148 public uint msg_controllen; //ancillary data buffer len 149 public int msg_flags; //flags on received message 150 } 151 152 struct cmsghdr 153 { 154 public uint cmsg_len; //data byte count, including header 155 public int cmsg_level; //originating protocol 156 public int cmsg_type; //protocol-specific type 157 } 158 159 unsafe struct cmsgcred 160 { 161 const int CMGROUP_MAX = 16; 162 163 public int cmcred_pid; //PID of sending process 164 public uint cmcred_uid; //real UID of sending process 165 public uint cmcred_euid; //effective UID of sending process 166 public uint cmcred_gid; //real GID of sending process 167 public short cmcred_ngroups; //number or groups 168 public fixed uint cmcred_groups[CMGROUP_MAX]; //groups 169 } 170 171 struct cmsg 172 { 173 public cmsghdr hdr; 174 public cmsgcred cred; 175 } 176 #endif 177 } 178