Initial version

very hardcoded, but great for demonstrations ig.
master
LEdoian 2 weeks ago
commit 09648a0b71

10
.gitignore vendored

@ -0,0 +1,10 @@
# compilation artifacts
*.o
wl_unlocker
# autogenerated by wayland-scanner
session-lock.h
session-lock.c
.*
!.gitignore

@ -0,0 +1,14 @@
# FIXME: use pkgconf --libs wayland-client
CFLAGS:=-lwayland
LDFLAGS:=-lwayland-client
wl_unlocker: unlocker.o session-lock.o
gcc $(LDFLAGS) unlocker.o session-lock.o -o wl_unlocker
unlocker.o: unlocker.c session-lock.h
session-lock.h:
# FIXME: don't hardcode path!
wayland-scanner client-header /usr/share/wayland-protocols/staging/ext-session-lock/ext-session-lock-v1.xml session-lock.h
session-lock.c:
wayland-scanner private-code /usr/share/wayland-protocols/staging/ext-session-lock/ext-session-lock-v1.xml session-lock.c

@ -0,0 +1,35 @@
A simple wayland unlocker
====
Two goals: learn how to use wayland protocols on the low level, and have a tool
to recover a locked session when the original locker is killed (when a shell is
available and *the compositor's policy* allows that).
I might use this as a demonstration project, in that case more thorough docs
might emerge…
Security
----
This might under certain circumstances undermine the security model of the
compositor, because whoever is able to run this might unlock the session. Use
and install with that knowledge.
However, if someone has `rw` access to the compositor's socket, they can do the
same nevertheless, so in a regular system this is probably a non-issue.
That all said, use at your own risk, I am not responsible for your fails :-)
Building
--------
TODO
Licence
-------
GPL v2 only
Improvements, patches, comments, feedback, praise, …
--------
→ [wl\_unlocker@pokemon.ledoian.cz](mailto:wl_unlocker@pokemon.ledoian.cz)

@ -0,0 +1,120 @@
// Just random stdlib (and POSIX) so I don't have to think about these
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <sys/mman.h>
// Wayland includes
#include "wayland-client.h"
#include "session-lock.h"
#define LOCK_MANAGER_NAME "ext_session_lock_manager_v1"
// global state
struct wl_display * wl = NULL;
struct wl_registry * reg = NULL;
struct ext_session_lock_manager_v1 * lockmgr = NULL;
struct ext_session_lock_v1 * lock = NULL;
enum lock_state {LOCKED, FINISHED, UNSET} lock_state = UNSET;
static void registry_global_handler(void * data, struct wl_registry * wl_registry, uint32_t name, const char * interface, uint32_t version) {
printf("UwU, iface %s (name %d) appeared!\n", interface, name);
if (strcmp(interface, LOCK_MANAGER_NAME) == 0) {
// fire the bind outright
lockmgr = wl_registry_bind(wl_registry, name, &ext_session_lock_manager_v1_interface, 1/*version, we don't know anything newer*/);
}
}
static void registry_global_remove_handler(void * data, struct wl_registry * wl_registry, uint32_t name) {
printf("OwO, iface %d disappeared, should destroy!\n", name);
}
static void callback_done_handler(void * data, struct wl_callback * wl_callback, uint32_t callback_data) {
printf("Heh, callback done!\n");
}
static void lock_locked_handler(void * data, struct ext_session_lock_v1 * lock) {
enum lock_state * state = (enum lock_state *)data;
*state = LOCKED;
}
static void lock_finished_handler(void * data, struct ext_session_lock_v1 * lock) {
enum lock_state * state = (enum lock_state *)data;
*state = FINISHED;
}
int main(void) {
// get wl_display, the core object
wl = wl_display_connect(NULL);
// prepare listeners for wl_registry.global
struct wl_registry_listener reg_listener = {
.global = &registry_global_handler,
.global_remove = &registry_global_remove_handler,
};
reg = wl_display_get_registry(wl);
wl_registry_add_listener(reg, &reg_listener, NULL);
// add the barrier to the end
struct wl_callback * cbk = wl_display_sync(wl);
struct wl_callback_listener cbk_l = {
.done = &callback_done_handler,
};
wl_callback_add_listener(cbk, &cbk_l, NULL);
// process the queue
wl_display_dispatch(wl);
if (lockmgr == NULL) {
fprintf(stderr, "No support for un/locking, no fun.\n");
return 1;
}
lock = ext_session_lock_manager_v1_lock(lockmgr);
struct ext_session_lock_v1_listener lock_l = {
.locked = &lock_locked_handler,
.finished = &lock_finished_handler,
};
ext_session_lock_v1_add_listener(lock, &lock_l, &lock_state);
// process the queue
wl_display_dispatch(wl);
if (lock_state == UNSET) {
fprintf(stderr, "BUG!\n");
return 1;
} else if (lock_state == FINISHED) {
printf("Not locked.\n");
// nothing to do, just destroy stuff
ext_session_lock_v1_destroy(lock);
} else if (lock_state == LOCKED) {
printf("Unlocking…\n");
ext_session_lock_v1_unlock_and_destroy(lock);
} else {
fprintf(stderr, "DAFUQ?\n");
return 1;
}
// just for completeness: destroy the objects we created. Also, set NULL for safety.
printf("Cleaning up…\n");
// lock is destroyed already
lock = NULL;
ext_session_lock_manager_v1_destroy(lockmgr);
lockmgr = NULL;
wl_registry_destroy(reg);
reg = NULL;
// Display is special, that is diconnected and not destroyed.
// Also, make the roundtrip beforehand
// FIXME: is wl_display_roundtrip the thing we want? What does it return?
wl_display_roundtrip(wl);
wl_display_disconnect(wl);
wl = NULL;
printf("Done lol\n");
return 0;
}
Loading…
Cancel
Save