Merge pull request #1 from IoIxD/idk
support launching into wayland sessions, set xdg vars, visually show errors upon pam errors.
This commit is contained in:
commit
fa4bff56c9
4 changed files with 189 additions and 70 deletions
155
mdm/login.c
155
mdm/login.c
|
|
@ -1,20 +1,26 @@
|
||||||
#include "mdm.h"
|
#include "mdm.h"
|
||||||
|
|
||||||
#include <ini.h>
|
#include <ini.h>
|
||||||
|
#include <sched.h>
|
||||||
|
#include <security/_pam_types.h>
|
||||||
#include <security/pam_appl.h>
|
#include <security/pam_appl.h>
|
||||||
#include <stb_ds.h>
|
#include <stb_ds.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
MwWidget root;
|
MwWidget root;
|
||||||
MwWidget window, sesscombo, usercombo, passentry;
|
MwWidget window, sesscombo, usercombo, passentry, error;
|
||||||
|
|
||||||
typedef struct session {
|
typedef struct session {
|
||||||
char* key;
|
char* key;
|
||||||
char* value;
|
session_environment_t* value;
|
||||||
} session_t;
|
} session_t;
|
||||||
|
|
||||||
session_t* sessions = NULL;
|
session_t* sessions = NULL;
|
||||||
char* name_line;
|
char* name_line = NULL;
|
||||||
char* exec_line;
|
char* try_exec_line = NULL;
|
||||||
|
char* exec_line = NULL;
|
||||||
|
char* desktop_names_line = NULL;
|
||||||
|
|
||||||
static void add_user(const char* name, void* user) {
|
static void add_user(const char* name, void* user) {
|
||||||
MwComboBoxAdd(user, -1, name);
|
MwComboBoxAdd(user, -1, name);
|
||||||
|
|
@ -25,42 +31,61 @@ static int dumper(void* user, const char* section, const char* name, const char*
|
||||||
|
|
||||||
if(strcmp(name, "Name") == 0) {
|
if(strcmp(name, "Name") == 0) {
|
||||||
name_line = MDEStringDuplicate(value);
|
name_line = MDEStringDuplicate(value);
|
||||||
|
} else if(strcmp(name, "TryExec") == 0) {
|
||||||
|
try_exec_line = MDEStringDuplicate(value);
|
||||||
} else if(strcmp(name, "Exec") == 0) {
|
} else if(strcmp(name, "Exec") == 0) {
|
||||||
exec_line = MDEStringDuplicate(value);
|
exec_line = MDEStringDuplicate(value);
|
||||||
|
} else if(strcmp(name, "DesktopNames") == 0) {
|
||||||
|
desktop_names_line = MDEStringDuplicate(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_session(const char* path, int dir, int symlink, void* user) {
|
static void add_session(session_type_t session_type, const char* path, int dir, int symlink, void* user) {
|
||||||
int m = 1;
|
int m = 1;
|
||||||
|
session_environment_t* value = malloc(sizeof(session_environment_t));
|
||||||
|
|
||||||
|
name_line = NULL;
|
||||||
|
exec_line = NULL;
|
||||||
|
try_exec_line = NULL;
|
||||||
|
desktop_names_line = NULL;
|
||||||
|
|
||||||
name_line = NULL;
|
|
||||||
exec_line = NULL;
|
|
||||||
|
|
||||||
if(dir || symlink) return;
|
if(dir || symlink) return;
|
||||||
|
|
||||||
ini_parse(path, dumper, user);
|
ini_parse(path, dumper, user);
|
||||||
|
|
||||||
if(name_line != NULL && exec_line != NULL) {
|
if(name_line != NULL && (exec_line != NULL || try_exec_line != NULL)) {
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < shlen(sessions); i++){
|
for(i = 0; i < shlen(sessions); i++) {
|
||||||
if(strcmp(sessions[i].key, name_line) == 0) break;
|
if(strcmp(sessions[i].key, name_line) == 0) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i == shlen(sessions)){
|
if(i == shlen(sessions)) {
|
||||||
MwComboBoxAdd(user, -1, name_line);
|
MwComboBoxAdd(user, -1, name_line);
|
||||||
|
|
||||||
shput(sessions, name_line, exec_line);
|
value->run = exec_line;
|
||||||
|
value->try_run = try_exec_line;
|
||||||
|
value->session_type = session_type;
|
||||||
|
value->desktop_names = desktop_names_line;
|
||||||
|
shput(sessions, name_line, value);
|
||||||
|
|
||||||
m = 0;
|
m = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(name_line != NULL) free(name_line);
|
if(name_line != NULL) free(name_line);
|
||||||
|
if(desktop_names_line != NULL) free(desktop_names_line);
|
||||||
|
if(m && try_exec_line != NULL) free(try_exec_line);
|
||||||
if(m && exec_line != NULL) free(exec_line);
|
if(m && exec_line != NULL) free(exec_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void add_session_x(const char* path, int dir, int symlink, void* user) {
|
||||||
|
add_session(MDM_SESSION_TYPE_X, path, dir, symlink, user);
|
||||||
|
}
|
||||||
|
static void add_session_wayland(const char* path, int dir, int symlink, void* user) {
|
||||||
|
add_session(MDM_SESSION_TYPE_WAYLAND, path, dir, symlink, user);
|
||||||
|
}
|
||||||
static int conversation(int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata) {
|
static int conversation(int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
@ -82,53 +107,85 @@ static int conversation(int num_msg, const struct pam_message** msg, struct pam_
|
||||||
}
|
}
|
||||||
|
|
||||||
static void try_login(MwWidget handle, void* user, void* client) {
|
static void try_login(MwWidget handle, void* user, void* client) {
|
||||||
const char* username = MwComboBoxGet(usercombo, MwGetInteger(usercombo, MwNvalue));
|
const char* username;
|
||||||
struct pam_conv conv = {conversation, NULL};
|
const char* place;
|
||||||
|
struct pam_conv conv;
|
||||||
pam_handle_t* pam;
|
pam_handle_t* pam;
|
||||||
|
int err;
|
||||||
|
int err2;
|
||||||
int ret;
|
int ret;
|
||||||
jmp_buf cleanup;
|
char err_str[255];
|
||||||
int err = 1;
|
int print_error = 0;
|
||||||
|
int i, n;
|
||||||
|
|
||||||
|
username = MwComboBoxGet(usercombo, MwGetInteger(usercombo, MwNvalue));
|
||||||
|
conv.conv = conversation;
|
||||||
|
conv.appdata_ptr = NULL;
|
||||||
|
err = 1;
|
||||||
|
|
||||||
(void)handle;
|
(void)handle;
|
||||||
(void)user;
|
(void)user;
|
||||||
(void)client;
|
(void)client;
|
||||||
|
|
||||||
if(setjmp(cleanup)) {
|
|
||||||
pam_end(pam, 0);
|
|
||||||
|
|
||||||
if(err) {
|
|
||||||
MwSetText(passentry, MwNtext, "");
|
|
||||||
} else {
|
|
||||||
struct passwd* pwd = getpwnam(username);
|
|
||||||
const char* session = MwComboBoxGet(sesscombo, MwGetInteger(sesscombo, MwNvalue));
|
|
||||||
|
|
||||||
uid = pwd->pw_uid;
|
|
||||||
gid = pwd->pw_gid;
|
|
||||||
run = shget(sessions, session);
|
|
||||||
|
|
||||||
MwDestroyWidget(root);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = pam_start("mdm", username, &conv, &pam);
|
ret = pam_start("mdm", username, &conv, &pam);
|
||||||
if(ret != PAM_SUCCESS) {
|
if(ret != PAM_SUCCESS) {
|
||||||
longjmp(cleanup, 1);
|
place = "Error calling pam_start";
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = pam_authenticate(pam, 0);
|
ret = pam_authenticate(pam, 0);
|
||||||
if(ret != PAM_SUCCESS) {
|
if(ret != PAM_SUCCESS) {
|
||||||
longjmp(cleanup, 1);
|
place = "Error calling pam_authenticate";
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = pam_acct_mgmt(pam, 0);
|
ret = pam_acct_mgmt(pam, 0);
|
||||||
if(ret != PAM_SUCCESS) {
|
if(ret != PAM_SUCCESS) {
|
||||||
longjmp(cleanup, 1);
|
place = "Error calling pam_acct_mgmt";
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = 0;
|
ret = pam_open_session(pam, 0);
|
||||||
longjmp(cleanup, 1);
|
if(ret != PAM_SUCCESS) {
|
||||||
|
place = "Error calling pam_open_session";
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
cleanup:
|
||||||
|
pam_close_session(pam, 0);
|
||||||
|
|
||||||
|
// if pam_end fails but we have another error, we care more about the error at hand
|
||||||
|
// then whether pam successfully ended.
|
||||||
|
err2 = pam_end(pam, 0);
|
||||||
|
|
||||||
|
if(err && ret != PAM_SUCCESS) {
|
||||||
|
MwSetText(passentry, MwNtext, "");
|
||||||
|
snprintf(err_str, 255, "%s: %s", place, pam_strerror(pam, err));
|
||||||
|
print_error = 1;
|
||||||
|
} else if(err2) {
|
||||||
|
MwSetText(passentry, MwNtext, "");
|
||||||
|
snprintf(err_str, 255, "Error calling pam_end: %s", pam_strerror(pam, err2));
|
||||||
|
print_error = 1;
|
||||||
|
}
|
||||||
|
if(print_error) {
|
||||||
|
n = 0;
|
||||||
|
for(i = 0; err_str[i] != '\0' && i <= 255; i++ && n++) {
|
||||||
|
if(err_str[i] == ' ' && n >= 40) {
|
||||||
|
err_str[i] = '\n';
|
||||||
|
n = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MwSetText(error, MwNtext, err_str);
|
||||||
|
} else {
|
||||||
|
printf("Logging in as %s\n", username);
|
||||||
|
struct passwd* pwd = getpwnam(username);
|
||||||
|
const char* session = MwComboBoxGet(sesscombo, MwGetInteger(sesscombo, MwNvalue));
|
||||||
|
|
||||||
|
uid = pwd->pw_uid;
|
||||||
|
gid = pwd->pw_gid;
|
||||||
|
env = shget(sessions, session);
|
||||||
|
|
||||||
|
MwDestroyWidget(root);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void login_window(void) {
|
void login_window(void) {
|
||||||
|
|
@ -143,7 +200,7 @@ void login_window(void) {
|
||||||
|
|
||||||
root = MwCreateWidget(NULL, "root", NULL, 0, 0, 0, 0);
|
root = MwCreateWidget(NULL, "root", NULL, 0, 0, 0, 0);
|
||||||
|
|
||||||
window = MwVaCreateWidget(MwWindowClass, "login", root, (x_width() - 366) / 2, (x_height() - 183) / 2, 366, 183,
|
window = MwVaCreateWidget(MwWindowClass, "login", root, (x_width() - 366) / 2, (x_height() - 200) / 2, 366, 250,
|
||||||
MwNtitle, "login",
|
MwNtitle, "login",
|
||||||
NULL);
|
NULL);
|
||||||
p = config_picture == NULL ? NULL : MwLoadImage(window, config_picture);
|
p = config_picture == NULL ? NULL : MwLoadImage(window, config_picture);
|
||||||
|
|
@ -179,7 +236,7 @@ void login_window(void) {
|
||||||
ok = MwVaCreateWidget(MwButtonClass, "ok", window, 366 - 10 - 60, 10 + 137 + 10, 60, 18,
|
ok = MwVaCreateWidget(MwButtonClass, "ok", window, 366 - 10 - 60, 10 + 137 + 10, 60, 18,
|
||||||
MwNtext, "OK",
|
MwNtext, "OK",
|
||||||
NULL);
|
NULL);
|
||||||
|
error = MwVaCreateWidget(MwLabelClass, "error", window, 10, 10 + 137 + 10 + 20, 366, 48, NULL);
|
||||||
if(p != NULL) MwVaApply(pic, MwNpixmap, p, NULL);
|
if(p != NULL) MwVaApply(pic, MwNpixmap, p, NULL);
|
||||||
|
|
||||||
MwAddUserHandler(ok, MwNactivateHandler, try_login, NULL);
|
MwAddUserHandler(ok, MwNactivateHandler, try_login, NULL);
|
||||||
|
|
@ -193,8 +250,10 @@ void login_window(void) {
|
||||||
shfree(sessions);
|
shfree(sessions);
|
||||||
sh_new_strdup(sessions);
|
sh_new_strdup(sessions);
|
||||||
shdefault(sessions, NULL);
|
shdefault(sessions, NULL);
|
||||||
MDEDirectoryScan(DATADIR "/xsessions", add_session, sesscombo);
|
MDEDirectoryScan(DATADIR "/xsessions", add_session_x, sesscombo);
|
||||||
MDEDirectoryScan("/usr/share/xsessions", add_session, sesscombo);
|
MDEDirectoryScan("/usr/share/xsessions", add_session_x, sesscombo);
|
||||||
|
MDEDirectoryScan(DATADIR "/wayland-sessions", add_session_wayland, sesscombo);
|
||||||
|
MDEDirectoryScan("/usr/share/wayland-sessions", add_session_wayland, sesscombo);
|
||||||
|
|
||||||
pthread_mutex_unlock(&xmutex);
|
pthread_mutex_unlock(&xmutex);
|
||||||
|
|
||||||
|
|
|
||||||
75
mdm/main.c
75
mdm/main.c
|
|
@ -1,14 +1,21 @@
|
||||||
#include "mdm.h"
|
#include "mdm.h"
|
||||||
|
#include <sched.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
int is_launch_x = 1;
|
int is_launch_x = 1;
|
||||||
int is_daemon = 1;
|
int is_daemon = 1;
|
||||||
|
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
char* run;
|
session_environment_t* env;
|
||||||
|
|
||||||
|
static void set_env_standard(struct passwd* pwd);
|
||||||
|
static void set_env_xdg(struct passwd* pwd);
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
int i, st;
|
int i, st, exit;
|
||||||
char* backup = NULL;
|
char* backup = NULL;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
|
|
@ -16,7 +23,7 @@ int main(int argc, char** argv) {
|
||||||
if(argv[i][0] == '-') {
|
if(argv[i][0] == '-') {
|
||||||
if(strcmp(argv[i], "-X") == 0 || strcmp(argv[i], "--no-launch-x") == 0) {
|
if(strcmp(argv[i], "-X") == 0 || strcmp(argv[i], "--no-launch-x") == 0) {
|
||||||
is_launch_x = 0;
|
is_launch_x = 0;
|
||||||
}else if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--no-daemon") == 0) {
|
} else if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--no-daemon") == 0) {
|
||||||
is_daemon = 0;
|
is_daemon = 0;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "%s: bad option: %s\n", argv[0], argv[i]);
|
fprintf(stderr, "%s: bad option: %s\n", argv[0], argv[i]);
|
||||||
|
|
@ -30,7 +37,7 @@ int main(int argc, char** argv) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_daemon && (pid = fork()) != 0){
|
if(is_daemon && (pid = fork()) != 0) {
|
||||||
FILE* f = fopen("/var/run/mdm.pid", "w");
|
FILE* f = fopen("/var/run/mdm.pid", "w");
|
||||||
fprintf(f, "%d\n", pid);
|
fprintf(f, "%d\n", pid);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
@ -52,7 +59,7 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
login_window();
|
login_window();
|
||||||
|
|
||||||
if(run == NULL) continue;
|
if(env->run == NULL && env->try_run == NULL) continue;
|
||||||
|
|
||||||
if((pid = fork()) == 0) {
|
if((pid = fork()) == 0) {
|
||||||
struct passwd* pwd = getpwuid(uid);
|
struct passwd* pwd = getpwuid(uid);
|
||||||
|
|
@ -60,18 +67,62 @@ int main(int argc, char** argv) {
|
||||||
setgid(gid);
|
setgid(gid);
|
||||||
setuid(uid);
|
setuid(uid);
|
||||||
chdir(pwd->pw_dir);
|
chdir(pwd->pw_dir);
|
||||||
setenv("USER", pwd->pw_name, 1);
|
|
||||||
setenv("SHELL", pwd->pw_shell, 1);
|
set_env_standard(pwd);
|
||||||
setenv("HOME", pwd->pw_dir, 1);
|
set_env_xdg(pwd);
|
||||||
_exit(system(run));
|
|
||||||
|
if((exit = system(env->try_run)) != 0) {
|
||||||
|
exit = system(env->run);
|
||||||
|
} else {
|
||||||
|
_exit(exit);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
waitpid(pid, NULL, 0);
|
waitpid(pid, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_launch_x) {
|
if(is_launch_x) {
|
||||||
|
unsetenv("DISPLAY");
|
||||||
kill_x();
|
kill_x();
|
||||||
}
|
}
|
||||||
} while(is_launch_x);
|
} while(is_launch_x);
|
||||||
|
|
||||||
if(backup != NULL) free(backup);
|
if(backup != NULL) free(backup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_env_standard(struct passwd* pwd) {
|
||||||
|
setenv("HOME", pwd->pw_dir, 1);
|
||||||
|
setenv("PWD", pwd->pw_dir, 1);
|
||||||
|
setenv("USER", pwd->pw_name, 1);
|
||||||
|
setenv("SHELL", pwd->pw_shell, 1);
|
||||||
|
setenv("LOGNAME", pwd->pw_shell, 1);
|
||||||
|
}
|
||||||
|
void set_env_xdg(struct passwd* pwd) {
|
||||||
|
// this directory isn't avaliable on bsd, but we can't check for all of them.
|
||||||
|
// so just assume it's only on linux, idek if that's true but who care
|
||||||
|
#if defined(__linux__)
|
||||||
|
char runtime_dir[255];
|
||||||
|
snprintf(runtime_dir, 255, "/run/user/%d", pwd->pw_uid);
|
||||||
|
setenv("XDG_RUNTIME_DIR", runtime_dir, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(env->session_type) {
|
||||||
|
case MDM_SESSION_TYPE_X:
|
||||||
|
setenv("XDG_SESSION_TYPE", "x11", 1);
|
||||||
|
break;
|
||||||
|
case MDM_SESSION_TYPE_WAYLAND:
|
||||||
|
setenv("XDG_SESSION_TYPE", "wayland", 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(env->desktop_names) {
|
||||||
|
if(strlen(env->desktop_names) > 1) {
|
||||||
|
setenv("XDG_SESSION_DESKTOP", strtok(env->desktop_names, ";"), 1);
|
||||||
|
}
|
||||||
|
setenv("XDG_CURRENT_DESKTOP", env->desktop_names, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setenv("XDG_SESSION_CLASS", "user", 1);
|
||||||
|
setenv("XDG_SESSION_ID", "1", 1);
|
||||||
|
setenv("XDG_SEAT", "seat0", 1);
|
||||||
|
// setenv("XDG_VTNR", "/dev/pts/7", 1);
|
||||||
|
}
|
||||||
|
|
|
||||||
26
mdm/mdm.h
26
mdm/mdm.h
|
|
@ -22,10 +22,25 @@
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/* login.c */
|
||||||
|
extern MwWidget root;
|
||||||
|
typedef enum session_type {
|
||||||
|
MDM_SESSION_TYPE_X,
|
||||||
|
MDM_SESSION_TYPE_WAYLAND,
|
||||||
|
} session_type_t;
|
||||||
|
typedef struct session_environment {
|
||||||
|
char* run;
|
||||||
|
char* try_run;
|
||||||
|
session_type_t session_type;
|
||||||
|
char* desktop_names;
|
||||||
|
} session_environment_t;
|
||||||
|
|
||||||
|
void login_window(void);
|
||||||
|
|
||||||
/* main.c */
|
/* main.c */
|
||||||
extern gid_t gid;
|
extern gid_t gid;
|
||||||
extern uid_t uid;
|
extern uid_t uid;
|
||||||
extern char* run;
|
extern session_environment_t* env;
|
||||||
|
|
||||||
/* xserver.c */
|
/* xserver.c */
|
||||||
extern pthread_t xthread;
|
extern pthread_t xthread;
|
||||||
|
|
@ -39,11 +54,6 @@ int init_x(void);
|
||||||
void loop_x(void);
|
void loop_x(void);
|
||||||
void kill_x(void);
|
void kill_x(void);
|
||||||
|
|
||||||
/* login.c */
|
|
||||||
extern MwWidget root;
|
|
||||||
|
|
||||||
void login_window(void);
|
|
||||||
|
|
||||||
/* config.c */
|
/* config.c */
|
||||||
extern char* config_picture;
|
extern char* config_picture;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <stdlib.h>
|
||||||
#define _MILSKO
|
#define _MILSKO
|
||||||
#define USE_X11
|
#define USE_X11
|
||||||
#include "mdm.h"
|
#include "mdm.h"
|
||||||
|
|
@ -22,8 +23,6 @@ int launch_x(void) {
|
||||||
|
|
||||||
signal(SIGUSR1, catch_usr1);
|
signal(SIGUSR1, catch_usr1);
|
||||||
|
|
||||||
/* TODO: Remove hardcoded DISPLAY */
|
|
||||||
|
|
||||||
if((xserver = fork()) == 0) {
|
if((xserver = fork()) == 0) {
|
||||||
signal(SIGUSR1, SIG_IGN);
|
signal(SIGUSR1, SIG_IGN);
|
||||||
execlp("X", "X", ":0", NULL);
|
execlp("X", "X", ":0", NULL);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue