groups: First pass at support for supplementary group lists
This commit is contained in:
parent
8775a28209
commit
8984cc8f71
@ -119,9 +119,7 @@ int main (int argc, char ** argv) {
|
||||
|
||||
pid_t _session_pid = fork();
|
||||
if (!_session_pid) {
|
||||
setgid(uid);
|
||||
setuid(uid);
|
||||
toaru_auth_set_vars();
|
||||
toaru_set_credentials(uid);
|
||||
char * args[] = {"/bin/session", NULL};
|
||||
execvp(args[0], args);
|
||||
exit(1);
|
||||
|
37
apps/groups.c
Normal file
37
apps/groups.c
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @brief List group memberships.
|
||||
* @file apps/groups.c
|
||||
*
|
||||
* @copyright
|
||||
* This file is part of ToaruOS and is released under the terms
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2021 K. Lange
|
||||
*/
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pwd.h>
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
/* First print our egid group */
|
||||
struct passwd * p = getpwuid(getegid());
|
||||
if (p) {
|
||||
fprintf(stdout, "%s ", p->pw_name);
|
||||
}
|
||||
/* Then get the group list. */
|
||||
int groupCount = getgroups(0, NULL);
|
||||
if (groupCount) {
|
||||
gid_t * myGroups = malloc(sizeof(gid_t) * groupCount);
|
||||
groupCount = getgroups(groupCount, myGroups);
|
||||
for (int i = 0; i < groupCount; ++i) {
|
||||
p = getpwuid(myGroups[i]);
|
||||
if (p) {
|
||||
fprintf(stdout, "%s ", p->pw_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stdout,"\n");
|
||||
endpwent();
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,10 +27,7 @@ int main(int argc, char * argv[]) {
|
||||
|
||||
int _session_pid = fork();
|
||||
if (!_session_pid) {
|
||||
setgid(1000);
|
||||
setuid(1000);
|
||||
toaru_auth_set_vars();
|
||||
|
||||
toaru_set_credentials(1000);
|
||||
char * args[] = {"/bin/session", NULL};
|
||||
execvp(args[0], args);
|
||||
|
||||
|
@ -144,9 +144,8 @@ do_fork:
|
||||
f = fork();
|
||||
if (getpid() != pid) {
|
||||
ioctl(STDIN_FILENO, IOCTLTTYLOGIN, &uid);
|
||||
setuid(uid);
|
||||
toaru_set_credentials(uid);
|
||||
setsid();
|
||||
toaru_auth_set_vars();
|
||||
char * args[] = {
|
||||
getenv("SHELL"),
|
||||
NULL
|
||||
|
@ -26,6 +26,8 @@
|
||||
|
||||
#define SUDO_TIME 5 MINUTES
|
||||
|
||||
extern int setgroups(int size, const gid_t list[]);
|
||||
|
||||
static int sudo_loop(int (*prompt_callback)(char * username, char * password, int failures, char * argv[]), char * argv[]) {
|
||||
|
||||
int fails = 0;
|
||||
@ -130,6 +132,7 @@ static int sudo_loop(int (*prompt_callback)(char * username, char * password, in
|
||||
/* Actually become root, so real user id = 0 */
|
||||
setgid(0);
|
||||
setuid(0);
|
||||
setgroups(0,NULL);
|
||||
|
||||
if (!strcmp(argv[1], "-s")) {
|
||||
argv[1] = getenv("SHELL");
|
||||
|
2
base/etc/group
Normal file
2
base/etc/group
Normal file
@ -0,0 +1,2 @@
|
||||
root:x:0:
|
||||
adm:x:1:local
|
@ -1,2 +1,3 @@
|
||||
root:x:0:0:Administrator:/home/root:/bin/sh:fancy
|
||||
adm:x:1:1:Administrators:/tmp:/bin/false:nope
|
||||
local:x:1000:1000:Local User:/home/local:/bin/sh:fancy
|
||||
|
@ -117,6 +117,9 @@ typedef struct process {
|
||||
spin_lock_t sched_lock;
|
||||
|
||||
uintptr_t signals[NUMSIGNALS+1];
|
||||
|
||||
int supplementary_group_count;
|
||||
gid_t * supplementary_group_list;
|
||||
} process_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -127,6 +127,8 @@ DECL_SYSCALL4(fswait3, int, int*, int, int*);
|
||||
DECL_SYSCALL0(getgid);
|
||||
DECL_SYSCALL0(getegid);
|
||||
DECL_SYSCALL1(setgid, unsigned int);
|
||||
DECL_SYSCALL2(getgroups, int, int*);
|
||||
DECL_SYSCALL2(setgroups, int, const int*);
|
||||
|
||||
_End_C_Header
|
||||
|
||||
|
@ -68,3 +68,5 @@
|
||||
#define SYS_GETGID 66
|
||||
#define SYS_GETEGID 67
|
||||
#define SYS_SETGID 68
|
||||
#define SYS_GETGROUPS 69
|
||||
#define SYS_SETGROUPS 70
|
||||
|
@ -13,6 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <_cheader.h>
|
||||
#include <unistd.h>
|
||||
|
||||
_Begin_C_Header
|
||||
|
||||
@ -31,4 +32,14 @@ extern int toaru_auth_check_pass(char * user, char * pass);
|
||||
*/
|
||||
extern void toaru_auth_set_vars(void);
|
||||
|
||||
/**
|
||||
* Set supplementary groups from /etc/groups
|
||||
*/
|
||||
extern void toaru_auth_set_groups(uid_t uid);
|
||||
|
||||
/**
|
||||
* Do the above two steps, and setuid, and setgid...
|
||||
*/
|
||||
extern void toaru_set_credentials(uid_t uid);
|
||||
|
||||
_End_C_Header
|
||||
|
@ -106,4 +106,6 @@ extern int truncate(const char *, off_t);
|
||||
#define _PC_PATH_MAX 1
|
||||
extern long pathconf(const char *path, int name);
|
||||
|
||||
extern int getgroups(int size, gid_t list[]);
|
||||
|
||||
_End_C_Header
|
||||
|
@ -435,6 +435,14 @@ process_t * spawn_process(volatile process_t * parent, int flags) {
|
||||
proc->job = parent->job;
|
||||
proc->session = parent->session;
|
||||
|
||||
if (parent->supplementary_group_count) {
|
||||
proc->supplementary_group_count = parent->supplementary_group_count;
|
||||
proc->supplementary_group_list = malloc(sizeof(gid_t) * proc->supplementary_group_count);
|
||||
for (int i = 0; i < proc->supplementary_group_count; ++i) {
|
||||
proc->supplementary_group_list[i] = parent->supplementary_group_list[i];
|
||||
}
|
||||
}
|
||||
|
||||
proc->thread.context.sp = 0;
|
||||
proc->thread.context.bp = 0;
|
||||
proc->thread.context.ip = 0;
|
||||
@ -579,6 +587,11 @@ void process_delete(process_t * proc) {
|
||||
shm_release_all(proc);
|
||||
free(proc->shm_mappings);
|
||||
|
||||
if (proc->supplementary_group_list) {
|
||||
proc->supplementary_group_count = 0;
|
||||
free(proc->supplementary_group_list);
|
||||
}
|
||||
|
||||
/* Is someone using this process? */
|
||||
for (int i = 0; i < processor_count; ++i) {
|
||||
if (i == this_core->cpu_id) continue;
|
||||
|
@ -499,6 +499,45 @@ static long sys_setgid(gid_t new_gid) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
static long sys_getgroups(int size, gid_t list[]) {
|
||||
if (size == 0) {
|
||||
return this_core->current_process->supplementary_group_count;
|
||||
} else if (size < this_core->current_process->supplementary_group_count) {
|
||||
return -EINVAL;
|
||||
} else {
|
||||
for (int i = 0; i < this_core->current_process->supplementary_group_count; ++i) {
|
||||
PTR_VALIDATE(list + i);
|
||||
list[i] = this_core->current_process->supplementary_group_list[i];
|
||||
}
|
||||
return this_core->current_process->supplementary_group_count;
|
||||
}
|
||||
}
|
||||
|
||||
static long sys_setgroups(int size, const gid_t list[]) {
|
||||
if (this_core->current_process->user != USER_ROOT_UID) return -EPERM;
|
||||
if (size < 0) return -EINVAL;
|
||||
if (size > 32) return -EINVAL; /* Arbitrary decision */
|
||||
|
||||
/* Free the current set. */
|
||||
if (this_core->current_process->supplementary_group_count) {
|
||||
free(this_core->current_process->supplementary_group_list);
|
||||
this_core->current_process->supplementary_group_list = NULL;
|
||||
}
|
||||
|
||||
this_core->current_process->supplementary_group_count = size;
|
||||
if (size == 0) return 0;
|
||||
|
||||
this_core->current_process->supplementary_group_list = malloc(sizeof(gid_t) * size);
|
||||
|
||||
for (int i = 0; i < size; ++i) {
|
||||
PTR_VALIDATE(list + i);
|
||||
this_core->current_process->supplementary_group_list[i] = list[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long sys_getpid(void) {
|
||||
/* The user actually wants the pid of the originating thread (which can be us). */
|
||||
return this_core->current_process->group ? (long)this_core->current_process->group : (long)this_core->current_process->id;
|
||||
@ -979,6 +1018,8 @@ static long (*syscalls[])() = {
|
||||
[SYS_GETGID] = sys_getgid,
|
||||
[SYS_GETEGID] = sys_getegid,
|
||||
[SYS_SETGID] = sys_setgid,
|
||||
[SYS_GETGROUPS] = sys_getgroups,
|
||||
[SYS_SETGROUPS] = sys_setgroups,
|
||||
|
||||
[SYS_SOCKET] = net_socket,
|
||||
[SYS_SETSOCKOPT] = net_setsockopt,
|
||||
|
@ -73,9 +73,14 @@ int has_permission(fs_node_t * node, int permission_bit) {
|
||||
uint8_t group_perm = (permissions >> 3) & 07;
|
||||
|
||||
if (this_core->current_process->user == node->uid) my_permissions |= user_perm;
|
||||
if (this_core->current_process->user_group == node->uid) my_permissions |= group_perm;
|
||||
|
||||
/* TODO: Supplementary group IDs */
|
||||
if (this_core->current_process->user_group == node->gid) my_permissions |= group_perm;
|
||||
else if (this_core->current_process->supplementary_group_count) {
|
||||
for (int i = 0; i < this_core->current_process->supplementary_group_count; ++i) {
|
||||
if (this_core->current_process->supplementary_group_list[i] == node->gid) {
|
||||
my_permissions |= group_perm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (permission_bit & my_permissions);
|
||||
}
|
||||
|
73
lib/auth.c
73
lib/auth.c
@ -17,6 +17,8 @@
|
||||
extern struct passwd *fgetpwent(FILE *stream);
|
||||
#endif
|
||||
|
||||
extern int setgroups(int size, const gid_t list[]);
|
||||
|
||||
#define MASTER_PASSWD "/etc/master.passwd"
|
||||
|
||||
int toaru_auth_check_pass(char * user, char * pass) {
|
||||
@ -63,3 +65,74 @@ void toaru_auth_set_vars(void) {
|
||||
chdir(getenv("HOME"));
|
||||
}
|
||||
|
||||
void toaru_auth_set_groups(uid_t uid) {
|
||||
/* Get the username for this uid */
|
||||
struct passwd * pwd = getpwuid(uid);
|
||||
|
||||
/* No username? No group memberships! */
|
||||
if (!pwd) goto no_groups;
|
||||
|
||||
/* Open the group file */
|
||||
FILE * groupList = fopen("/etc/group","r");
|
||||
|
||||
/* No groups? No membership. */
|
||||
if (!groupList) goto no_groups;
|
||||
|
||||
/* Scan through lines of groups. */
|
||||
#define LINE_LEN 2048
|
||||
char * pw_blob = malloc(LINE_LEN);
|
||||
|
||||
int groupCount = 0;
|
||||
gid_t myGroups[32] = {0};
|
||||
|
||||
while (!feof(groupList)) {
|
||||
memset(pw_blob, 0x00, LINE_LEN);
|
||||
fgets(pw_blob, LINE_LEN, groupList);
|
||||
if (pw_blob[strlen(pw_blob)-1] == '\n') {
|
||||
pw_blob[strlen(pw_blob)-1] = '\0'; /* erase newline */
|
||||
}
|
||||
|
||||
/* Tokenize */
|
||||
char * memberlist = NULL;
|
||||
char *p, *last;
|
||||
gid_t groupNumber = -1;
|
||||
int i = 0;
|
||||
for ((p = strtok_r(pw_blob, ":", &last)); p;
|
||||
(p = strtok_r(NULL, ":", &last)), i++) {
|
||||
if (i == 2) {
|
||||
groupNumber = atoi(p);
|
||||
} else if (i == 3) {
|
||||
memberlist = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (groupNumber == -1) continue;
|
||||
if (!memberlist) continue;
|
||||
|
||||
for ((p = strtok_r(memberlist, ",", &last)); p;
|
||||
(p = strtok_r(NULL, ",", &last))) {
|
||||
if (!strcmp(p, pwd->pw_name)) {
|
||||
if (groupCount < 32) {
|
||||
myGroups[groupCount] = groupNumber;
|
||||
groupCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setgroups(groupCount, myGroups);
|
||||
free(pw_blob);
|
||||
fclose(groupList);
|
||||
return;
|
||||
|
||||
no_groups:
|
||||
setgroups(0, NULL);
|
||||
}
|
||||
|
||||
void toaru_set_credentials(uid_t uid) {
|
||||
toaru_auth_set_groups(uid);
|
||||
setgid(uid);
|
||||
setuid(uid);
|
||||
toaru_auth_set_vars();
|
||||
}
|
||||
|
11
libc/unistd/getgroups.c
Normal file
11
libc/unistd/getgroups.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include <unistd.h>
|
||||
#include <syscall.h>
|
||||
#include <syscall_nums.h>
|
||||
#include <errno.h>
|
||||
|
||||
DEFN_SYSCALL2(getgroups, SYS_GETGROUPS, int, gid_t *);
|
||||
|
||||
int getgroups(int size, gid_t list[]) {
|
||||
__sets_errno(syscall_getgroups(size, list));
|
||||
}
|
||||
|
12
libc/unistd/setgroups.c
Normal file
12
libc/unistd/setgroups.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <unistd.h>
|
||||
#include <syscall.h>
|
||||
#include <syscall_nums.h>
|
||||
#include <errno.h>
|
||||
|
||||
DEFN_SYSCALL2(setgroups, SYS_SETGROUPS, int, const gid_t *);
|
||||
|
||||
int setgroups(int size, const gid_t list[]) {
|
||||
__sets_errno(syscall_setgroups(size, list));
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,8 @@ static fs_node_t * spkr_device_create(void) {
|
||||
fs_node_t * fnode = malloc(sizeof(fs_node_t));
|
||||
memset(fnode, 0x00, sizeof(fs_node_t));
|
||||
snprintf(fnode->name, 5, "spkr");
|
||||
fnode->mask = 0666; /* TODO need a speaker group */
|
||||
fnode->mask = 0660; /* TODO need a speaker group */
|
||||
fnode->gid = 1;
|
||||
fnode->flags = FS_CHARDEVICE;
|
||||
fnode->write = write_spkr;
|
||||
return fnode;
|
||||
|
Loading…
Reference in New Issue
Block a user