commit
09648a0b71
@ -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 = ®istry_global_handler,
|
||||
.global_remove = ®istry_global_remove_handler,
|
||||
};
|
||||
reg = wl_display_get_registry(wl);
|
||||
wl_registry_add_listener(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…
Reference in New Issue