Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include <pthread.h>
4 : #include <stdlib.h>
5 :
6 : #include "sd-bus.h"
7 :
8 : #include "bus-internal.h"
9 : #include "bus-util.h"
10 : #include "log.h"
11 : #include "macro.h"
12 : #include "memory-util.h"
13 :
14 : struct context {
15 : int fds[2];
16 :
17 : bool client_negotiate_unix_fds;
18 : bool server_negotiate_unix_fds;
19 :
20 : bool client_anonymous_auth;
21 : bool server_anonymous_auth;
22 : };
23 :
24 7 : static void *server(void *p) {
25 7 : struct context *c = p;
26 7 : sd_bus *bus = NULL;
27 : sd_id128_t id;
28 7 : bool quit = false;
29 : int r;
30 :
31 7 : assert_se(sd_id128_randomize(&id) >= 0);
32 :
33 7 : assert_se(sd_bus_new(&bus) >= 0);
34 7 : assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
35 7 : assert_se(sd_bus_set_server(bus, 1, id) >= 0);
36 7 : assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
37 7 : assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
38 7 : assert_se(sd_bus_start(bus) >= 0);
39 :
40 37 : while (!quit) {
41 55 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
42 :
43 31 : r = sd_bus_process(bus, &m);
44 31 : if (r < 0) {
45 1 : log_error_errno(r, "Failed to process requests: %m");
46 1 : goto fail;
47 : }
48 :
49 30 : if (r == 0) {
50 8 : r = sd_bus_wait(bus, (uint64_t) -1);
51 8 : if (r < 0) {
52 0 : log_error_errno(r, "Failed to wait: %m");
53 0 : goto fail;
54 : }
55 :
56 8 : continue;
57 : }
58 :
59 22 : if (!m)
60 15 : continue;
61 :
62 7 : log_info("Got message! member=%s", strna(sd_bus_message_get_member(m)));
63 :
64 7 : if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {
65 :
66 6 : assert_se((sd_bus_can_send(bus, 'h') >= 1) ==
67 : (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
68 :
69 6 : r = sd_bus_message_new_method_return(m, &reply);
70 6 : if (r < 0) {
71 0 : log_error_errno(r, "Failed to allocate return: %m");
72 0 : goto fail;
73 : }
74 :
75 6 : quit = true;
76 :
77 1 : } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
78 0 : r = sd_bus_message_new_method_error(
79 : m,
80 : &reply,
81 0 : &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
82 0 : if (r < 0) {
83 0 : log_error_errno(r, "Failed to allocate return: %m");
84 0 : goto fail;
85 : }
86 : }
87 :
88 7 : if (reply) {
89 6 : r = sd_bus_send(bus, reply, NULL);
90 6 : if (r < 0) {
91 0 : log_error_errno(r, "Failed to send reply: %m");
92 0 : goto fail;
93 : }
94 : }
95 : }
96 :
97 6 : r = 0;
98 :
99 7 : fail:
100 7 : if (bus) {
101 7 : sd_bus_flush(bus);
102 7 : sd_bus_unref(bus);
103 : }
104 :
105 7 : return INT_TO_PTR(r);
106 : }
107 :
108 7 : static int client(struct context *c) {
109 7 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
110 7 : _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
111 7 : sd_bus_error error = SD_BUS_ERROR_NULL;
112 : int r;
113 :
114 7 : assert_se(sd_bus_new(&bus) >= 0);
115 7 : assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
116 7 : assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
117 7 : assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0);
118 7 : assert_se(sd_bus_start(bus) >= 0);
119 :
120 7 : r = sd_bus_message_new_method_call(
121 : bus,
122 : &m,
123 : "org.freedesktop.systemd.test",
124 : "/",
125 : "org.freedesktop.systemd.test",
126 : "Exit");
127 7 : if (r < 0)
128 0 : return log_error_errno(r, "Failed to allocate method call: %m");
129 :
130 7 : r = sd_bus_call(bus, m, 0, &error, &reply);
131 7 : if (r < 0)
132 1 : return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, -r));
133 :
134 6 : return 0;
135 : }
136 :
137 7 : static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_fds,
138 : bool client_anonymous_auth, bool server_anonymous_auth) {
139 :
140 : struct context c;
141 : pthread_t s;
142 : void *p;
143 : int r, q;
144 :
145 7 : zero(c);
146 :
147 7 : assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
148 :
149 7 : c.client_negotiate_unix_fds = client_negotiate_unix_fds;
150 7 : c.server_negotiate_unix_fds = server_negotiate_unix_fds;
151 7 : c.client_anonymous_auth = client_anonymous_auth;
152 7 : c.server_anonymous_auth = server_anonymous_auth;
153 :
154 7 : r = pthread_create(&s, NULL, server, &c);
155 7 : if (r != 0)
156 0 : return -r;
157 :
158 7 : r = client(&c);
159 :
160 7 : q = pthread_join(s, &p);
161 7 : if (q != 0)
162 0 : return -q;
163 :
164 7 : if (r < 0)
165 1 : return r;
166 :
167 6 : if (PTR_TO_INT(p) < 0)
168 0 : return PTR_TO_INT(p);
169 :
170 6 : return 0;
171 : }
172 :
173 1 : int main(int argc, char *argv[]) {
174 : int r;
175 :
176 1 : r = test_one(true, true, false, false);
177 1 : assert_se(r >= 0);
178 :
179 1 : r = test_one(true, false, false, false);
180 1 : assert_se(r >= 0);
181 :
182 1 : r = test_one(false, true, false, false);
183 1 : assert_se(r >= 0);
184 :
185 1 : r = test_one(false, false, false, false);
186 1 : assert_se(r >= 0);
187 :
188 1 : r = test_one(true, true, true, true);
189 1 : assert_se(r >= 0);
190 :
191 1 : r = test_one(true, true, false, true);
192 1 : assert_se(r >= 0);
193 :
194 1 : r = test_one(true, true, true, false);
195 1 : assert_se(r == -EPERM);
196 :
197 1 : return EXIT_SUCCESS;
198 : }
|