feat: better handling

* setui/setgid/etc errors are recoverable now
* fix small print_errno arguments bug
* send TERM env var to session (if present)
This commit is contained in:
javalsai 2024-07-26 18:17:17 +02:00
parent 5861b4dc34
commit 9d81c9df8b
Signed by: javalsai
SSH Key Fingerprint: SHA256:3G83yKhBUWVABVX/vPWH88xnK4+ptMtHkZGCRXD4Mk8
2 changed files with 69 additions and 36 deletions

View File

@ -5,12 +5,14 @@
#include <security/pam_misc.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <auth.h>
#include <sessions.h>
#include <ui.h>
#include <unistd.h>
#include <util.h>
int pam_conversation(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr) {
@ -51,6 +53,11 @@ pam_handle_t *get_pamh(char *user, char *passwd) {
}
#undef CHECK_PAM_RET
void *shmalloc(size_t size) {
return mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,
-1, 0);
}
void moarEnv(char *user, struct session session, struct passwd *pw) {
chdir(pw->pw_dir);
setenv("HOME", pw->pw_dir, true);
@ -96,45 +103,66 @@ bool launch(char *user, char *passwd, struct session session,
return false;
}
// point of no return
// TODO: move this to get_pamh, before first setcred, like login does
if (cb != NULL)
cb();
if (setgid(pw->pw_gid) == -1) {
perror("setgid");
exit(EXIT_FAILURE);
bool *reach_session = shmalloc(sizeof(bool));
if (reach_session == NULL) {
perror("error allocating shared memory");
return false;
}
if (initgroups(user, pw->pw_gid) == -1) {
perror("init groups");
exit(EXIT_FAILURE);
}
char **envlist = pam_getenvlist(pamh);
if (envlist == NULL) {
perror("pam_getenvlist");
exit(EXIT_FAILURE);
}
// TODO: chown stdin to user
if (setuid(pw->pw_uid) == -1) {
perror("setuid");
exit(EXIT_FAILURE);
}
system("clear");
printf("\x1b[0m\x1b[H");
for (uint i = 0; envlist[i] != NULL; i++) {
putenv(envlist[i]);
}
// NOTE: path hotfix
putenv("PATH=/bin:/usr/bin");
free(envlist);
moarEnv(user, session, pw);
*reach_session = false;
uint pid = fork();
if (pid == 0) { // child
char *TERM = NULL;
char *_GETTERM = getenv("TERM");
if (_GETTERM != NULL)
strcln(&TERM, _GETTERM);
if (clearenv() != 0) {
print_errno("clearenv");
_exit(EXIT_FAILURE);
}
char **envlist = pam_getenvlist(pamh);
if (envlist == NULL) {
print_errno("pam_getenvlist");
_exit(EXIT_FAILURE);
}
for (uint i = 0; envlist[i] != NULL; i++) {
putenv(envlist[i]);
}
// FIXME: path hotfix
putenv("PATH=/bin:/usr/bin");
if (TERM != NULL) {
setenv("TERM", TERM, true);
free(TERM);
}
free(envlist);
moarEnv(user, session, pw);
// TODO: chown stdin to user
// does it inherit stdin from parent and
// does parent need to reclaim it after
// this dies?
if (setgid(pw->pw_gid) == -1) {
print_errno("setgid");
_exit(EXIT_FAILURE);
}
if (initgroups(user, pw->pw_gid) == -1) {
print_errno("initgroups");
_exit(EXIT_FAILURE);
}
if (setuid(pw->pw_uid) == -1) {
perror("setuid");
_exit(EXIT_FAILURE);
}
if (cb != NULL)
cb();
*reach_session = true;
// TODO: these will be different due to TryExec
// and, Exec/TryExec might contain spaces as args
if (session.type == SHELL) {
@ -152,6 +180,11 @@ bool launch(char *user, char *passwd, struct session session,
pam_setcred(pamh, PAM_DELETE_CRED);
pam_close_session(pamh, 0);
pam_end(pamh, PAM_SUCCESS);
if (*reach_session == false) {
return false;
} else
exit(0);
}
return true;

View File

@ -569,7 +569,7 @@ void print_errno(const char *descr) {
origin.x, theme.colors.err, errno, strerror(errno));
else {
fprintf(stderr, "\x1b[%d;%dH\x1b[%sm%s(%d): %s", origin.y - 1, origin.x,
descr, theme.colors.err, errno, strerror(errno));
theme.colors.err, descr, errno, strerror(errno));
}
}