1// Tests of SCTP functionality
2// Requires: libsctp-dev package on Debian Linux, CONFIG_IP_SCTP in kernel config
3#ifdef HAVE_SCTP
4#include <sys/types.h>
5#include <sys/socket.h>
6#include <netinet/in.h>
7#include <netinet/sctp.h>
8#include <arpa/inet.h>
9#include <stdio.h>
10
11#include "syscalls.h"
12#include "capsicum.h"
13#include "capsicum-test.h"
14
15static cap_rights_t r_ro;
16static cap_rights_t r_wo;
17static cap_rights_t r_rw;
18static cap_rights_t r_all;
19static cap_rights_t r_all_nopeel;
20#define DO_PEELOFF 0x1A
21#define DO_TERM    0x1B
22
23static int SctpClient(int port, unsigned char byte) {
24  // Create sockets
25  int sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
26  EXPECT_OK(sock);
27  if (sock < 0) return sock;
28  int cap_sock_ro = dup(sock);
29  EXPECT_OK(cap_sock_ro);
30  EXPECT_OK(cap_rights_limit(cap_sock_ro, &r_rw));
31  int cap_sock_rw = dup(sock);
32  EXPECT_OK(cap_sock_rw);
33  EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
34  int cap_sock_all = dup(sock);
35  EXPECT_OK(cap_sock_all);
36  EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
37  close(sock);
38
39  // Send a message.  Requires CAP_WRITE and CAP_CONNECT.
40  struct sockaddr_in serv_addr;
41  memset(&serv_addr, 0, sizeof(serv_addr));
42  serv_addr.sin_family = AF_INET;
43  serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
44  serv_addr.sin_port = htons(port);
45
46  EXPECT_NOTCAPABLE(sctp_sendmsg(cap_sock_ro, &byte, 1,
47                                 (struct sockaddr*)&serv_addr, sizeof(serv_addr),
48                                 0, 0, 1, 0, 0));
49  EXPECT_NOTCAPABLE(sctp_sendmsg(cap_sock_rw, &byte, 1,
50                                 (struct sockaddr*)&serv_addr, sizeof(serv_addr),
51                                 0, 0, 1, 0, 0));
52  if (verbose) fprintf(stderr, "  [%d]sctp_sendmsg(%02x)\n", getpid_(), byte);
53  EXPECT_OK(sctp_sendmsg(cap_sock_all, &byte, 1,
54                         (struct sockaddr*)&serv_addr, sizeof(serv_addr),
55                         0, 0, 1, 0, 0));
56  close(cap_sock_ro);
57  close(cap_sock_rw);
58  return cap_sock_all;
59}
60
61
62TEST(Sctp, Socket) {
63  int sock = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
64  EXPECT_OK(sock);
65  if (sock < 0) return;
66
67  cap_rights_init(&r_ro, CAP_READ);
68  cap_rights_init(&r_wo, CAP_WRITE);
69  cap_rights_init(&r_rw, CAP_READ, CAP_WRITE);
70  cap_rights_init(&r_all, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
71  cap_rights_init(&r_all_nopeel, CAP_READ, CAP_WRITE, CAP_SOCK_CLIENT, CAP_SOCK_SERVER);
72  cap_rights_clear(&r_all_nopeel, CAP_PEELOFF);
73
74  int cap_sock_wo = dup(sock);
75  EXPECT_OK(cap_sock_wo);
76  EXPECT_OK(cap_rights_limit(cap_sock_wo, &r_wo));
77  int cap_sock_rw = dup(sock);
78  EXPECT_OK(cap_sock_rw);
79  EXPECT_OK(cap_rights_limit(cap_sock_rw, &r_rw));
80  int cap_sock_all = dup(sock);
81  EXPECT_OK(cap_sock_all);
82  EXPECT_OK(cap_rights_limit(cap_sock_all, &r_all));
83  int cap_sock_all_nopeel = dup(sock);
84  EXPECT_OK(cap_sock_all_nopeel);
85  EXPECT_OK(cap_rights_limit(cap_sock_all_nopeel, &r_all_nopeel));
86  close(sock);
87
88  struct sockaddr_in addr;
89  memset(&addr, 0, sizeof(addr));
90  addr.sin_family = AF_INET;
91  addr.sin_port = htons(0);
92  addr.sin_addr.s_addr = htonl(INADDR_ANY);
93  socklen_t len = sizeof(addr);
94
95  // Can only bind the fully-capable socket.
96  EXPECT_NOTCAPABLE(bind(cap_sock_rw, (struct sockaddr *)&addr, len));
97  EXPECT_OK(bind(cap_sock_all, (struct sockaddr *)&addr, len));
98
99  EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr *)&addr, &len));
100  int port = ntohs(addr.sin_port);
101
102  // Now we know the port involved, fork off children to run clients.
103  pid_t child1 = fork();
104  if (child1 == 0) {
105    // Child process 1: wait for server setup
106    sleep(1);
107    // Send a message that triggers peeloff
108    int client_sock = SctpClient(port, DO_PEELOFF);
109    sleep(1);
110    close(client_sock);
111    exit(HasFailure());
112  }
113
114  pid_t child2 = fork();
115  if (child2 == 0) {
116    // Child process 2: wait for server setup
117    sleep(2);
118    // Send a message that triggers server exit
119    int client_sock = SctpClient(port, DO_TERM);
120    close(client_sock);
121    exit(HasFailure());
122  }
123
124  // Can only listen on the fully-capable socket.
125  EXPECT_NOTCAPABLE(listen(cap_sock_rw, 3));
126  EXPECT_OK(listen(cap_sock_all, 3));
127
128  // Can only do socket operations on the fully-capable socket.
129  len = sizeof(addr);
130  EXPECT_NOTCAPABLE(getsockname(cap_sock_rw, (struct sockaddr*)&addr, &len));
131
132  struct sctp_event_subscribe events;
133  memset(&events, 0, sizeof(events));
134  events.sctp_association_event = 1;
135  events.sctp_data_io_event = 1;
136  EXPECT_NOTCAPABLE(setsockopt(cap_sock_rw, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)));
137  len = sizeof(events);
138  EXPECT_NOTCAPABLE(getsockopt(cap_sock_rw, IPPROTO_SCTP, SCTP_EVENTS, &events, &len));
139  memset(&events, 0, sizeof(events));
140  events.sctp_association_event = 1;
141  events.sctp_data_io_event = 1;
142  EXPECT_OK(setsockopt(cap_sock_all, IPPROTO_SCTP, SCTP_EVENTS, &events, sizeof(events)));
143  len = sizeof(events);
144  EXPECT_OK(getsockopt(cap_sock_all, IPPROTO_SCTP, SCTP_EVENTS, &events, &len));
145
146  len = sizeof(addr);
147  memset(&addr, 0, sizeof(addr));
148  EXPECT_OK(getsockname(cap_sock_all, (struct sockaddr*)&addr, &len));
149  EXPECT_EQ(AF_INET, addr.sin_family);
150  EXPECT_EQ(htons(port), addr.sin_port);
151
152  struct sockaddr_in client_addr;
153  socklen_t addr_len = sizeof(client_addr);
154  unsigned char buffer[1024];
155  struct sctp_sndrcvinfo sri;
156  memset(&sri, 0, sizeof(sri));
157  int flags = 0;
158  EXPECT_NOTCAPABLE(sctp_recvmsg(cap_sock_wo, buffer, sizeof(buffer),
159                                 (struct sockaddr*)&client_addr, &addr_len,
160                                 &sri, &flags));
161  while (true) {
162  retry:
163    memset(&sri, 0, sizeof(sri));
164    int len = sctp_recvmsg(cap_sock_rw, buffer, sizeof(buffer),
165                           (struct sockaddr*)&client_addr, &addr_len,
166                           &sri, &flags);
167    if (len < 0 && errno == EAGAIN) goto retry;
168    EXPECT_OK(len);
169    if (len > 0) {
170      if (verbose) fprintf(stderr, "[%d]sctp_recvmsg(%02x..)", getpid_(), (unsigned)buffer[0]);
171      if (buffer[0] == DO_PEELOFF) {
172        if (verbose) fprintf(stderr, "..peeling off association %08lx\n", (long)sri.sinfo_assoc_id);
173        // Peel off the association.  Needs CAP_PEELOFF.
174        int rc1 = sctp_peeloff(cap_sock_all_nopeel, sri.sinfo_assoc_id);
175        EXPECT_NOTCAPABLE(rc1);
176        int rc2 = sctp_peeloff(cap_sock_all, sri.sinfo_assoc_id);
177        EXPECT_OK(rc2);
178        int peeled = std::max(rc1, rc2);
179        if (peeled > 0) {
180#ifdef CAP_FROM_PEELOFF
181          // Peeled off FD should have same rights as original socket.
182          cap_rights_t rights;
183          EXPECT_OK(cap_rights_get(peeled, &rights));
184          EXPECT_RIGHTS_EQ(&r_all, &rights);
185#endif
186          close(peeled);
187        }
188      } else if (buffer[0] == DO_TERM) {
189        if (verbose) fprintf(stderr, "..terminating server\n");
190        break;
191      }
192    } else if (len < 0) {
193      break;
194    }
195  }
196
197  // Wait for the children.
198  int status;
199  int rc;
200  EXPECT_EQ(child1, waitpid(child1, &status, 0));
201  rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
202  EXPECT_EQ(0, rc);
203  EXPECT_EQ(child2, waitpid(child2, &status, 0));
204  rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
205  EXPECT_EQ(0, rc);
206
207  close(cap_sock_wo);
208  close(cap_sock_rw);
209  close(cap_sock_all);
210  close(cap_sock_all_nopeel);
211}
212#endif
213