shadow/libmisc/prefix_flag.c
Christian Göttsche 45bba0e190 Use strict prototypes
Function declarations with no argument declare functions taking an
arbitrary number of arguments. Use the special type void to declare
functions taking no argument.
2022-01-03 15:09:17 +01:00

341 lines
6.9 KiB
C

/*
* SPDX-FileCopyrightText: 2011 , Julian Pidancet
* SPDX-FileCopyrightText: 2011 , Nicolas François
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <config.h>
#ident "$Id$"
#include <stdio.h>
#include <assert.h>
#include "defines.h"
#include "prototypes.h"
/*@-exitarg@*/
#include "exitcodes.h"
#include "groupio.h"
#include "pwio.h"
#ifdef SHADOWGRP
#include "sgroupio.h"
#endif
#include "shadowio.h"
#ifdef ENABLE_SUBIDS
#include "subordinateio.h"
#endif /* ENABLE_SUBIDS */
#include "getdef.h"
#include "shadowlog.h"
static char *passwd_db_file = NULL;
static char *spw_db_file = NULL;
static char *group_db_file = NULL;
static char *sgroup_db_file = NULL;
static char *suid_db_file = NULL;
static char *sgid_db_file = NULL;
static char *def_conf_file = NULL;
static FILE* fp_pwent = NULL;
static FILE* fp_grent = NULL;
/*
* process_prefix_flag - prefix all paths if given the --prefix option
*
* This shall be called before accessing the passwd, group, shadow,
* gshadow, useradd's default, login.defs files (non exhaustive list)
* or authenticating the caller.
*
* The audit, syslog, or locale files shall be open before
*/
extern const char* process_prefix_flag (const char* short_opt, int argc, char **argv)
{
/*
* Parse the command line options.
*/
int i;
const char *prefix = NULL, *val;
for (i = 0; i < argc; i++) {
val = NULL;
if ( (strcmp (argv[i], "--prefix") == 0)
|| ((strncmp (argv[i], "--prefix=", 9) == 0)
&& (val = argv[i] + 9))
|| (strcmp (argv[i], short_opt) == 0)) {
if (NULL != prefix) {
fprintf (log_get_logfd(),
_("%s: multiple --prefix options\n"),
log_get_progname());
exit (E_BAD_ARG);
}
if (val) {
prefix = val;
} else if (i + 1 == argc) {
fprintf (log_get_logfd(),
_("%s: option '%s' requires an argument\n"),
log_get_progname(), argv[i]);
exit (E_BAD_ARG);
} else {
prefix = argv[++ i];
}
}
}
if (prefix != NULL) {
if ( prefix[0] == '\0' || !strcmp(prefix, "/"))
return ""; /* if prefix is "/" then we ignore the flag option */
/* should we prevent symbolic link from being used as a prefix? */
if ( prefix[0] != '/') {
fprintf (log_get_logfd(),
_("%s: prefix must be an absolute path\n"),
log_get_progname());
exit (E_BAD_ARG);
}
size_t len;
len = strlen(prefix) + strlen(PASSWD_FILE) + 2;
passwd_db_file = xmalloc(len);
snprintf(passwd_db_file, len, "%s/%s", prefix, PASSWD_FILE);
pw_setdbname(passwd_db_file);
len = strlen(prefix) + strlen(GROUP_FILE) + 2;
group_db_file = xmalloc(len);
snprintf(group_db_file, len, "%s/%s", prefix, GROUP_FILE);
gr_setdbname(group_db_file);
#ifdef SHADOWGRP
len = strlen(prefix) + strlen(SGROUP_FILE) + 2;
sgroup_db_file = xmalloc(len);
snprintf(sgroup_db_file, len, "%s/%s", prefix, SGROUP_FILE);
sgr_setdbname(sgroup_db_file);
#endif
#ifdef USE_NIS
__setspNIS(0); /* disable NIS for now, at least until it is properly supporting a "prefix" */
#endif
len = strlen(prefix) + strlen(SHADOW_FILE) + 2;
spw_db_file = xmalloc(len);
snprintf(spw_db_file, len, "%s/%s", prefix, SHADOW_FILE);
spw_setdbname(spw_db_file);
#ifdef ENABLE_SUBIDS
len = strlen(prefix) + strlen("/etc/subuid") + 2;
suid_db_file = xmalloc(len);
snprintf(suid_db_file, len, "%s/%s", prefix, "/etc/subuid");
sub_uid_setdbname(suid_db_file);
len = strlen(prefix) + strlen("/etc/subgid") + 2;
sgid_db_file = xmalloc(len);
snprintf(sgid_db_file, len, "%s/%s", prefix, "/etc/subgid");
sub_gid_setdbname(sgid_db_file);
#endif
#ifdef USE_ECONF
setdef_config_file(prefix);
#else
len = strlen(prefix) + strlen("/etc/login.defs") + 2;
def_conf_file = xmalloc(len);
snprintf(def_conf_file, len, "%s/%s", prefix, "/etc/login.defs");
setdef_config_file(def_conf_file);
#endif
}
if (prefix == NULL)
return "";
return prefix;
}
extern struct group *prefix_getgrnam(const char *name)
{
if (group_db_file) {
FILE* fg;
struct group * grp = NULL;
fg = fopen(group_db_file, "rt");
if (!fg)
return NULL;
while ((grp = fgetgrent(fg)) != NULL) {
if (!strcmp(name, grp->gr_name))
break;
}
fclose(fg);
return grp;
}
return getgrnam(name);
}
extern struct group *prefix_getgrgid(gid_t gid)
{
if (group_db_file) {
FILE* fg;
struct group * grp = NULL;
fg = fopen(group_db_file, "rt");
if (!fg)
return NULL;
while ((grp = fgetgrent(fg)) != NULL) {
if (gid == grp->gr_gid)
break;
}
fclose(fg);
return grp;
}
return getgrgid(gid);
}
extern struct passwd *prefix_getpwuid(uid_t uid)
{
if (passwd_db_file) {
FILE* fg;
struct passwd *pwd = NULL;
fg = fopen(passwd_db_file, "rt");
if (!fg)
return NULL;
while ((pwd = fgetpwent(fg)) != NULL) {
if (uid == pwd->pw_uid)
break;
}
fclose(fg);
return pwd;
}
else {
return getpwuid(uid);
}
}
extern struct passwd *prefix_getpwnam(const char* name)
{
if (passwd_db_file) {
FILE* fg;
struct passwd *pwd = NULL;
fg = fopen(passwd_db_file, "rt");
if (!fg)
return NULL;
while ((pwd = fgetpwent(fg)) != NULL) {
if (!strcmp(name, pwd->pw_name))
break;
}
fclose(fg);
return pwd;
}
else {
return getpwnam(name);
}
}
extern struct spwd *prefix_getspnam(const char* name)
{
if (spw_db_file) {
FILE* fg;
struct spwd *sp = NULL;
fg = fopen(spw_db_file, "rt");
if (!fg)
return NULL;
while ((sp = fgetspent(fg)) != NULL) {
if (!strcmp(name, sp->sp_namp))
break;
}
fclose(fg);
return sp;
}
else {
return getspnam(name);
}
}
extern void prefix_setpwent(void)
{
if (!passwd_db_file) {
setpwent();
return;
}
if (fp_pwent)
fclose (fp_pwent);
fp_pwent = fopen(passwd_db_file, "rt");
if (!fp_pwent)
return;
}
extern struct passwd* prefix_getpwent(void)
{
if (!passwd_db_file) {
return getpwent();
}
if (!fp_pwent) {
return NULL;
}
return fgetpwent(fp_pwent);
}
extern void prefix_endpwent(void)
{
if (!passwd_db_file) {
endpwent();
return;
}
if (fp_pwent)
fclose(fp_pwent);
fp_pwent = NULL;
}
extern void prefix_setgrent(void)
{
if (!group_db_file) {
setgrent();
return;
}
if (fp_grent)
fclose (fp_grent);
fp_grent = fopen(group_db_file, "rt");
if (!fp_grent)
return;
}
extern struct group* prefix_getgrent(void)
{
if (!group_db_file) {
return getgrent();
}
return fgetgrent(fp_grent);
}
extern void prefix_endgrent(void)
{
if (!group_db_file) {
endgrent();
return;
}
if (fp_grent)
fclose(fp_grent);
fp_grent = NULL;
}
extern struct group *prefix_getgr_nam_gid(const char *grname)
{
long long int gid;
char *endptr;
struct group *g;
if (NULL == grname) {
return NULL;
}
if (group_db_file) {
errno = 0;
gid = strtoll (grname, &endptr, 10);
if ( ('\0' != *grname)
&& ('\0' == *endptr)
&& (ERANGE != errno)
&& (gid == (gid_t)gid)) {
return prefix_getgrgid ((gid_t) gid);
}
g = prefix_getgrnam (grname);
return g ? __gr_dup(g) : NULL;
}
else
return getgr_nam_gid(grname);
}