Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libcs/csrecv.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1990-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* Glenn Fowler
24
* AT&T Research
25
*
26
* receive up to n fds from stream fd
27
* number of fds received is returned
28
*
29
* NOTE: cssend() only supported for local host
30
* for local host Csid_t.hid==0, Csid_t.pid not trusted
31
* for remote host csauth() can authenticate Csid_t.[ug]id
32
*/
33
34
#include "cslib.h"
35
36
#if CS_LIB_SOCKET_RIGHTS && !CS_LIB_STREAM
37
38
static int
39
sockrecv(int fd, Csid_t* id, int* fds, int n)
40
{
41
struct iovec iov;
42
struct msghdr msg;
43
#if _mem_msg_control_msghdr
44
struct
45
{
46
struct cmsghdr hdr;
47
int fds[OPEN_MAX + 1];
48
} ctl;
49
#else
50
#define msg_control msg_accrights
51
#define msg_controllen msg_accrightslen
52
#endif
53
54
msg.msg_name = 0;
55
msg.msg_namelen = 0;
56
msg.msg_iov = &iov;
57
msg.msg_iovlen = 1;
58
iov.iov_base = (caddr_t)id;
59
iov.iov_len = sizeof(*id);
60
#if _mem_msg_control_msghdr
61
msg.msg_control = (caddr_t)&ctl;
62
msg.msg_controllen = (char*)&ctl.fds[n] - (char*)&ctl;
63
ctl.hdr.cmsg_len = msg.msg_controllen;
64
ctl.hdr.cmsg_level = SOL_SOCKET;
65
ctl.hdr.cmsg_type = SCM_RIGHTS;
66
#else
67
msg.msg_control = (caddr_t)fds;
68
msg.msg_controllen = n * sizeof(fds[0]);
69
#endif
70
if (recvmsg(fd, &msg, 0) < 0) return -1;
71
id->hid = id->hid;
72
id->pid = id->pid;
73
id->uid = id->uid;
74
id->gid = id->gid;
75
#if _mem_msg_control_msghdr
76
if (ctl.hdr.cmsg_level != SOL_SOCKET || ctl.hdr.cmsg_type != SCM_RIGHTS)
77
return -1;
78
n = (ctl.hdr.cmsg_len - sizeof(ctl.hdr)) / sizeof(fds[0]);
79
for (fd = 0; fd < n; fd++)
80
fds[fd] = ctl.fds[fd];
81
return n;
82
#else
83
return msg.msg_controllen / sizeof(fds[0]);
84
#endif
85
}
86
87
#endif
88
89
int
90
csrecv(register Cs_t* state, int fd, Csid_t* id, int* fds, int n)
91
{
92
int oerrno;
93
Csid_t ignore;
94
95
#if CS_LIB_SOCKET
96
97
Sock_size_t namlen;
98
struct sockaddr_in nam;
99
100
#if CS_LIB_SOCKET_UN && !CS_LIB_STREAM
101
102
#if CS_LIB_SOCKET_RIGHTS
103
int rfd[OPEN_MAX + 1];
104
#endif
105
struct stat st;
106
107
#endif
108
109
#endif
110
111
#if CS_LIB_STREAM || CS_LIB_V10
112
113
int m;
114
struct strrecvfd rcv;
115
struct csfdhdr hdr;
116
117
#if CS_LIB_V10
118
119
struct tcpuser tcp;
120
121
#endif
122
123
#endif
124
125
#if CS_LIB_STREAM || CS_LIB_V10 || CS_LIB_SOCKET_RIGHTS
126
127
register int i;
128
129
#endif
130
131
messagef((state->id, NiL, -8, "recv(%d,%d) call", fd, n));
132
if (n < 1)
133
{
134
errno = EINVAL;
135
return -1;
136
}
137
if (!id) id = &ignore;
138
memzero(id, sizeof(*id));
139
oerrno = errno;
140
csprotect(&cs);
141
142
#if CS_LIB_V10
143
144
if (!ioctl(fd, TCPGETADDR, &tcp))
145
{
146
if ((fds[0] = tcp_accept(fd, &tcp)) < 0)
147
{
148
messagef((state->id, NiL, -1, "recv: %d: tcp accept error", fd));
149
return -1;
150
}
151
id->hid = tcp.faddr;
152
return 1;
153
}
154
messagef((state->id, NiL, -1, "recv: %d: ioctl TCPGETADDR error", fd));
155
156
#else
157
158
#if CS_LIB_SOCKET
159
160
namlen = sizeof(nam);
161
if ((fds[0] = accept(fd, (struct sockaddr*)&nam, &namlen)) >= 0)
162
{
163
164
#if CS_LIB_SOCKET_UN && !CS_LIB_STREAM
165
166
#if defined(__linux__) && defined(AF_UNSPEC)
167
if (nam.sin_family == AF_UNSPEC)
168
nam.sin_family = AF_UNIX;
169
#endif
170
if (nam.sin_family == AF_UNIX)
171
{
172
#if CS_LIB_SOCKET_RIGHTS
173
if (write(fds[0], "", 1) != 1)
174
{
175
messagef((state->id, NiL, -1, "recv: %d: ping write error", fd));
176
close(fds[0]);
177
return -1;
178
}
179
if (sockrecv(fds[0], id, rfd, 1) != 1)
180
{
181
messagef((state->id, NiL, -1, "recv: %d: sockrecv error", fd));
182
goto eperm;
183
}
184
if (fstat(rfd[0], &st))
185
{
186
messagef((state->id, NiL, -1, "recv: %d: %d: authentication stat error", fd, rfd[0]));
187
drop:
188
close(rfd[0]);
189
eperm:
190
close(fds[0]);
191
errno = EPERM;
192
return -1;
193
}
194
if ((st.st_mode & CS_AUTH_MASK) != CS_AUTH_MODE)
195
{
196
messagef((state->id, NiL, -1, "recv: %d: %d: invalid authentication mode %04o", fd, rfd[0], st.st_mode & CS_AUTH_MASK));
197
goto drop;
198
}
199
close(rfd[0]);
200
#else
201
if (fstat(fds[0], &st))
202
{
203
st.st_uid = geteuid();
204
st.st_gid = getegid();
205
}
206
#endif
207
id->uid = st.st_uid;
208
id->gid = st.st_gid;
209
}
210
else
211
212
#endif
213
214
if (nam.sin_family == AF_INET)
215
id->hid = (unsigned long)nam.sin_addr.s_addr;
216
return 1;
217
}
218
messagef((state->id, NiL, -1, "recv: %d: accept error", fd));
219
220
#endif
221
222
#endif
223
224
#if CS_LIB_STREAM || CS_LIB_V10
225
226
if (ioctl(fd, I_RECVFD, &rcv) < 0)
227
{
228
messagef((state->id, NiL, -1, "recv: %d: ioctl I_RECVFD error", fd));
229
switch (errno)
230
{
231
case EIO:
232
#ifdef EBADMSG
233
case EBADMSG:
234
#endif
235
break;
236
default:
237
return -1;
238
}
239
#if CS_LIB_STREAM
240
if (!(m = read(fd, &hdr, sizeof(hdr))))
241
#endif
242
m = read(fd, &hdr, sizeof(hdr));
243
if (m != sizeof(hdr))
244
{
245
errno = EINVAL;
246
messagef((state->id, NiL, -1, "recv: %d: hdr read error", fd));
247
return -1;
248
}
249
if (hdr.count <= 0)
250
{
251
errno = EINVAL;
252
messagef((state->id, NiL, -1, "recv: %d: invalid hdr count %d", fd, hdr.count));
253
return -1;
254
}
255
for (i = 0; i < hdr.count; i++)
256
{
257
if (ioctl(fd, I_RECVFD, &rcv) < 0)
258
{
259
messagef((state->id, NiL, -1, "recv: %d: ioctl I_RECVFD #%d error", fd, i + 1));
260
while (--i >= 0) close(fds[i]);
261
return -1;
262
}
263
fds[i] = rcv.fd;
264
}
265
id->pid = hdr.pid;
266
}
267
268
#ifdef I_ACCEPT
269
270
else if (ioctl(rcv.fd, I_ACCEPT, NiL) < 0)
271
{
272
messagef((state->id, NiL, -1, "recv: %d: ioctl I_ACCEPT error", fd));
273
close(rcv.fd);
274
return -1;
275
}
276
277
#endif
278
279
else
280
{
281
282
i = 1;
283
fds[0] = rcv.fd;
284
}
285
id->uid = rcv.uid;
286
id->gid = rcv.gid;
287
errno = oerrno;
288
return i;
289
290
#else
291
292
#if CS_LIB_SOCKET_RIGHTS
293
294
if ((i = sockrecv(fd, id, rfd, n + 1)) <= 1)
295
{
296
messagef((state->id, NiL, -1, "recv: %d: sockrecv error", fd));
297
nope:
298
if (i >= 0)
299
{
300
errno = EPERM;
301
while (--i >= 0) close(rfd[i]);
302
}
303
return -1;
304
}
305
if (fstat(rfd[0], &st))
306
{
307
messagef((state->id, NiL, -1, "recv: %d: %d: authentication stat error", fd, rfd[0]));
308
goto nope;
309
}
310
if ((st.st_mode & CS_AUTH_MASK) != CS_AUTH_MODE)
311
{
312
messagef((state->id, NiL, -1, "recv: %d: %d: invalid authentication mode %04o", fd, rfd[0], st.st_mode & CS_AUTH_MASK));
313
goto nope;
314
}
315
close(rfd[0]);
316
for (n = --i; i > 0; i--) fds[i - 1] = rfd[i];
317
id->uid = st.st_uid;
318
id->gid = st.st_gid;
319
return n;
320
321
#else
322
323
if (!access(CS_PROC_FD_TST, F_OK))
324
{
325
register int i;
326
register int j;
327
char* s;
328
unsigned long pid;
329
struct stat st;
330
331
s = state->temp;
332
if ((i = recv(fd, s, sizeof(state->temp), 0)) <= 0)
333
{
334
messagef((state->id, NiL, -1, "recv: %d: read error", fd));
335
return -1;
336
}
337
if (i >= sizeof(state->temp))
338
i = sizeof(state->temp) - 1;
339
s[i] = 0;
340
messagef((state->id, NiL, -8, "recv: `%s'", s));
341
pid = strtol(s, &s, 0);
342
i = strtol(s, &s, 0);
343
if (i < n)
344
n = i;
345
for (i = 0; i < n; i++)
346
fds[i] = strtol(s, &s, 0);
347
s = state->temp;
348
for (i = j = 0; i < n; i++)
349
{
350
sfsprintf(s, sizeof(state->temp), CS_PROC_FD_FMT, pid, fds[i]);
351
if (!stat(s, &st) && (fds[i] = open(s, (st.st_mode & (S_IRUSR|S_IWUSR)) == (S_IRUSR|S_IWUSR) ? O_RDWR : (st.st_mode & S_IWUSR) ? O_WRONLY : O_RDONLY)) >= 0)
352
j++;
353
}
354
if (id)
355
{
356
id->hid = 0;
357
id->pid = pid;
358
if (!stat(CS_PROC_FD_TST, &st))
359
{
360
id->uid = st.st_uid;
361
id->gid = st.st_gid;
362
}
363
else
364
{
365
id->uid = geteuid();
366
id->gid = getegid();
367
}
368
}
369
messagef((state->id, NiL, -8, "recv: %d fds", j));
370
return j;
371
}
372
errno = EINVAL;
373
return -1;
374
375
#endif
376
377
#endif
378
379
}
380
381
int
382
_cs_recv(int fd, Csid_t* id, int* fds, int n)
383
{
384
return csrecv(&cs, fd, id, fds, n);
385
}
386
387