Add include and comment support to passwd(5) and group(5).
This commit is contained in:
parent
da86ca1873
commit
c57ff050e9
2
Makefile
2
Makefile
|
@ -447,7 +447,9 @@ $(LIVE_INITRD): sysroot
|
||||||
mkdir -p $(LIVE_INITRD).d/etc/init
|
mkdir -p $(LIVE_INITRD).d/etc/init
|
||||||
echo require single-user exit-code > $(LIVE_INITRD).d/etc/init/default
|
echo require single-user exit-code > $(LIVE_INITRD).d/etc/init/default
|
||||||
echo "root::0:0:root:/root:sh" > $(LIVE_INITRD).d/etc/passwd
|
echo "root::0:0:root:/root:sh" > $(LIVE_INITRD).d/etc/passwd
|
||||||
|
echo "include /etc/default/passwd.d/*" >> $(LIVE_INITRD).d/etc/passwd
|
||||||
echo "root::0:root" > $(LIVE_INITRD).d/etc/group
|
echo "root::0:root" > $(LIVE_INITRD).d/etc/group
|
||||||
|
echo "include /etc/default/group.d/*" >> $(LIVE_INITRD).d/etc/group
|
||||||
mkdir -p $(LIVE_INITRD).d/home
|
mkdir -p $(LIVE_INITRD).d/home
|
||||||
mkdir -p $(LIVE_INITRD).d/root -m 700
|
mkdir -p $(LIVE_INITRD).d/root -m 700
|
||||||
cp -RT "$(SYSROOT)/etc/skel" $(LIVE_INITRD).d/root
|
cp -RT "$(SYSROOT)/etc/skel" $(LIVE_INITRD).d/root
|
||||||
|
|
|
@ -478,7 +478,9 @@ pwd/getpwnam.o \
|
||||||
pwd/getpwnam_r.o \
|
pwd/getpwnam_r.o \
|
||||||
pwd/getpwuid.o \
|
pwd/getpwuid.o \
|
||||||
pwd/getpwuid_r.o \
|
pwd/getpwuid_r.o \
|
||||||
|
pwd/__openent.o \
|
||||||
pwd/openpw.o \
|
pwd/openpw.o \
|
||||||
|
pwd/scanpwent.o \
|
||||||
pwd/setpwent.o \
|
pwd/setpwent.o \
|
||||||
sched/sched_yield.o \
|
sched/sched_yield.o \
|
||||||
pty/openpty.o \
|
pty/openpty.o \
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -18,9 +18,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
FILE* opengr(void)
|
FILE* opengr(void)
|
||||||
{
|
{
|
||||||
return fopen("/etc/group", "r");
|
return __openent("/etc/group");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2015 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2015, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -24,8 +24,9 @@ FILE* __grp_file = NULL;
|
||||||
|
|
||||||
void setgrent(void)
|
void setgrent(void)
|
||||||
{
|
{
|
||||||
if ( __grp_file )
|
FILE* new_file = opengr();
|
||||||
|
if ( !new_file && __grp_file )
|
||||||
rewind(__grp_file);
|
rewind(__grp_file);
|
||||||
else
|
else
|
||||||
__grp_file = opengr();
|
__grp_file = new_file;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2015 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2015, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -62,6 +62,8 @@ struct passwd
|
||||||
|
|
||||||
#if defined(__is_sortix_libc)
|
#if defined(__is_sortix_libc)
|
||||||
extern FILE* __pwd_file;
|
extern FILE* __pwd_file;
|
||||||
|
|
||||||
|
FILE* __openent(const char*);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int bcrypt_newhash(const char*, int, char*, size_t);
|
int bcrypt_newhash(const char*, int, char*, size_t);
|
||||||
|
@ -79,6 +81,7 @@ int getpwnam_r(const char* __restrict, struct passwd* __restrict,
|
||||||
struct passwd* getpwuid(uid_t);
|
struct passwd* getpwuid(uid_t);
|
||||||
int getpwuid_r(uid_t, struct passwd* __restrict, char* __restrict, size_t,
|
int getpwuid_r(uid_t, struct passwd* __restrict, char* __restrict, size_t,
|
||||||
struct passwd** __restrict);
|
struct passwd** __restrict);
|
||||||
|
int scanpwent(char* __restrict, struct passwd* __restrict);
|
||||||
FILE* openpw(void);
|
FILE* openpw(void);
|
||||||
void setpwent(void);
|
void setpwent(void);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pwd/__openent.c
|
||||||
|
* Preprocesses include statements in an entry database.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <glob.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
bool __openent_append(FILE* out, const char* path)
|
||||||
|
{
|
||||||
|
FILE* fp = fopen(path, "r");
|
||||||
|
if ( !fp )
|
||||||
|
return false;
|
||||||
|
char* line = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
ssize_t amount;
|
||||||
|
bool success = true;
|
||||||
|
while ( success && 0 < (amount = getline(&line, &size, fp)) )
|
||||||
|
{
|
||||||
|
size_t length = amount;
|
||||||
|
size_t offset = 0;
|
||||||
|
while ( offset < length && isspace((unsigned char) line[offset]) )
|
||||||
|
offset++;
|
||||||
|
if ( !line[offset] || line[offset] == '#' )
|
||||||
|
continue;
|
||||||
|
size_t include_length = strlen("include");
|
||||||
|
if ( !strncmp(line + offset, "include", include_length) &&
|
||||||
|
isspace((unsigned char) line[offset + include_length]) )
|
||||||
|
{
|
||||||
|
while ( length && isspace((unsigned char) line[length - 1]) )
|
||||||
|
line[--length] = '\0';
|
||||||
|
offset = offset + include_length;
|
||||||
|
while ( offset < length && isspace((unsigned char) line[offset]) )
|
||||||
|
offset++;
|
||||||
|
const char* pattern = line + offset;
|
||||||
|
glob_t gl;
|
||||||
|
if ( !glob(pattern, GLOB_NOCHECK, NULL, &gl) )
|
||||||
|
{
|
||||||
|
for ( size_t i = 0; success && i < gl.gl_pathc; i++ )
|
||||||
|
if ( !__openent_append(out, gl.gl_pathv[i]) &&
|
||||||
|
errno != ENOENT )
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
success = false;
|
||||||
|
globfree(&gl);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( fwrite(line, 1, length, out) != length )
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
if ( ferror(fp) )
|
||||||
|
success = false;
|
||||||
|
fclose(fp);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* __openent(const char* path)
|
||||||
|
{
|
||||||
|
char* data;
|
||||||
|
size_t size;
|
||||||
|
FILE* memstream = open_memstream(&data, &size);
|
||||||
|
if ( !memstream )
|
||||||
|
return NULL;
|
||||||
|
if ( !__openent_append(memstream, path) ||
|
||||||
|
ferror(memstream) || fflush(memstream) == EOF )
|
||||||
|
{
|
||||||
|
fclose(memstream);
|
||||||
|
free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fclose(memstream);
|
||||||
|
size = strlen(data);
|
||||||
|
FILE* result = fmemopen(NULL, size, "r+");
|
||||||
|
if ( !result )
|
||||||
|
return free(data), NULL;
|
||||||
|
size_t amount = fwrite(data, 1, size, result);
|
||||||
|
free(data);
|
||||||
|
if ( amount != size || fflush(result) == EOF )
|
||||||
|
return fclose(result), NULL;
|
||||||
|
rewind(result);
|
||||||
|
return result;
|
||||||
|
}
|
|
@ -17,70 +17,9 @@
|
||||||
* Reads a passwd entry from a FILE.
|
* Reads a passwd entry from a FILE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
static char* next_field(char** current)
|
|
||||||
{
|
|
||||||
char* result = *current;
|
|
||||||
if ( result )
|
|
||||||
{
|
|
||||||
char* next = result;
|
|
||||||
while ( *next && *next != ':' )
|
|
||||||
next++;
|
|
||||||
if ( !*next )
|
|
||||||
next = NULL;
|
|
||||||
else
|
|
||||||
*next++ = '\0';
|
|
||||||
*current = next;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool next_field_uintmax(char** current, uintmax_t* result)
|
|
||||||
{
|
|
||||||
char* id_str = next_field(current);
|
|
||||||
if ( !id_str )
|
|
||||||
return false;
|
|
||||||
char* id_endptr;
|
|
||||||
uintmax_t id_umax = strtoumax(id_str, &id_endptr, 10);
|
|
||||||
if ( *id_endptr )
|
|
||||||
return false;
|
|
||||||
*result = id_umax;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool next_field_gid(char** current, gid_t* result)
|
|
||||||
{
|
|
||||||
uintmax_t id_umax;
|
|
||||||
if ( !next_field_uintmax(current, &id_umax) )
|
|
||||||
return false;
|
|
||||||
gid_t gid = (gid_t) id_umax;
|
|
||||||
if ( (uintmax_t) gid != (uintmax_t) id_umax )
|
|
||||||
return false;
|
|
||||||
*result = gid;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool next_field_uid(char** current, uid_t* result)
|
|
||||||
{
|
|
||||||
uintmax_t id_umax;
|
|
||||||
if ( !next_field_uintmax(current, &id_umax) )
|
|
||||||
return false;
|
|
||||||
uid_t uid = (uid_t) id_umax;
|
|
||||||
if ( (uintmax_t) uid != (uintmax_t) id_umax )
|
|
||||||
return false;
|
|
||||||
*result = uid;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fgetpwent_r(FILE* restrict fp,
|
int fgetpwent_r(FILE* restrict fp,
|
||||||
struct passwd* restrict result,
|
struct passwd* restrict result,
|
||||||
|
@ -144,22 +83,7 @@ int fgetpwent_r(FILE* restrict fp,
|
||||||
}
|
}
|
||||||
buf[buf_used] = '\0';
|
buf[buf_used] = '\0';
|
||||||
|
|
||||||
char* parse_str = buf;
|
if ( !scanpwent(buf, result) )
|
||||||
if ( !(result->pw_name = next_field(&parse_str)) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !(result->pw_passwd = next_field(&parse_str)) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !next_field_uid(&parse_str, &result->pw_uid) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !next_field_gid(&parse_str, &result->pw_gid) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !(result->pw_gecos = next_field(&parse_str)) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !(result->pw_dir = next_field(&parse_str)) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( !(result->pw_shell = next_field(&parse_str)) )
|
|
||||||
goto parse_failure;
|
|
||||||
if ( parse_str )
|
|
||||||
goto parse_failure;
|
goto parse_failure;
|
||||||
|
|
||||||
funlockfile(fp);
|
funlockfile(fp);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -22,5 +22,5 @@
|
||||||
|
|
||||||
FILE* openpw(void)
|
FILE* openpw(void)
|
||||||
{
|
{
|
||||||
return fopen("/etc/passwd", "r");
|
return __openent("/etc/passwd");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 2023 Jonas 'Sortie' Termansen.
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*
|
||||||
|
* pwd/scanfpwent.c
|
||||||
|
* Parse passwd entry.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
static char* next_field(char** current)
|
||||||
|
{
|
||||||
|
char* result = *current;
|
||||||
|
if ( result )
|
||||||
|
{
|
||||||
|
char* next = result;
|
||||||
|
while ( *next && *next != ':' )
|
||||||
|
next++;
|
||||||
|
if ( !*next )
|
||||||
|
next = NULL;
|
||||||
|
else
|
||||||
|
*next++ = '\0';
|
||||||
|
*current = next;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool next_field_uintmax(char** current, uintmax_t* result)
|
||||||
|
{
|
||||||
|
char* id_str = next_field(current);
|
||||||
|
if ( !id_str )
|
||||||
|
return false;
|
||||||
|
char* id_endptr;
|
||||||
|
uintmax_t id_umax = strtoumax(id_str, &id_endptr, 10);
|
||||||
|
if ( *id_endptr )
|
||||||
|
return false;
|
||||||
|
*result = id_umax;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool next_field_gid(char** current, gid_t* result)
|
||||||
|
{
|
||||||
|
uintmax_t id_umax;
|
||||||
|
if ( !next_field_uintmax(current, &id_umax) )
|
||||||
|
return false;
|
||||||
|
gid_t gid = (gid_t) id_umax;
|
||||||
|
if ( (uintmax_t) gid != (uintmax_t) id_umax )
|
||||||
|
return false;
|
||||||
|
*result = gid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool next_field_uid(char** current, uid_t* result)
|
||||||
|
{
|
||||||
|
uintmax_t id_umax;
|
||||||
|
if ( !next_field_uintmax(current, &id_umax) )
|
||||||
|
return false;
|
||||||
|
uid_t uid = (uid_t) id_umax;
|
||||||
|
if ( (uintmax_t) uid != (uintmax_t) id_umax )
|
||||||
|
return false;
|
||||||
|
*result = uid;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int scanpwent(char* str, struct passwd* passwd)
|
||||||
|
{
|
||||||
|
while ( *str && isspace((unsigned char) *str) )
|
||||||
|
str++;
|
||||||
|
if ( !*str || *str == '#' ||
|
||||||
|
!(passwd->pw_name = next_field(&str)) ||
|
||||||
|
!(passwd->pw_passwd = next_field(&str)) ||
|
||||||
|
!next_field_uid(&str, &passwd->pw_uid) ||
|
||||||
|
!next_field_gid(&str, &passwd->pw_gid) ||
|
||||||
|
!(passwd->pw_gecos = next_field(&str)) ||
|
||||||
|
!(passwd->pw_dir = next_field(&str)) ||
|
||||||
|
!(passwd->pw_shell = next_field(&str)) )
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2015 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2013, 2015, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -24,8 +24,9 @@ FILE* __pwd_file = NULL;
|
||||||
|
|
||||||
void setpwent(void)
|
void setpwent(void)
|
||||||
{
|
{
|
||||||
if ( __pwd_file )
|
FILE* new_file = openpw();
|
||||||
|
if ( !new_file && __pwd_file )
|
||||||
rewind(__pwd_file);
|
rewind(__pwd_file);
|
||||||
else
|
else
|
||||||
__pwd_file = openpw();
|
__pwd_file = new_file;
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,24 @@ releasing Sortix x.y, foo." to allow the maintainer to easily
|
||||||
.Xr grep 1
|
.Xr grep 1
|
||||||
for it after a release.
|
for it after a release.
|
||||||
.Sh CHANGES
|
.Sh CHANGES
|
||||||
|
.Ss Add include and comment support to passwd(5) and group(5)
|
||||||
|
The
|
||||||
|
.Xr passwd 5
|
||||||
|
and
|
||||||
|
.Xr group 5
|
||||||
|
files have gained support for include statements via libc support.
|
||||||
|
Installations must now include
|
||||||
|
.Pa /etc/default/passwd.d/*
|
||||||
|
and
|
||||||
|
.Pa /etc/default/group.d/*
|
||||||
|
respectively in order to have system users and groups.
|
||||||
|
.Pp
|
||||||
|
An upgrade hook will add the inclusions to
|
||||||
|
.Pa /etc/passwd
|
||||||
|
and
|
||||||
|
.Pa /etc/group .
|
||||||
|
Applications accessing passwd and group databases must be recompiled with the
|
||||||
|
latest libc.
|
||||||
.Ss Add memory statistics to struct psctl_stat
|
.Ss Add memory statistics to struct psctl_stat
|
||||||
The
|
The
|
||||||
.Xr psctl 2
|
.Xr psctl 2
|
||||||
|
|
|
@ -55,6 +55,8 @@ install: all
|
||||||
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-tix-manifest-mode
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-tix-manifest-mode
|
||||||
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-leaked-files
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-leaked-files
|
||||||
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-init
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-init
|
||||||
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-passwd
|
||||||
|
touch $(DESTDIR)$(DATADIR)/sysinstall/hooks/sortix-1.1-group
|
||||||
|
|
||||||
sysinstall: $(SYSINSTALL_OBJS)
|
sysinstall: $(SYSINSTALL_OBJS)
|
||||||
$(CC) $(SYSINSTALL_OBJS) -o $@ -lmount
|
$(CC) $(SYSINSTALL_OBJS) -o $@ -lmount
|
||||||
|
|
|
@ -296,6 +296,64 @@ void upgrade_prepare(const struct release* old_release,
|
||||||
free(init_target_path);
|
free(init_target_path);
|
||||||
free(init_default_path);
|
free(init_default_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: After releasing Sortix 1.1, remove this compatibility.
|
||||||
|
if ( hook_needs_to_be_run(source_prefix, target_prefix,
|
||||||
|
"sortix-1.1-passwd") )
|
||||||
|
{
|
||||||
|
char* passwd_path = join_paths(target_prefix, "/etc/passwd");
|
||||||
|
if ( !passwd_path )
|
||||||
|
{
|
||||||
|
warn("malloc");
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
FILE* fp = fopen(passwd_path, "a");
|
||||||
|
if ( fp )
|
||||||
|
{
|
||||||
|
printf(" - Including /etc/default/passwd.d/* in /etc/passwd...\n");
|
||||||
|
if ( fprintf(fp, "include /etc/default/passwd.d/*\n") < 0 ||
|
||||||
|
fclose(fp) == EOF )
|
||||||
|
{
|
||||||
|
warn("%s", passwd_path);
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( errno != ENOENT )
|
||||||
|
{
|
||||||
|
warn("%s", passwd_path);
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
free(passwd_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: After releasing Sortix 1.1, remove this compatibility.
|
||||||
|
if ( hook_needs_to_be_run(source_prefix, target_prefix,
|
||||||
|
"sortix-1.1-group") )
|
||||||
|
{
|
||||||
|
char* group_path = join_paths(target_prefix, "/etc/group");
|
||||||
|
if ( !group_path )
|
||||||
|
{
|
||||||
|
warn("malloc");
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
FILE* fp = fopen(group_path, "a");
|
||||||
|
if ( fp )
|
||||||
|
{
|
||||||
|
printf(" - Including /etc/default/group.d/* in /etc/group...\n");
|
||||||
|
if ( fprintf(fp, "include /etc/default/group.d/*\n") < 0 ||
|
||||||
|
fclose(fp) == EOF )
|
||||||
|
{
|
||||||
|
warn("%s", group_path);
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( errno != ENOENT )
|
||||||
|
{
|
||||||
|
warn("%s", group_path);
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
free(group_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void upgrade_finalize(const struct release* old_release,
|
void upgrade_finalize(const struct release* old_release,
|
||||||
|
|
|
@ -220,16 +220,23 @@ static bool passwd_check(const char* passwd_path,
|
||||||
warn("%s", passwd_path);
|
warn("%s", passwd_path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct passwd* pwd;
|
char* line = NULL;
|
||||||
while ( (errno = 0, pwd = fgetpwent(passwd)) )
|
size_t size = 0;
|
||||||
|
ssize_t length;
|
||||||
|
while ( 0 < (length = getline(&line, &size, passwd) ) )
|
||||||
{
|
{
|
||||||
if ( check(pwd, check_ctx) )
|
if ( line[size - 1] == '\n' )
|
||||||
|
line[--size] = '\0';
|
||||||
|
struct passwd pwd;
|
||||||
|
if ( scanpwent(line, &pwd) && check(&pwd, check_ctx) )
|
||||||
{
|
{
|
||||||
|
free(line);
|
||||||
fclose(passwd);
|
fclose(passwd);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( errno != 0 )
|
free(line);
|
||||||
|
if ( ferror(passwd) )
|
||||||
warn("%s", passwd_path);
|
warn("%s", passwd_path);
|
||||||
fclose(passwd);
|
fclose(passwd);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1025,10 +1032,13 @@ int main(void)
|
||||||
}
|
}
|
||||||
explicit_bzero(first, sizeof(first));
|
explicit_bzero(first, sizeof(first));
|
||||||
if ( !install_configurationf("etc/passwd", "a",
|
if ( !install_configurationf("etc/passwd", "a",
|
||||||
"root:%s:0:0:root:/root:sh\n", hash) )
|
"root:%s:0:0:root:/root:sh\n"
|
||||||
|
"include /etc/default/passwd.d/*\n", hash) )
|
||||||
continue;
|
continue;
|
||||||
textf("User '%s' added to /etc/passwd\n", "root");
|
textf("User '%s' added to /etc/passwd\n", "root");
|
||||||
if ( !install_configurationf("etc/group", "a", "root::0:root\n") )
|
if ( !install_configurationf("etc/group", "a",
|
||||||
|
"root::0:root\n"
|
||||||
|
"include /etc/default/group.d/*\n") )
|
||||||
continue;
|
continue;
|
||||||
install_skel("/root", 0, 0);
|
install_skel("/root", 0, 0);
|
||||||
textf("Group '%s' added to /etc/group.\n", "root");
|
textf("Group '%s' added to /etc/group.\n", "root");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Jonas 'Sortie' Termansen.
|
* Copyright (c) 2015, 2023 Jonas 'Sortie' Termansen.
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -155,24 +156,50 @@ int main(int argc, char* argv[])
|
||||||
if ( crypt_newhash(first, cipher, newhash, sizeof(newhash)) < 0 )
|
if ( crypt_newhash(first, cipher, newhash, sizeof(newhash)) < 0 )
|
||||||
err(1, "crypt_newhash");
|
err(1, "crypt_newhash");
|
||||||
explicit_bzero(first, sizeof(first));
|
explicit_bzero(first, sizeof(first));
|
||||||
|
|
||||||
// TODO: This is subject to races and is obviously an insecure design.
|
// TODO: This is subject to races and is obviously an insecure design.
|
||||||
// The backend and coordination of the passwd database should be moved
|
// The backend and coordination of the passwd database should be moved
|
||||||
// to its own daemon.
|
// to its own daemon.
|
||||||
|
FILE* in = fopen("/etc/passwd", "r");
|
||||||
|
if ( !in )
|
||||||
|
err(1, "/etc/passwd");
|
||||||
int fd = open("/etc/passwd.new", O_WRONLY | O_CREAT | O_EXCL, 0644);
|
int fd = open("/etc/passwd.new", O_WRONLY | O_CREAT | O_EXCL, 0644);
|
||||||
if ( fd < 0 )
|
if ( fd < 0 )
|
||||||
err(1, "/etc/passwd.new");
|
err(1, "/etc/passwd.new");
|
||||||
fchown(fd, 0, 0); // HACK.
|
fchown(fd, 0, 0); // HACK.
|
||||||
FILE* fp = fdopen(fd, "w");
|
FILE* fp = fdopen(fd, "w");
|
||||||
if ( !fp )
|
if ( !fp )
|
||||||
err(1, "fdopen");
|
|
||||||
setpwent();
|
|
||||||
while ( (errno = 0, pwd = getpwent()) )
|
|
||||||
{
|
{
|
||||||
|
unlink("/etc/passwd.new");
|
||||||
|
err(1, "fdopen");
|
||||||
|
}
|
||||||
|
char* line = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
ssize_t length;
|
||||||
|
bool found = false;
|
||||||
|
while ( 0 < (length = getline(&line, &size, in)) )
|
||||||
|
{
|
||||||
|
char* copy = strdup(line);
|
||||||
|
if ( !copy )
|
||||||
|
{
|
||||||
|
unlink("/etc/passwd.new");
|
||||||
|
err(1, "malloc");
|
||||||
|
}
|
||||||
|
if ( copy[length - 1] == '\n' )
|
||||||
|
copy[--length] = '\0';
|
||||||
|
struct passwd passwd;
|
||||||
|
if ( !scanpwent(copy, (pwd = &passwd)) )
|
||||||
|
{
|
||||||
|
fputs(line, fp);
|
||||||
|
free(copy);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
fputs(pwd->pw_name, fp);
|
fputs(pwd->pw_name, fp);
|
||||||
fputc(':', fp);
|
fputc(':', fp);
|
||||||
if ( !strcmp(pwd->pw_name, username) )
|
if ( !strcmp(pwd->pw_name, username) )
|
||||||
|
{
|
||||||
fputs(newhash, fp);
|
fputs(newhash, fp);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
fputs(pwd->pw_passwd, fp);
|
fputs(pwd->pw_passwd, fp);
|
||||||
fputc(':', fp);
|
fputc(':', fp);
|
||||||
|
@ -191,17 +218,25 @@ int main(int argc, char* argv[])
|
||||||
unlink("/etc/passwd.new");
|
unlink("/etc/passwd.new");
|
||||||
err(1, "/etc/passwd.new");
|
err(1, "/etc/passwd.new");
|
||||||
}
|
}
|
||||||
|
free(copy);
|
||||||
}
|
}
|
||||||
if ( errno != 0 )
|
free(line);
|
||||||
|
if ( ferror(in) )
|
||||||
{
|
{
|
||||||
unlink("/etc/passwd.new");
|
unlink("/etc/passwd.new");
|
||||||
err(1, "getpwent");
|
err(1, "/etc/passwd");
|
||||||
}
|
}
|
||||||
if ( fclose(fp) == EOF )
|
fclose(in);
|
||||||
|
if ( ferror(fp) || fclose(fp) == EOF )
|
||||||
{
|
{
|
||||||
unlink("/etc/passwd.new");
|
unlink("/etc/passwd.new");
|
||||||
err(1, "/etc/passwd.new");
|
err(1, "/etc/passwd.new");
|
||||||
}
|
}
|
||||||
|
if ( !found )
|
||||||
|
{
|
||||||
|
unlink("/etc/passwd.new");
|
||||||
|
errx(1, "user %s is not directly in /etc/passwd", username);
|
||||||
|
}
|
||||||
if ( rename("/etc/passwd.new", "/etc/passwd") < 0 )
|
if ( rename("/etc/passwd.new", "/etc/passwd") < 0 )
|
||||||
{
|
{
|
||||||
unlink("/etc/passwd.new");
|
unlink("/etc/passwd.new");
|
||||||
|
|
Loading…
Reference in New Issue