From de00067fd1907aab7e00a9582f60a360f75bd261 Mon Sep 17 00:00:00 2001 From: hippoz <10706925-hippoz@users.noreply.gitlab.com> Date: Tue, 3 Jan 2023 19:06:44 +0200 Subject: [PATCH] fixes --- server.c | 114 +++++++++++++++++++++++++++++++++++++------------------ wire.c | 18 ++++++++- 2 files changed, 94 insertions(+), 38 deletions(-) diff --git a/server.c b/server.c index 5a7ed43..5035cac 100644 --- a/server.c +++ b/server.c @@ -1,3 +1,5 @@ +#define _GNU_SOURCE 1 + #include #include #include @@ -130,7 +132,7 @@ int jb_server_client_assign_unique_name(struct jb_server *s, int i) return -1; } - if (snprintf(name, 16, ":%"PRIu32, id) < 0) { + if (snprintf(name, 16, ":1.%"PRIu32, id) < 0) { return -1; } @@ -241,8 +243,10 @@ int jb_server_broadcast_message(struct jb_server *s, wire_message_t *msg, wire_c .data_len = 4096, }; + uint32_t previous_cursor = ctx->byte_cursor; TRYST(wire_compose_unicast_reply(&reply_ctx, ctx, msg, sender_unique_name)); TRYST(send(c->fd, reply_data, reply_ctx.byte_cursor, 0)); + ctx->byte_cursor = previous_cursor; } } } @@ -293,23 +297,18 @@ int jb_server_unicast_message(struct jb_server *s, wire_message_t *msg, wire_con } \ } while(0) \ -int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, size_t data_len) +int jb_server_client_process_message(struct jb_server *s, int i, wire_context_t *ctx) { struct jb_client *client = &s->clients[i]; wire_message_t msg = {0}; - wire_context_t ctx = { - .byte_cursor = 0, - .data = data, - .data_len = data_len, - }; - if (wire_parse_message(&ctx, &msg) < 0) { + if (wire_parse_message(ctx, &msg) < 0) { printf("parsing failed\n"); return -1; } - printf("process_message: processed %d/%zu bytes\n", ctx.byte_cursor, data_len); + printf("process_message: processed %d/%zu bytes\n", ctx->byte_cursor, ctx->data_len); wire_message_field_t *destination_field = &msg.fields[DBUS_HEADER_FIELD_DESTINATION]; wire_message_field_t *member_field = &msg.fields[DBUS_HEADER_FIELD_MEMBER]; @@ -356,7 +355,7 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, printf("assigned unique name '%s' to connection %d\n", s->names[unique_name_index].name, i); } else if (strcmp(member, "RequestName") == 0) { - char *name = TRYPTR(wire_get_string(&ctx)); + char *name = TRYPTR(wire_get_string(ctx)); int name_len = strlen(name); if (name_len < 1 || name_len > 256) { return -1; @@ -380,7 +379,7 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, printf("client '%s' (index=%d) now owns name '%s'\n", s->names[client->unique_name_index].name, i, name_str); } } else if (strcmp(member, "GetNameOwner") == 0) { - char *name = TRYPTR(wire_get_string(&ctx)); + char *name = TRYPTR(wire_get_string(ctx)); int name_len = strlen(name); if (name_len < 1 || name_len > 256) { return -1; @@ -396,7 +395,7 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, TRYPTR(wire_set_string(&reply_ctx, s->names[target->unique_name_index].name)); } _reply_end() } else if (strcmp(member, "NameHasOwner") == 0) { - char *name = TRYPTR(wire_get_string(&ctx)); + char *name = TRYPTR(wire_get_string(ctx)); int name_len = strlen(name); if (name_len < 1 || name_len > 256) { return -1; @@ -440,32 +439,21 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, } else if (strcmp(member, "StartServiceByName") == 0) { // TODO: stub (does nothing and always returns success) - char *name = TRYPTR(wire_get_string(&ctx)); + char *name = TRYPTR(wire_get_string(ctx)); int name_len = strlen(name); if (name_len < 1 || name_len > 256) { return -1; } /* unused flags value */ - TRYPTR(wire_get_u32(&ctx)); + TRYPTR(wire_get_u32(ctx)); printf("FIXME: STUB: StartServiceByName: %s\n", name); _reply_begin("u") { TRYPTR(wire_set_u32(&reply_ctx, 1)); } _reply_end() - } else if (strcmp(member, "GetConnectionUnixProcessID") == 0) { - // TODO: stub (returns an error) - char *name = TRYPTR(wire_get_string(&ctx)); - int name_len = strlen(name); - if (name_len < 1 || name_len > 256) { - return -1; - } - - printf("FIXME: STUB: GetConnectionUnixProcessID: %s\n", name); - - _reply_error("xyz.hippoz.jitterbug.NotImplemented"); } else if (strcmp(member, "AddMatch") == 0) { - char *match = TRYPTR(wire_get_string(&ctx)); + char *match = TRYPTR(wire_get_string(ctx)); int match_len = strlen(match); if (match_len < 1 || match_len > MATCH_RULE_MAX) { return -1; @@ -479,7 +467,7 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, } else if (strcmp(member, "RemoveMatch") == 0) { // TODO: stub (does nothing and always returns success) - char *match = TRYPTR(wire_get_string(&ctx)); + char *match = TRYPTR(wire_get_string(ctx)); int match_len = strlen(match); if (match_len < 1 || match_len > MATCH_RULE_MAX) { return -1; @@ -488,6 +476,39 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, printf("FIXME: STUB: RemoveMatch: %s\n", match); _reply_begin("") {} _reply_end() + } else if (strcmp(member, "GetConnectionStats") == 0) { + // TODO: stub (always returns empty array) + printf("FIXME: STUB: GetConnectionStats\n"); + + _reply_begin("as") { + TRYPTR(wire_set_u32(&reply_ctx, 0)); + // empty arrays still need to align + TRYPTR(wire_write_align(&reply_ctx, 8)); + } _reply_end() + } else if (strcmp(member, "GetConnectionUnixProcessID") == 0) { + char *name = TRYPTR(wire_get_string(ctx)); + int name_len = strlen(name); + if (name_len < 1 || name_len > 256) { + return -1; + } + + struct jb_client *target = jb_server_name_find_client(s, name); + if (!target || target->unique_name_index < 0 || target->fd < 0) { + _reply_error("org.freedesktop.DBus.Error.NameHasNoOwner"); + return 0; + } + + struct ucred cred; + socklen_t len = sizeof(struct ucred); + + if (getsockopt(target->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1) { + _reply_error("xyz.hippoz.jitterbug.FailedToGetPID"); + return 0; + } + + _reply_begin("u") { + TRYPTR(wire_set_u32(&reply_ctx, cred.pid)); + } _reply_end() } else if (strcmp(member, "GetAllMatchRules") == 0) { _reply_begin("a{sas}") { uint32_t *outer_array_len = TRYPTR(wire_set_u32(&reply_ctx, 0)); @@ -534,8 +555,10 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, } break; case DBUS_MESSAGE_METHOD_RETURN: { + // we assume that method returns without any destination field are directed at their sender + // TODO: this is probably not correct if (!destination_field->present) { - return -1; + destination_field->t.str = s->names[client->unique_name_index].name; } should_forward = true; @@ -557,22 +580,41 @@ int jb_server_client_process_message(struct jb_server *s, int i, uint8_t *data, } if (destination_field->present) { /* unicast */ - if (jb_server_unicast_message(s, &msg, &ctx, destination_field->t.str, s->names[client->unique_name_index].name) < 0) { + if (jb_server_unicast_message(s, &msg, ctx, destination_field->t.str, s->names[client->unique_name_index].name) < 0) { _reply_error("xyz.hippoz.jitterbug.UnicastFailed"); return 0; } } else { /* broadcast */ - if (jb_server_broadcast_message(s, &msg, &ctx, s->names[client->unique_name_index].name) < 0) { + if (jb_server_broadcast_message(s, &msg, ctx, s->names[client->unique_name_index].name) < 0) { _reply_error("xyz.hippoz.jitterbug.BroadcastFailed"); return 0; } } } - if (ctx.byte_cursor < ctx.data_len && ctx.data[ctx.byte_cursor] == 'l') { - // another message - TRYST(jb_server_client_process_message(s, i, ctx.data + ctx.byte_cursor, ctx.data_len - ctx.byte_cursor)); + return 0; +} + +int jb_server_client_drain_messages(struct jb_server *s, int ci, uint8_t *data, uint32_t data_len) +{ + wire_context_t ctx = { + .byte_cursor = 0, + .data = data, + .data_len = data_len + }; + + TRYST(jb_server_client_process_message(s, ci, &ctx)); + + for (int i = 0; i < 10; i++) { + if (ctx.byte_cursor >= ctx.data_len || ctx.data[ctx.byte_cursor] != 'l') { + // no more messages + break; + } + ctx.data = ctx.data + ctx.byte_cursor; + ctx.data_len = ctx.data_len - ctx.byte_cursor; + ctx.byte_cursor = 0; + TRYST(jb_server_client_process_message(s, ci, &ctx)); } return 0; @@ -655,7 +697,7 @@ int jb_server_turn(struct jb_server *s) static const char auth_ok[] = "OK aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\r\n"; static const char auth_list[] = "REJECTED EXTERNAL\r\n"; static const char auth_data[] = "DATA\r\n"; - static const int data_buffer_len = 4096; + static const int data_buffer_len = 8192; // We can keep a padding of null bytes for the data buffer. In the event that, for // example, a string function is called on a char array without a proper ending null @@ -752,7 +794,7 @@ int jb_server_turn(struct jb_server *s) char *first_message_begin = data + 7; /* 7 = length of "BEGIN\r\n" */ if (*first_message_begin == 'l' || *first_message_begin == 'B') { // This looks like a D-Bus message. Let's process it! - if (jb_server_client_process_message(s, i, (uint8_t *)first_message_begin, data_buffer_len - 7) < 0) { + if (jb_server_client_drain_messages(s, i, (uint8_t *)first_message_begin, data_buffer_len - 7) < 0) { _client_die("failed to process message"); } } @@ -765,7 +807,7 @@ int jb_server_turn(struct jb_server *s) } break; case JB_CLIENT_STATE_READY: { - if (jb_server_client_process_message(s, i, (uint8_t*)data, data_buffer_len) < 0) { + if (jb_server_client_drain_messages(s, i, (uint8_t*)data, data_buffer_len) < 0) { _client_die("failed to process message"); } } break; diff --git a/wire.c b/wire.c index c0df1d5..b471d46 100644 --- a/wire.c +++ b/wire.c @@ -182,6 +182,20 @@ int wire_compose_reply(wire_context_t *c, wire_message_t *msg, const char *signa /* header fields */ { + /* SENDER */ + { + /* byte (field code) */ + TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SENDER)); + /* variant */ + /* signature */ + TRYPTR(wire_set_signature(c, "s")); + /* string */ + TRYPTR(wire_set_string(c, "org.freedesktop.DBus")); + + // need to align to 8 byte boundry after each array element? + TRYPTR(wire_write_align(c, 8)); + } + /* SIGNATURE */ { /* byte (field code) */ @@ -336,7 +350,7 @@ int wire_compose_unicast_reply(wire_context_t *c, wire_context_t *msg_c, wire_me if (signature_field->present) { TRYPTR(wire_set_u8(c, DBUS_HEADER_FIELD_SIGNATURE)); TRYPTR(wire_set_signature(c, "g")); - TRYPTR(wire_set_string(c, signature_field->t.str)); + TRYPTR(wire_set_signature(c, signature_field->t.str)); TRYPTR(wire_write_align(c, 8)); } @@ -356,7 +370,7 @@ int wire_compose_unicast_reply(wire_context_t *c, wire_context_t *msg_c, wire_me // header ends on an 8 byte alignment TRYPTR(wire_write_align(c, 8)); - if (c->byte_cursor + msg->body_length > c->data_len) { + if (c->byte_cursor + msg->body_length >= c->data_len || msg_c->byte_cursor + msg->body_length >= msg_c->data_len) { return -1; }