entry validity before commits to databases.
* libmisc/fields.c, libmisc/Makefile.am, lib/fields.c,
lib/Makefile.am, po/POTFILES.in: fields.c moved from libmisc to
lib.
+2010-02-15 Nicolas François <nicolas.francois@centraliens.net>
+
+ * lib/groupio.c, lib/sgroupio.c, lib/shadowio.c, lib/pwio.c: Check
+ entry validity before commits to databases.
+ * libmisc/fields.c, libmisc/Makefile.am, lib/fields.c,
+ lib/Makefile.am, po/POTFILES.in: fields.c moved from libmisc to
+ lib.
+
2010-02-13 Nicolas François <nicolas.francois@centraliens.net>
* NEWS, src/chfn.c, src/chsh.c: Fix CVE-2011-0721: forbid \n in
encrypt.c \
exitcodes.h \
faillog.h \
+ fields.c \
fputsx.c \
getdef.c \
getdef.h \
const char *cp;
int err = 0;
+ if (NULL == cp) {
+ return -1;
+ }
+
/* For each character of field, search if it appears in the list
* of illegal characters. */
for (cp = field; '\0' != *cp; cp++) {
{
const struct group *gr = ent;
+ if ( (NULL == gr)
+ || (valid_field (gr->gr_name, ":\n") == -1)
+ || (valid_field (gr->gr_passwd, ":\n") == -1)
+ || (gr->gr_gid == (gid_t)-1)) {
+ return -1;
+ }
+
+ /* FIXME: fail also if gr->gr_mem == NULL ?*/
+ if (NULL != gr->gr_mem) {
+ size_t i;
+ for (i = 0; NULL != gr->gr_mem[i]; i++) {
+ if (valid_field (gr->gr_mem[i], ",:\n") == -1) {
+ return -1;
+ }
+ }
+ }
+
return (putgrent (gr, file) == -1) ? -1 : 0;
}
{
const struct passwd *pw = ent;
+ if ( (NULL == pw)
+ || (valid_field (pw->pw_name, ":\n") == -1)
+ || (valid_field (pw->pw_passwd, ":\n") == -1)
+ || (pw->pw_uid == (uid_t)-1)
+ || (pw->pw_gid == (gid_t)-1)
+ || (valid_field (pw->pw_gecos, ":\n") == -1)
+ || (valid_field (pw->pw_dir, ":\n") == -1)
+ || (valid_field (pw->pw_shell, ":\n") == -1)) {
+ return -1;
+ }
+
return (putpwent (pw, file) == -1) ? -1 : 0;
}
{
const struct sgrp *sg = ent;
+ if ( (NULL == sg)
+ || (valid_field (sg->sg_name, ":\n") == -1)
+ || (valid_field (sg->sg_passwd, ":\n") == -1)) {
+ return -1;
+ }
+
+ /* FIXME: fail also if sg->sg_adm == NULL ?*/
+ if (NULL != sg->sg_adm) {
+ size_t i;
+ for (i = 0; NULL != sg->sg_adm[i]; i++) {
+ if (valid_field (sg->sg_adm[i], ",:\n") == -1) {
+ return -1;
+ }
+ }
+ }
+
+ /* FIXME: fail also if sg->sg_mem == NULL ?*/
+ if (NULL != sg->sg_mem) {
+ size_t i;
+ for (i = 0; NULL != sg->sg_mem[i]; i++) {
+ if (valid_field (sg->sg_mem[i], ",:\n") == -1) {
+ return -1;
+ }
+ }
+ }
+
return (putsgent (sg, file) == -1) ? -1 : 0;
}
{
const struct spwd *sp = ent;
+ if ( (NULL == sp)
+ || (valid_field (sp->sp_namp, ":\n") == -1)
+ || (valid_field (sp->sp_pwdp, ":\n") == -1)) {
+ return -1;
+ }
+
return (putspent (sp, file) == -1) ? -1 : 0;
}
env.c \
failure.c \
failure.h \
- fields.c \
find_new_gid.c \
find_new_uid.c \
getdate.h \
#ifdef __linux__
static int check_status (const char *sname, uid_t uid);
-static int user_busy_processes (uid_t uid);
+static int user_busy_processes (const char *name, uid_t uid);
#else /* !__linux__ */
static int user_busy_utmp (const char *name);
#endif /* !__linux__ */
*/
#ifdef __linux__
/* On Linux, directly parse /proc */
- return user_busy_processes (uid);
+ return user_busy_processes (name, uid);
#else /* !__linux__ */
/* If we cannot rely on /proc, check is there is a record in utmp
* indicating that the user is still logged in */
continue;
}
+ fprintf (stderr,
+ _("%s: user %s is currently logged in\n"),
+ Prog, name);
return 1;
}
return 0;
}
-static int user_busy_processes (uid_t uid)
+static int user_busy_processes (const char *name, uid_t uid)
{
DIR *proc;
struct dirent *ent;
if (check_status (tmp_d_name, uid) != 0) {
(void) closedir (proc);
+ fprintf (stderr,
+ _("%s: user %s is currently used by process %d\n"),
+ Prog, name, pid);
return 1;
}
}
if (check_status (task_path+6, uid) != 0) {
(void) closedir (proc);
+ fprintf (stderr,
+ _("%s: user %s is currently used by process %d\n"),
+ Prog, name, pid);
return 1;
}
}
lib/commonio.c
lib/encrypt.c
+lib/fields.c
lib/fputsx.c
lib/getdef.c
lib/get_gid.c
libmisc/entry.c
libmisc/env.c
libmisc/failure.c
-libmisc/fields.c
libmisc/find_new_gid.c
libmisc/find_new_uid.c
libmisc/getgr_nam_gid.c