1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3 * Copyright (c) 2017, Intel Corporation
4 * All rights reserved.
5 */
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <glib.h>
9 #include <inttypes.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13
14 #include "connection.h"
15 #include "connection-manager.h"
16 #include "command-source.h"
17 #include "source-interface.h"
18 #include "tpm2-command.h"
19 #include "tpm2-header.h"
20 #include "util.h"
21
22 #ifndef G_SOURCE_FUNC
23 #define G_SOURCE_FUNC(x) ((GSourceFunc)(void*)x)
24 #endif
25
26 enum {
27 PROP_0,
28 PROP_COMMAND_ATTRS,
29 PROP_CONNECTION_MANAGER,
30 PROP_SINK,
31 N_PROPERTIES
32 };
33 static GParamSpec *obj_properties [N_PROPERTIES] = { NULL, };
34
35 /**
36 * Function implementing the Source interface. Adds a sink for the source
37 * to pass data to.
38 */
39 void
command_source_add_sink(Source * self,Sink * sink)40 command_source_add_sink (Source *self,
41 Sink *sink)
42 {
43 CommandSource *src = COMMAND_SOURCE (self);
44 GValue value = G_VALUE_INIT;
45
46 g_debug (__func__);
47 g_value_init (&value, G_TYPE_OBJECT);
48 g_value_set_object (&value, sink);
49 g_object_set_property (G_OBJECT (src), "sink", &value);
50 g_value_unset (&value);
51 }
52 /*
53 * This function initializes the SourceInterface. This is just registering
54 * a function pointer with the interface.
55 */
56 static void
command_source_source_interface_init(gpointer g_iface)57 command_source_source_interface_init (gpointer g_iface)
58 {
59 SourceInterface *source = (SourceInterface*)g_iface;
60 source->add_sink = command_source_add_sink;
61 }
62 /*
63 * This is a callback function used to clean up memory used by the
64 * source_data_t structure. It's called by the GHashTable when removing
65 * source_data_t values.
66 */
67 static void
source_data_free(gpointer data)68 source_data_free (gpointer data)
69 {
70 source_data_t *source_data = (source_data_t*)data;
71 g_object_unref (source_data->cancellable);
72 g_source_unref (source_data->source);
73 g_free (source_data);
74 }
75 /*
76 * Initialize a CommandSource instance.
77 */
78 static void
command_source_init(CommandSource * source)79 command_source_init (CommandSource *source)
80 {
81 source->main_context = g_main_context_new ();
82 source->main_loop = g_main_loop_new (source->main_context, FALSE);
83 /*
84 * GHashTable mapping a GSocket to an instance of the source_data_t
85 * structure. The socket is the I/O mechanism for communicating with a
86 * client (from Connection object), and the source_data_t instance is
87 * a collection of data that we use to manage callbacks for I/O events
88 * from the main loop.
89 * The hash table owns a reference to the socket (key) and it owns
90 * the structure held in the value (it will be freed when removed).
91 */
92 source->istream_to_source_data_map =
93 g_hash_table_new_full (g_direct_hash,
94 g_direct_equal,
95 g_object_unref,
96 source_data_free);
97 }
98
99 G_DEFINE_TYPE_WITH_CODE (
100 CommandSource,
101 command_source,
102 TYPE_THREAD,
103 G_IMPLEMENT_INTERFACE (TYPE_SOURCE,
104 command_source_source_interface_init)
105 );
106
107 static void
command_source_set_property(GObject * object,guint property_id,GValue const * value,GParamSpec * pspec)108 command_source_set_property (GObject *object,
109 guint property_id,
110 GValue const *value,
111 GParamSpec *pspec)
112 {
113 CommandSource *self = COMMAND_SOURCE (object);
114
115 g_debug (__func__);
116 switch (property_id) {
117 case PROP_COMMAND_ATTRS:
118 self->command_attrs = COMMAND_ATTRS (g_value_dup_object (value));
119 break;
120 case PROP_CONNECTION_MANAGER:
121 self->connection_manager = CONNECTION_MANAGER (g_value_get_object (value));
122 break;
123 case PROP_SINK:
124 /* be rigid initially, add flexiblity later if we need it */
125 if (self->sink != NULL) {
126 g_warning (" sink already set");
127 break;
128 }
129 self->sink = SINK (g_value_get_object (value));
130 g_object_ref (self->sink);
131 break;
132 default:
133 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
134 break;
135 }
136 }
137
138 static void
command_source_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)139 command_source_get_property (GObject *object,
140 guint property_id,
141 GValue *value,
142 GParamSpec *pspec)
143 {
144 CommandSource *self = COMMAND_SOURCE (object);
145
146 g_debug (__func__);
147 switch (property_id) {
148 case PROP_COMMAND_ATTRS:
149 g_value_set_object (value, self->command_attrs);
150 break;
151 case PROP_CONNECTION_MANAGER:
152 g_value_set_object (value, self->connection_manager);
153 break;
154 case PROP_SINK:
155 g_value_set_object (value, self->sink);
156 break;
157 default:
158 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
159 break;
160 }
161 }
162 /*
163 * This function is invoked by the GMainLoop thread when a client GSocket has
164 * data ready. This is what makes the CommandSource a source (of Tpm2Commands).
165 * Here we take the GSocket, extract the command body from the it and
166 * transform it to a Tpm2Command. Most of the details are handled by utility
167 * functions further down the stack.
168 *
169 * If an error occurs while getting the command from the GSocket the connection
170 * with the client will be closed and removed from the ConnectionManager.
171 * Additionally the function will return FALSE and the GSource will no longer
172 * monitor the GSocket for the G_IO_IN condition.
173 */
174 gboolean
command_source_on_input_ready(GInputStream * istream,gpointer user_data)175 command_source_on_input_ready (GInputStream *istream,
176 gpointer user_data)
177 {
178 source_data_t *data = (source_data_t*)user_data;
179 Connection *connection;
180 Tpm2Command *command;
181 TPMA_CC attributes = { 0 };
182 uint8_t *buf;
183 size_t buf_size;
184
185 g_debug (__func__);
186 connection =
187 connection_manager_lookup_istream (data->self->connection_manager,
188 istream);
189 if (connection == NULL) {
190 g_error ("%s: failed to get connection associated with istream",
191 __func__);
192 }
193 buf = read_tpm_buffer_alloc (istream, &buf_size);
194 if (buf == NULL) {
195 goto fail_out;
196 }
197 attributes = command_attrs_from_cc (data->self->command_attrs,
198 get_command_code (buf));
199 command = tpm2_command_new (connection, buf, buf_size, attributes);
200 if (command != NULL) {
201 sink_enqueue (data->self->sink, G_OBJECT (command));
202 /* the sink now owns this message */
203 g_object_unref (command);
204 } else {
205 goto fail_out;
206 }
207 g_object_unref (connection);
208 return G_SOURCE_CONTINUE;
209 fail_out:
210 if (buf != NULL) {
211 g_free (buf);
212 }
213 g_debug ("%s: removing connection from connection_manager", __func__);
214 connection_manager_remove (data->self->connection_manager,
215 connection);
216 ControlMessage *msg =
217 control_message_new_with_object (CONNECTION_REMOVED,
218 G_OBJECT (connection));
219 sink_enqueue (data->self->sink, G_OBJECT (msg));
220 g_object_unref (msg);
221 g_object_unref (connection);
222 /*
223 * Remove data from hash table which includes the GCancellable associated
224 * with the G_IN_IO condition source. Don't call the cancellable though
225 * since we're letting this source die at the end of this function
226 * (returning FALSE).
227 */
228 g_debug ("%s: removing GCancellable", __func__);
229 g_hash_table_remove (data->self->istream_to_source_data_map, istream);
230 return G_SOURCE_REMOVE;
231 }
232 /*
233 * This is a callback function invoked by the ConnectionManager when a new
234 * Connection object is added to it. It creates and sets up the GIO
235 * machinery needed to monitor the Connection for I/O events.
236 */
237 gint
command_source_on_new_connection(ConnectionManager * connection_manager,Connection * connection,CommandSource * self)238 command_source_on_new_connection (ConnectionManager *connection_manager,
239 Connection *connection,
240 CommandSource *self)
241 {
242 GIOStream *iostream;
243 GPollableInputStream *istream;
244 source_data_t *data;
245 UNUSED_PARAM(connection_manager);
246
247 g_info ("%s: adding new connection", __func__);
248 /*
249 * Take reference to socket, will be freed when the source_data_t
250 * structure is freed
251 */
252 iostream = connection_get_iostream (connection);
253 istream = G_POLLABLE_INPUT_STREAM (g_io_stream_get_input_stream (iostream));
254 g_object_ref (istream);
255 data = g_malloc0 (sizeof (source_data_t));
256 data->cancellable = g_cancellable_new ();
257 data->source = g_pollable_input_stream_create_source (istream,
258 data->cancellable);
259 /* we ignore the ID returned since we keep a reference to the source around */
260 g_source_attach (data->source, self->main_context);
261 data->self = self;
262 g_source_set_callback (data->source,
263 G_SOURCE_FUNC (command_source_on_input_ready),
264 data,
265 NULL);
266 /*
267 * To stop watching this socket for G_IO_IN condition use this GHashTable
268 * to look up the GCancellable object. The hash table takes ownership of
269 * the reference to the istream and the source_data_t pointer.
270 */
271 g_hash_table_insert (self->istream_to_source_data_map, istream, data);
272
273 return 0;
274 }
275 /*
276 * callback for iterating over objects in the member socket_to_source_data_map
277 * GHashMap to kill off the GSource. This requires cancelling it, and then
278 * calling the GSource destroy function. This should only happen when the
279 * CommandSource object is destroyed.
280 */
281 static void
command_source_source_cancel(gpointer key,gpointer value,gpointer user_data)282 command_source_source_cancel (gpointer key,
283 gpointer value,
284 gpointer user_data)
285 {
286 UNUSED_PARAM(key);
287 UNUSED_PARAM(user_data);
288 g_debug ("%s", __func__);
289 source_data_t *data = (source_data_t*)value;
290
291 g_debug ("%s: canceling cancellable and destroying source", __func__);
292 g_cancellable_cancel (data->cancellable);
293 }
294 /*
295 * GObject dispose function. It's used to unref / release all GObjects held
296 * by the CommandSource before chaining up to the parent.
297 */
298 static void
command_source_dispose(GObject * object)299 command_source_dispose (GObject *object) {
300 CommandSource *self = COMMAND_SOURCE (object);
301
302 g_clear_object (&self->sink);
303 g_clear_object (&self->connection_manager);
304 g_clear_object (&self->command_attrs);
305 /* cancel all outstanding G_IO_IN condition GSources and destroy them */
306 if (self->istream_to_source_data_map != NULL) {
307 g_hash_table_foreach (self->istream_to_source_data_map,
308 command_source_source_cancel,
309 NULL);
310 }
311 g_clear_pointer (&self->istream_to_source_data_map, g_hash_table_unref);
312 if (self->main_loop != NULL && g_main_loop_is_running (self->main_loop)) {
313 g_main_loop_quit (self->main_loop);
314 }
315 g_clear_pointer (&self->main_loop, g_main_loop_unref);
316 g_clear_pointer (&self->main_context, g_main_context_unref);
317 G_OBJECT_CLASS (command_source_parent_class)->dispose (object);
318 }
319
320 /*
321 * GObject finalize function releases all resources not freed in 'dispose'
322 * & chain up to parent.
323 */
324 static void
command_source_finalize(GObject * object)325 command_source_finalize (GObject *object)
326 {
327 G_OBJECT_CLASS (command_source_parent_class)->finalize (object);
328 }
329 /*
330 * Cause the GMainLoop to stop monitoring whatever GSources are attached to
331 * it and return
332 */
333 static void
command_source_unblock(Thread * self)334 command_source_unblock (Thread *self)
335 {
336 CommandSource *source = COMMAND_SOURCE (self);
337 g_main_loop_quit (source->main_loop);
338 }
339 /*
340 * This function creates it's very own GMainLoop thread. This is used to
341 * monitor client connections for incoming data (TPM2 command buffers).
342 */
343 void*
command_source_thread(void * data)344 command_source_thread (void *data)
345 {
346 CommandSource *source;
347
348 g_assert (data != NULL);
349 source = COMMAND_SOURCE (data);
350 g_assert (source->main_loop != NULL);
351
352 if (!g_main_loop_is_running (source->main_loop)) {
353 g_main_loop_run (source->main_loop);
354 }
355
356 return NULL;
357 }
358
359 static void
command_source_class_init(CommandSourceClass * klass)360 command_source_class_init (CommandSourceClass *klass)
361 {
362 GObjectClass *object_class = G_OBJECT_CLASS (klass);
363 ThreadClass *thread_class = THREAD_CLASS (klass);
364
365 g_debug ("command_source_class_init");
366 if (command_source_parent_class == NULL)
367 command_source_parent_class = g_type_class_peek_parent (klass);
368
369 object_class->dispose = command_source_dispose;
370 object_class->finalize = command_source_finalize;
371 object_class->get_property = command_source_get_property;
372 object_class->set_property = command_source_set_property;
373 thread_class->thread_run = command_source_thread;
374 thread_class->thread_unblock = command_source_unblock;
375
376 obj_properties [PROP_COMMAND_ATTRS] =
377 g_param_spec_object ("command-attrs",
378 "CommandAttrs object",
379 "CommandAttrs instance.",
380 TYPE_COMMAND_ATTRS,
381 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
382 obj_properties [PROP_CONNECTION_MANAGER] =
383 g_param_spec_object ("connection-manager",
384 "ConnectionManager object",
385 "ConnectionManager instance.",
386 TYPE_CONNECTION_MANAGER,
387 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
388 obj_properties [PROP_SINK] =
389 g_param_spec_object ("sink",
390 "Sink",
391 "Reference to a Sink object.",
392 G_TYPE_OBJECT,
393 G_PARAM_READWRITE);
394 g_object_class_install_properties (object_class,
395 N_PROPERTIES,
396 obj_properties);
397 }
398 CommandSource*
command_source_new(ConnectionManager * connection_manager,CommandAttrs * command_attrs)399 command_source_new (ConnectionManager *connection_manager,
400 CommandAttrs *command_attrs)
401 {
402 CommandSource *source;
403
404 if (connection_manager == NULL)
405 g_error ("command_source_new passed NULL ConnectionManager");
406 g_object_ref (connection_manager);
407 source = COMMAND_SOURCE (g_object_new (TYPE_COMMAND_SOURCE,
408 "command-attrs", command_attrs,
409 "connection-manager", connection_manager,
410 NULL));
411 g_signal_connect (connection_manager,
412 "new-connection",
413 (GCallback) command_source_on_new_connection,
414 source);
415 return source;
416 }
417