summaryrefslogtreecommitdiff
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)
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