Make pw_scan(3) more compatible with getpwent(3) et. al. when processing
data from /etc/passwd rather than /etc/master.passwd. The libc getpwent(3) and related functions automatically read master.passwd when run by root, or passwd when run by a non-root user. When run by non- root, getpwent() copes with the missing data by setting the corresponding fields in the passwd struct to known values (zeroes for numbers, or a pointer to an empty string for literals). When libutil's pw_scan(3) was used to parse a line without the root-accessible data, it was leaving garbage in the corresponding fields. These changes rename the static pw_init() function used by getpwent() and friends to __pw_initpwd(), and move it into pw_scan.c so that common init code can be shared between libc and libutil. pw_scan(3) now calls __pw_initpwd() before __pw_scan(), just like the getpwent() family does, so that reading an arbitrary passwd file in either format and parsing it with pw_scan(3) returns the same results as getpwent(3) would. This also adds a new pw_initpwd(3) function to libutil, so that code which creates passwd structs from scratch in some manner that doesn't involve pw_scan() can initialize the struct to the values expected by lots of existing code, which doesn't expect to encounter NULL pointers or garbage values in some fields.
This commit is contained in:
parent
669a205547
commit
c125d4a078
@ -510,6 +510,7 @@ FBSDprivate_1.0 {
|
||||
__opendir2;
|
||||
__pause;
|
||||
_pause;
|
||||
__pw_initpwd; /* Used by (at least) libutil */
|
||||
__pw_scan; /* Used by (at least) libutil */
|
||||
__raise;
|
||||
_raise;
|
||||
|
@ -96,8 +96,6 @@ int __pw_match_entry(const char *, size_t, enum nss_lookup_type,
|
||||
const char *, uid_t);
|
||||
int __pw_parse_entry(char *, size_t, struct passwd *, int, int *errnop);
|
||||
|
||||
static void pwd_init(struct passwd *);
|
||||
|
||||
union key {
|
||||
const char *name;
|
||||
uid_t uid;
|
||||
@ -527,7 +525,7 @@ getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize,
|
||||
};
|
||||
int rv, ret_errno;
|
||||
|
||||
pwd_init(pwd);
|
||||
__pw_initpwd(pwd);
|
||||
ret_errno = 0;
|
||||
*result = NULL;
|
||||
rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwent_r", defaultsrc,
|
||||
@ -566,7 +564,7 @@ getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize,
|
||||
};
|
||||
int rv, ret_errno;
|
||||
|
||||
pwd_init(pwd);
|
||||
__pw_initpwd(pwd);
|
||||
ret_errno = 0;
|
||||
*result = NULL;
|
||||
rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwnam_r", defaultsrc,
|
||||
@ -605,7 +603,7 @@ getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize,
|
||||
};
|
||||
int rv, ret_errno;
|
||||
|
||||
pwd_init(pwd);
|
||||
__pw_initpwd(pwd);
|
||||
ret_errno = 0;
|
||||
*result = NULL;
|
||||
rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwuid_r", defaultsrc,
|
||||
@ -617,23 +615,6 @@ getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pwd_init(struct passwd *pwd)
|
||||
{
|
||||
static char nul[] = "";
|
||||
|
||||
memset(pwd, 0, sizeof(*pwd));
|
||||
pwd->pw_uid = (uid_t)-1; /* Considered least likely to lead to */
|
||||
pwd->pw_gid = (gid_t)-1; /* a security issue. */
|
||||
pwd->pw_name = nul;
|
||||
pwd->pw_passwd = nul;
|
||||
pwd->pw_class = nul;
|
||||
pwd->pw_gecos = nul;
|
||||
pwd->pw_dir = nul;
|
||||
pwd->pw_shell = nul;
|
||||
}
|
||||
|
||||
|
||||
static struct passwd pwd;
|
||||
static char *pwd_storage;
|
||||
static size_t pwd_storage_size;
|
||||
@ -1614,7 +1595,7 @@ compat_redispatch(struct compat_state *st, enum nss_lookup_type how,
|
||||
for (i = 0; i < (int)(nitems(dtab) - 1); i++)
|
||||
dtab[i].mdata = (void *)lookup_how;
|
||||
more:
|
||||
pwd_init(pwd);
|
||||
__pw_initpwd(pwd);
|
||||
switch (lookup_how) {
|
||||
case nss_lt_all:
|
||||
rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT,
|
||||
|
@ -65,6 +65,22 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
static int pw_big_ids_warning = 0;
|
||||
|
||||
void
|
||||
__pw_initpwd(struct passwd *pwd)
|
||||
{
|
||||
static char nul[] = "";
|
||||
|
||||
memset(pwd, 0, sizeof(*pwd));
|
||||
pwd->pw_uid = (uid_t)-1; /* Considered least likely to lead to */
|
||||
pwd->pw_gid = (gid_t)-1; /* a security issue. */
|
||||
pwd->pw_name = nul;
|
||||
pwd->pw_passwd = nul;
|
||||
pwd->pw_class = nul;
|
||||
pwd->pw_gecos = nul;
|
||||
pwd->pw_dir = nul;
|
||||
pwd->pw_shell = nul;
|
||||
}
|
||||
|
||||
int
|
||||
__pw_scan(char *bp, struct passwd *pw, int flags)
|
||||
{
|
||||
|
@ -35,4 +35,5 @@
|
||||
#define _PWSCAN_MASTER 0x01
|
||||
#define _PWSCAN_WARN 0x02
|
||||
|
||||
extern void __pw_initpwd(struct passwd *);
|
||||
extern int __pw_scan(char *, struct passwd *, int);
|
||||
|
@ -155,6 +155,7 @@ int pw_edit(int _notsetuid);
|
||||
int pw_equal(const struct passwd *_pw1, const struct passwd *_pw2);
|
||||
void pw_fini(void);
|
||||
int pw_init(const char *_dir, const char *_master);
|
||||
void pw_initpwd(struct passwd *_pw);
|
||||
char *pw_make(const struct passwd *_pw);
|
||||
char *pw_make_v7(const struct passwd *_pw);
|
||||
int pw_mkdb(const char *_user);
|
||||
|
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 02, 2015
|
||||
.Dd July 26, 2018
|
||||
.Dt PW_UTIL 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -59,6 +59,8 @@
|
||||
.Fn pw_fini "void"
|
||||
.Ft int
|
||||
.Fn pw_init "const char *dir" const char *master"
|
||||
.Ft void
|
||||
.Fn pw_initpwd "struct passwd *pw"
|
||||
.Ft "char *"
|
||||
.Fn pw_make "const struct passwd *pw"
|
||||
.Ft "char *"
|
||||
@ -179,7 +181,7 @@ if any.
|
||||
.Pp
|
||||
The
|
||||
.Fn pw_init
|
||||
initialize the static variable representing the path a password file.
|
||||
initializes the static variable representing the path to a password file.
|
||||
.Fa dir
|
||||
is the directory where the password file is located.
|
||||
If set to
|
||||
@ -194,6 +196,18 @@ it will default to
|
||||
.Pa master.passwd
|
||||
.Pp
|
||||
The
|
||||
.Fn pw_initpwd
|
||||
function initializes the
|
||||
.Vt passwd
|
||||
struct to canonical values.
|
||||
The entire structure is zeroed, then
|
||||
.Va pw_uid
|
||||
and
|
||||
.Va pw_gid
|
||||
are set to -1, and all string pointers are set to point at
|
||||
an internally-defined zero-length string.
|
||||
.Pp
|
||||
The
|
||||
.Fn pw_make
|
||||
function creates a properly formatted
|
||||
.Bx
|
||||
|
@ -652,8 +652,16 @@ pw_dup(const struct passwd *pw)
|
||||
#include "pw_scan.h"
|
||||
|
||||
/*
|
||||
* Wrapper around an internal libc function
|
||||
* Wrapper around some internal libc functions.
|
||||
*/
|
||||
|
||||
void
|
||||
pw_initpwd(struct passwd *pw)
|
||||
{
|
||||
|
||||
__pw_initpwd(pw);
|
||||
}
|
||||
|
||||
struct passwd *
|
||||
pw_scan(const char *line, int flags)
|
||||
{
|
||||
@ -662,6 +670,7 @@ pw_scan(const char *line, int flags)
|
||||
|
||||
if ((bp = strdup(line)) == NULL)
|
||||
return (NULL);
|
||||
__pw_initpwd(&pw);
|
||||
if (!__pw_scan(bp, &pw, flags)) {
|
||||
free(bp);
|
||||
return (NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user