File: UnixNativeTransport.cs

package info (click to toggle)
aircrack-ng 1%3A1.6%2Bgit20210130.91820bc-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 19,056 kB
  • sloc: ansic: 67,045; cs: 5,392; sh: 3,773; python: 2,565; pascal: 1,074; asm: 570; makefile: 253; cpp: 46
file content (277 lines) | stat: -rw-r--r-- 7,400 bytes parent folder | download | duplicates (16)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
// Copyright 2006 Alp Toker <alp@atoker.com>
// This software is made available under the MIT License
// See COPYING for details

//We send BSD-style credentials on all platforms
//Doesn't seem to break Linux (but is redundant there)
//This may turn out to be a bad idea
#define HAVE_CMSGCRED

using System;
using System.IO;
using System.Text;

using System.Runtime.InteropServices;

using Mono.Unix;
using Mono.Unix.Native;

namespace NDesk.DBus.Transports
{
	class UnixSocket
	{
		public const short AF_UNIX = 1;
		//TODO: SOCK_STREAM is 2 on Solaris
		public const short SOCK_STREAM = 1;

		//TODO: some of these are provided by libsocket instead of libc on Solaris

		[DllImport ("libc", SetLastError=true)]
			protected static extern int socket (int domain, int type, int protocol);

		[DllImport ("libc", SetLastError=true)]
			protected static extern int connect (int sockfd, byte[] serv_addr, uint addrlen);

		[DllImport ("libc", SetLastError=true)]
			protected static extern int bind (int sockfd, byte[] my_addr, uint addrlen);

		[DllImport ("libc", SetLastError=true)]
			protected static extern int listen (int sockfd, int backlog);

		//TODO: this prototype is probably wrong, fix it
		[DllImport ("libc", SetLastError=true)]
			protected static extern int accept (int sockfd, byte[] addr, ref uint addrlen);

		//TODO: confirm and make use of these functions
		[DllImport ("libc", SetLastError=true)]
			protected static extern int getsockopt (int s, int optname, IntPtr optval, ref uint optlen);

		[DllImport ("libc", SetLastError=true)]
			protected static extern int setsockopt (int s, int optname, IntPtr optval, uint optlen);

		[DllImport ("libc", SetLastError=true)]
			public static extern int recvmsg (int s, IntPtr msg, int flags);

		[DllImport ("libc", SetLastError=true)]
			public static extern int sendmsg (int s, IntPtr msg, int flags);

		public int Handle;

		public UnixSocket (int handle)
		{
			this.Handle = handle;
		}

		public UnixSocket ()
		{
			//TODO: don't hard-code PF_UNIX and SOCK_STREAM or SocketType.Stream
			//AddressFamily family, SocketType type, ProtocolType proto

			int r = socket (AF_UNIX, SOCK_STREAM, 0);
			//we should get the Exception from UnixMarshal and throw it here for a better stack trace, but the relevant API seems to be private
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
			Handle = r;
		}

		protected bool connected = false;

		//TODO: consider memory management
		public void Connect (byte[] remote_end)
		{
			int r = connect (Handle, remote_end, (uint)remote_end.Length);
			//we should get the Exception from UnixMarshal and throw it here for a better stack trace, but the relevant API seems to be private
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
			connected = true;
		}

		//assigns a name to the socket
		public void Bind (byte[] local_end)
		{
			int r = bind (Handle, local_end, (uint)local_end.Length);
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
		}

		public void Listen (int backlog)
		{
			int r = listen (Handle, backlog);
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
		}

		public UnixSocket Accept ()
		{
			byte[] addr = new byte[110];
			uint addrlen = (uint)addr.Length;

			int r = accept (Handle, addr, ref addrlen);
			UnixMarshal.ThrowExceptionForLastErrorIf (r);
			//TODO: use the returned addr
			//TODO: fix probable memory leak here
			//string str = Encoding.Default.GetString (addr, 0, (int)addrlen);
			return new UnixSocket (r);
		}
	}

	struct IOVector
	{
		public IntPtr Base;
		public int Length;
	}

	class UnixNativeTransport : UnixTransport
	{
		protected UnixSocket socket;

		public override void Open (string path, bool @abstract)
		{
			if (String.IsNullOrEmpty (path))
				throw new ArgumentException ("path");

			if (@abstract)
				socket = OpenAbstractUnix (path);
			else
				socket = OpenUnix (path);

			//socket.Blocking = true;
			SocketHandle = (long)socket.Handle;
			Stream = new UnixStream ((int)socket.Handle);
		}

		//send peer credentials null byte
		//different platforms do this in different ways
#if HAVE_CMSGCRED
		unsafe void WriteBsdCred ()
		{
			//null credentials byte
			byte buf = 0;

			IOVector iov = new IOVector ();
			iov.Base = (IntPtr)(&buf);
			iov.Length = 1;

			msghdr msg = new msghdr ();
			msg.msg_iov = &iov;
			msg.msg_iovlen = 1;

			cmsg cm = new cmsg ();
			msg.msg_control = (IntPtr)(&cm);
			msg.msg_controllen = (uint)sizeof (cmsg);
			cm.hdr.cmsg_len = (uint)sizeof (cmsg);
			cm.hdr.cmsg_level = 0xffff; //SOL_SOCKET
			cm.hdr.cmsg_type = 0x03; //SCM_CREDS

			int written = UnixSocket.sendmsg (socket.Handle, (IntPtr)(&msg), 0);
			UnixMarshal.ThrowExceptionForLastErrorIf (written);
			if (written != 1)
				throw new Exception ("Failed to write credentials");
		}
#endif

		public override void WriteCred ()
		{
#if HAVE_CMSGCRED
			try {
				WriteBsdCred ();
			} catch {
				if (Protocol.Verbose)
					Console.Error.WriteLine ("Warning: WriteBsdCred() failed; falling back to ordinary WriteCred()");
				//null credentials byte
				byte buf = 0;
				Stream.WriteByte (buf);
			}
#else
			//null credentials byte
			byte buf = 0;
			Stream.WriteByte (buf);
#endif
		}

		protected UnixSocket OpenAbstractUnix (string path)
		{
			byte[] p = Encoding.Default.GetBytes (path);

			byte[] sa = new byte[2 + 1 + p.Length];

			//we use BitConverter to stay endian-safe
			byte[] afData = BitConverter.GetBytes (UnixSocket.AF_UNIX);
			sa[0] = afData[0];
			sa[1] = afData[1];

			sa[2] = 0; //null prefix for abstract domain socket addresses, see unix(7)
			for (int i = 0 ; i != p.Length ; i++)
				sa[3 + i] = p[i];

			UnixSocket client = new UnixSocket ();
			client.Connect (sa);

			return client;
		}

		public UnixSocket OpenUnix (string path)
		{
			byte[] p = Encoding.Default.GetBytes (path);

			byte[] sa = new byte[2 + p.Length + 1];

			//we use BitConverter to stay endian-safe
			byte[] afData = BitConverter.GetBytes (UnixSocket.AF_UNIX);
			sa[0] = afData[0];
			sa[1] = afData[1];

			for (int i = 0 ; i != p.Length ; i++)
				sa[2 + i] = p[i];
			sa[2 + p.Length] = 0; //null suffix for domain socket addresses, see unix(7)

			UnixSocket client = new UnixSocket ();
			client.Connect (sa);

			return client;
		}
	}

#if HAVE_CMSGCRED
	/*
	public struct msg
	{
		public IntPtr msg_next;
		public long msg_type;
		public ushort msg_ts;
		short msg_spot;
		IntPtr label;
	}
	*/

	unsafe struct msghdr
	{
		public IntPtr msg_name; //optional address
		public uint msg_namelen; //size of address
		public IOVector *msg_iov; //scatter/gather array
		public int msg_iovlen; //# elements in msg_iov
		public IntPtr msg_control; //ancillary data, see below
		public uint msg_controllen; //ancillary data buffer len
		public int msg_flags; //flags on received message
	}

	struct cmsghdr
	{
		public uint cmsg_len; //data byte count, including header
		public int cmsg_level; //originating protocol
		public int cmsg_type; //protocol-specific type
	}

	unsafe struct cmsgcred
	{
		public int cmcred_pid; //PID of sending process
		public uint cmcred_uid; //real UID of sending process
		public uint cmcred_euid; //effective UID of sending process
		public uint cmcred_gid; //real GID of sending process
		public short cmcred_ngroups; //number or groups
		public fixed uint cmcred_groups[16]; //groups, CMGROUP_MAX
	}

	struct cmsg
	{
		public cmsghdr hdr;
		public cmsgcred cred;
	}
#endif
}