base+su+libc: Add support for a shadow file and use it by default
All checks were successful
Build and test / build (push) Successful in 1m39s
All checks were successful
Build and test / build (push) Successful in 1m39s
This commit is contained in:
parent
6968961d5c
commit
701dc30221
23
apps/su.cpp
23
apps/su.cpp
@ -3,6 +3,7 @@
|
|||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <os/ArgumentParser.h>
|
#include <os/ArgumentParser.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
#include <shadow.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -148,7 +149,25 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
signal(SIGTTOU, SIG_IGN);
|
signal(SIGTTOU, SIG_IGN);
|
||||||
|
|
||||||
if (!strcmp(entry->pw_passwd, "!"))
|
const char* passwd = entry->pw_passwd;
|
||||||
|
|
||||||
|
// If the user's password entry is 'x', read their password from the shadow file instead.
|
||||||
|
if (!strcmp(entry->pw_passwd, "x"))
|
||||||
|
{
|
||||||
|
struct spwd* sp = getspnam(name.chars());
|
||||||
|
|
||||||
|
if (!sp)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: user %s not found in shadow file!\n", argv[0], name.chars());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
endspent();
|
||||||
|
|
||||||
|
passwd = sp->sp_pwdp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(passwd, "!"))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: %s's password is disabled!\n", argv[0], entry->pw_name);
|
fprintf(stderr, "%s: %s's password is disabled!\n", argv[0], entry->pw_name);
|
||||||
return 1;
|
return 1;
|
||||||
@ -157,7 +176,7 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
char* pass = getpass();
|
char* pass = getpass();
|
||||||
if (!pass) return 1;
|
if (!pass) return 1;
|
||||||
|
|
||||||
if (strcmp(pass, entry->pw_passwd))
|
if (strcmp(pass, passwd))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s: wrong password!\n", argv[0]);
|
fprintf(stderr, "%s: wrong password!\n", argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
root:toor:0:0:Administrator:/:/usr/bin/sh
|
root:x:0:0:Administrator:/:/usr/bin/sh
|
||||||
wind:!:2:2:Window Manager:/:/usr/bin/init
|
wind:x:2:2:Window Manager:/:/usr/bin/init
|
||||||
selene:moon:1000:1000:User:/home/selene:/usr/bin/sh
|
selene:x:1000:1000:User:/home/selene:/usr/bin/sh
|
||||||
|
3
base/etc/shadow
Normal file
3
base/etc/shadow
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
root:toor:0:0:99999:7:::
|
||||||
|
wind:!:0:0:99999:7:::
|
||||||
|
selene:moon:0:0:99999:7:::
|
@ -27,6 +27,7 @@ set(SOURCES
|
|||||||
src/math.cpp
|
src/math.cpp
|
||||||
src/pty.cpp
|
src/pty.cpp
|
||||||
src/utmp.cpp
|
src/utmp.cpp
|
||||||
|
src/shadow.cpp
|
||||||
src/sys/stat.cpp
|
src/sys/stat.cpp
|
||||||
src/sys/mman.cpp
|
src/sys/mman.cpp
|
||||||
src/sys/wait.cpp
|
src/sys/wait.cpp
|
||||||
|
48
libc/include/shadow.h
Normal file
48
libc/include/shadow.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/* shadow.h: Password file parsing. */
|
||||||
|
|
||||||
|
#ifndef _SHADOW_H
|
||||||
|
#define _SHADOW_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct spwd
|
||||||
|
{
|
||||||
|
char* sp_namp;
|
||||||
|
char* sp_pwdp;
|
||||||
|
long sp_lstchg;
|
||||||
|
long sp_min;
|
||||||
|
long sp_max;
|
||||||
|
long sp_warn;
|
||||||
|
long sp_inact;
|
||||||
|
long sp_expire;
|
||||||
|
unsigned long sp_flag;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Read the next entry from the shadow file. */
|
||||||
|
struct spwd* getspent();
|
||||||
|
|
||||||
|
/* Find the entry with a matching username in the shadow file. */
|
||||||
|
struct spwd* getspnam(const char* name);
|
||||||
|
|
||||||
|
/* Read the next entry from the shadow file (reentrant version). */
|
||||||
|
int getspent_r(struct spwd* spbuf, char* buf, size_t buflen, struct spwd** spbufp);
|
||||||
|
|
||||||
|
/* Read the next entry from a shadow file (reentrant version). */
|
||||||
|
int fgetspent_r(FILE* stream, struct spwd* spbuf, char* buf, size_t buflen, struct spwd** spbufp);
|
||||||
|
|
||||||
|
/* Rewind the shadow file. */
|
||||||
|
void setspent(void);
|
||||||
|
|
||||||
|
/* End shadow file parsing. */
|
||||||
|
void endspent(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
116
libc/src/shadow.cpp
Normal file
116
libc/src/shadow.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
|
#include <shadow.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static struct spwd spwd;
|
||||||
|
static FILE* f { nullptr };
|
||||||
|
static char s_buf[4096];
|
||||||
|
|
||||||
|
extern char* _strtok_once(char* str, const char* delim);
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
struct spwd* getspent()
|
||||||
|
{
|
||||||
|
struct spwd* result;
|
||||||
|
|
||||||
|
getspent_r(&spwd, s_buf, sizeof(s_buf), &result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getspent_r(struct spwd* spbuf, char* buf, size_t buflen, struct spwd** spbufp)
|
||||||
|
{
|
||||||
|
*spbufp = nullptr;
|
||||||
|
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
f = fopen("/etc/shadow", "r");
|
||||||
|
if (!f) return 0;
|
||||||
|
fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fgetspent_r(f, spbuf, buf, buflen, spbufp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int fgetspent_r(FILE* stream, struct spwd* spbuf, char* buf, size_t buflen, struct spwd** spbufp)
|
||||||
|
{
|
||||||
|
*spbufp = nullptr;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char* rc = fgets(buf, buflen, stream);
|
||||||
|
if (!rc) return -1;
|
||||||
|
|
||||||
|
char* name = _strtok_once(rc, ":\n");
|
||||||
|
if (!name) continue;
|
||||||
|
|
||||||
|
char* passwd = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!passwd) continue;
|
||||||
|
|
||||||
|
char* lstchg = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!lstchg) continue;
|
||||||
|
|
||||||
|
char* min = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!min) continue;
|
||||||
|
|
||||||
|
char* max = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!max) continue;
|
||||||
|
|
||||||
|
char* warn = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!warn) continue;
|
||||||
|
|
||||||
|
char* inact = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!inact) continue;
|
||||||
|
|
||||||
|
char* expire = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!expire) continue;
|
||||||
|
|
||||||
|
char* flag = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!flag) continue;
|
||||||
|
|
||||||
|
spbuf->sp_namp = name;
|
||||||
|
spbuf->sp_pwdp = passwd;
|
||||||
|
spbuf->sp_lstchg = (long)strtol(lstchg, nullptr, 10);
|
||||||
|
spbuf->sp_min = (long)strtol(min, nullptr, 10);
|
||||||
|
spbuf->sp_max = (long)strtol(max, nullptr, 10);
|
||||||
|
spbuf->sp_warn = (long)strtol(warn, nullptr, 10);
|
||||||
|
spbuf->sp_inact = (long)strtol(inact, nullptr, 10);
|
||||||
|
spbuf->sp_expire = (long)strtol(expire, nullptr, 10);
|
||||||
|
spbuf->sp_flag = (unsigned long)strtoul(flag, nullptr, 10);
|
||||||
|
|
||||||
|
*spbufp = spbuf;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct spwd* getspnam(const char* name)
|
||||||
|
{
|
||||||
|
setspent();
|
||||||
|
|
||||||
|
struct spwd* entry;
|
||||||
|
|
||||||
|
while ((entry = getspent()))
|
||||||
|
{
|
||||||
|
if (!strcmp(entry->sp_namp, name)) { return entry; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setspent()
|
||||||
|
{
|
||||||
|
if (f) rewind(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void endspent()
|
||||||
|
{
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
fclose(f);
|
||||||
|
f = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,8 @@ cmake --install $LUNA_BUILD_DIR
|
|||||||
|
|
||||||
chmod a+s base/usr/bin/su
|
chmod a+s base/usr/bin/su
|
||||||
|
|
||||||
|
chmod 600 base/etc/shadow
|
||||||
|
|
||||||
mkdir -p base/home/selene
|
mkdir -p base/home/selene
|
||||||
|
|
||||||
mkdir -p base/dev
|
mkdir -p base/dev
|
||||||
|
Loading…
Reference in New Issue
Block a user