about summary refs log tree commit diff
path: root/nss/getent.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2015-10-02 11:34:13 +0200
committerFlorian Weimer <fweimer@redhat.com>2015-10-02 11:34:13 +0200
commit676599b36a92f3c201c5682ee7a5caddd9f370a4 (patch)
tree6860752c26ccab76ee9db5e60ff465d1edf25feb /nss/getent.c
parentb0f81637d5bda47be93bac34b68f429a12979321 (diff)
downloadglibc-676599b36a92f3c201c5682ee7a5caddd9f370a4.tar.gz
glibc-676599b36a92f3c201c5682ee7a5caddd9f370a4.tar.xz
glibc-676599b36a92f3c201c5682ee7a5caddd9f370a4.zip
Harden putpwent, putgrent, putspent, putspent against injection [BZ #18724]
This prevents injection of ':' and '\n' into output functions which
use the NSS files database syntax.  Critical fields (user/group names
and file system paths) are checked strictly.  For backwards
compatibility, the GECOS field is rewritten instead.

The getent program is adjusted to use the put*ent functions in libc,
instead of local copies.  This changes the behavior of getent if user
names start with '-' or '+'.
Diffstat (limited to 'nss/getent.c')
-rw-r--r--nss/getent.c76
1 files changed, 8 insertions, 68 deletions
diff --git a/nss/getent.c b/nss/getent.c
index 34df8487a9..996d378af7 100644
--- a/nss/getent.c
+++ b/nss/getent.c
@@ -184,20 +184,8 @@ ethers_keys (int number, char *key[])
 static void
 print_group (struct group *grp)
 {
-  unsigned int i = 0;
-
-  printf ("%s:%s:%lu:", grp->gr_name ? grp->gr_name : "",
-	  grp->gr_passwd ? grp->gr_passwd : "",
-	  (unsigned long int) grp->gr_gid);
-
-  while (grp->gr_mem[i] != NULL)
-    {
-      fputs_unlocked (grp->gr_mem[i], stdout);
-      ++i;
-      if (grp->gr_mem[i] != NULL)
-	putchar_unlocked (',');
-    }
-  putchar_unlocked ('\n');
+  if (putgrent (grp, stdout) != 0)
+    fprintf (stderr, "error writing group entry: %m\n");
 }
 
 static int
@@ -241,32 +229,8 @@ group_keys (int number, char *key[])
 static void
 print_gshadow (struct sgrp *sg)
 {
-  unsigned int i = 0;
-
-  printf ("%s:%s:",
-	  sg->sg_namp ? sg->sg_namp : "",
-	  sg->sg_passwd ? sg->sg_passwd : "");
-
-  while (sg->sg_adm[i] != NULL)
-    {
-      fputs_unlocked (sg->sg_adm[i], stdout);
-      ++i;
-      if (sg->sg_adm[i] != NULL)
-	putchar_unlocked (',');
-    }
-
-  putchar_unlocked (':');
-
-  i = 0;
-  while (sg->sg_mem[i] != NULL)
-    {
-      fputs_unlocked (sg->sg_mem[i], stdout);
-      ++i;
-      if (sg->sg_mem[i] != NULL)
-	putchar_unlocked (',');
-    }
-
-  putchar_unlocked ('\n');
+  if (putsgent (sg, stdout) != 0)
+    fprintf (stderr, "error writing gshadow entry: %m\n");
 }
 
 static int
@@ -603,14 +567,8 @@ networks_keys (int number, char *key[])
 static void
 print_passwd (struct passwd *pwd)
 {
-  printf ("%s:%s:%lu:%lu:%s:%s:%s\n",
-	  pwd->pw_name ? pwd->pw_name : "",
-	  pwd->pw_passwd ? pwd->pw_passwd : "",
-	  (unsigned long int) pwd->pw_uid,
-	  (unsigned long int) pwd->pw_gid,
-	  pwd->pw_gecos ? pwd->pw_gecos : "",
-	  pwd->pw_dir ? pwd->pw_dir : "",
-	  pwd->pw_shell ? pwd->pw_shell : "");
+  if (putpwent (pwd, stdout) != 0)
+    fprintf (stderr, "error writing passwd entry: %m\n");
 }
 
 static int
@@ -812,26 +770,8 @@ services_keys (int number, char *key[])
 static void
 print_shadow (struct spwd *sp)
 {
-  printf ("%s:%s:",
-	  sp->sp_namp ? sp->sp_namp : "",
-	  sp->sp_pwdp ? sp->sp_pwdp : "");
-
-#define SHADOW_FIELD(n) \
-  if (sp->n == -1)							      \
-    putchar_unlocked (':');						      \
-  else									      \
-    printf ("%ld:", sp->n)
-
-  SHADOW_FIELD (sp_lstchg);
-  SHADOW_FIELD (sp_min);
-  SHADOW_FIELD (sp_max);
-  SHADOW_FIELD (sp_warn);
-  SHADOW_FIELD (sp_inact);
-  SHADOW_FIELD (sp_expire);
-  if (sp->sp_flag == ~0ul)
-    putchar_unlocked ('\n');
-  else
-    printf ("%lu\n", sp->sp_flag);
+  if (putspent (sp, stdout) != 0)
+    fprintf (stderr, "error writing shadow entry: %m\n");
 }
 
 static int