Skip to content

Commit

Permalink
Merge pull request #4 from xnox/master
Browse files Browse the repository at this point in the history
Make shadow more robust in hostile environments
  • Loading branch information
hallyn committed Nov 13, 2015
2 parents 4c4896f + bab349b commit e01bad7
Show file tree
Hide file tree
Showing 30 changed files with 141 additions and 87 deletions.
5 changes: 5 additions & 0 deletions etc/login.defs
Original file line number Diff line number Diff line change
Expand Up @@ -393,3 +393,8 @@ USERGROUPS_ENAB yes
#
#CREATE_HOME yes

#
# Force use shadow, even if shadow passwd & shadow group files are
# missing.
#
#FORCE_SHADOW yes
7 changes: 3 additions & 4 deletions lib/commonio.c
Original file line number Diff line number Diff line change
Expand Up @@ -968,11 +968,10 @@ int commonio_close (struct commonio_db *db)
} else {
/*
* Default permissions for new [g]shadow files.
* (passwd and group always exist...)
*/
sb.st_mode = 0400;
sb.st_uid = 0;
sb.st_gid = 0;
sb.st_mode = db->st_mode;
sb.st_uid = db->st_uid;
sb.st_gid = db->st_gid;
}

snprintf (buf, sizeof buf, "%s+", db->filename);
Expand Down
6 changes: 6 additions & 0 deletions lib/commonio.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ struct commonio_db {
#ifdef WITH_SELINUX
/*@null@*/security_context_t scontext;
#endif
/*
* Default permissions and owner for newly created data file.
*/
mode_t st_mode;
uid_t st_uid;
gid_t st_gid;
/*
* Head, tail, current position in linked list.
*/
Expand Down
80 changes: 51 additions & 29 deletions lib/getdef.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,32 @@ struct itemdef {
/*@null@*/char *value; /* value given, or NULL if no value */
};

#define PAMDEFS \
{"CHFN_AUTH", NULL}, \
{"CHSH_AUTH", NULL}, \
{"CRACKLIB_DICTPATH", NULL}, \
{"ENV_HZ", NULL}, \
{"ENVIRON_FILE", NULL}, \
{"ENV_TZ", NULL}, \
{"FAILLOG_ENAB", NULL}, \
{"FTMP_FILE", NULL}, \
{"ISSUE_FILE", NULL}, \
{"LASTLOG_ENAB", NULL}, \
{"LOGIN_STRING", NULL}, \
{"MAIL_CHECK_ENAB", NULL}, \
{"MOTD_FILE", NULL}, \
{"NOLOGINS_FILE", NULL}, \
{"OBSCURE_CHECKS_ENAB", NULL}, \
{"PASS_ALWAYS_WARN", NULL}, \
{"PASS_CHANGE_TRIES", NULL}, \
{"PASS_MAX_LEN", NULL}, \
{"PASS_MIN_LEN", NULL}, \
{"PORTTIME_CHECKS_ENAB", NULL}, \
{"QUOTAS_ENAB", NULL}, \
{"SU_WHEEL_ONLY", NULL}, \
{"ULIMIT", NULL},


#define NUMDEFS (sizeof(def_table)/sizeof(def_table[0]))
static struct itemdef def_table[] = {
{"CHFN_RESTRICT", NULL},
Expand Down Expand Up @@ -102,29 +128,7 @@ static struct itemdef def_table[] = {
{"USERDEL_CMD", NULL},
{"USERGROUPS_ENAB", NULL},
#ifndef USE_PAM
{"CHFN_AUTH", NULL},
{"CHSH_AUTH", NULL},
{"CRACKLIB_DICTPATH", NULL},
{"ENV_HZ", NULL},
{"ENVIRON_FILE", NULL},
{"ENV_TZ", NULL},
{"FAILLOG_ENAB", NULL},
{"FTMP_FILE", NULL},
{"ISSUE_FILE", NULL},
{"LASTLOG_ENAB", NULL},
{"LOGIN_STRING", NULL},
{"MAIL_CHECK_ENAB", NULL},
{"MOTD_FILE", NULL},
{"NOLOGINS_FILE", NULL},
{"OBSCURE_CHECKS_ENAB", NULL},
{"PASS_ALWAYS_WARN", NULL},
{"PASS_CHANGE_TRIES", NULL},
{"PASS_MAX_LEN", NULL},
{"PASS_MIN_LEN", NULL},
{"PORTTIME_CHECKS_ENAB", NULL},
{"QUOTAS_ENAB", NULL},
{"SU_WHEEL_ONLY", NULL},
{"ULIMIT", NULL},
PAMDEFS
#endif
#ifdef USE_SYSLOG
{"SYSLOG_SG_ENAB", NULL},
Expand All @@ -135,9 +139,17 @@ static struct itemdef def_table[] = {
{"TCB_SYMLINKS", NULL},
{"USE_TCB", NULL},
#endif
{"FORCE_SHADOW", NULL},
{NULL, NULL}
};

#define NUMKNOWNDEFS (sizeof(knowndef_table)/sizeof(knowndef_table[0]))
static struct itemdef knowndef_table[] = {
#ifdef USE_PAM
PAMDEFS
#endif
};

#ifndef LOGINDEFS
#define LOGINDEFS "/etc/login.defs"
#endif
Expand Down Expand Up @@ -397,10 +409,17 @@ static /*@observer@*/ /*@null@*/struct itemdef *def_find (const char *name)
* Item was never found.
*/

for (ptr = knowndef_table; NULL != ptr->name; ptr++) {
if (strcmp (ptr->name, name) == 0) {
goto out;
}
}
fprintf (stderr,
_("configuration error - unknown item '%s' (notify administrator)\n"),
name);
SYSLOG ((LOG_CRIT, "unknown configuration item `%s'", name));

out:
return (struct itemdef *) NULL;
}

Expand All @@ -416,23 +435,26 @@ static void def_load (void)
FILE *fp;
char buf[1024], *name, *value, *s;

/*
* Set the initialized flag.
* (do it early to prevent recursion in putdef_str())
*/
def_loaded = true;

/*
* Open the configuration definitions file.
*/
fp = fopen (def_fname, "r");
if (NULL == fp) {
if (errno == ENOENT)
return;

int err = errno;
SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]",
def_fname, strerror (err)));
exit (EXIT_FAILURE);
}

/*
* Set the initialized flag.
* (do it early to prevent recursion in putdef_str())
*/
def_loaded = true;

/*
* Go through all of the lines in the file.
*/
Expand Down
3 changes: 3 additions & 0 deletions lib/groupio.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ static /*@owned@*/struct commonio_db group_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
Expand Down
3 changes: 3 additions & 0 deletions lib/pwio.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ static struct commonio_db passwd_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
Expand Down
5 changes: 5 additions & 0 deletions lib/sgroupio.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,9 @@ static struct commonio_db gshadow_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0400, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
Expand All @@ -249,6 +252,8 @@ int sgr_setdbname (const char *filename)

bool sgr_file_present (void)
{
if (getdef_bool ("FORCE_SHADOW"))
return true;
return commonio_present (&gshadow_db);
}

Expand Down
5 changes: 5 additions & 0 deletions lib/shadowio.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ static struct commonio_db shadow_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif /* WITH_SELINUX */
0400, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
Expand All @@ -125,6 +128,8 @@ int spw_setdbname (const char *filename)

bool spw_file_present (void)
{
if (getdef_bool ("FORCE_SHADOW"))
return true;
return commonio_present (&shadow_db);
}

Expand Down
6 changes: 6 additions & 0 deletions lib/subordinateio.c
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,9 @@ static struct commonio_db subordinate_uid_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
Expand Down Expand Up @@ -619,6 +622,9 @@ static struct commonio_db subordinate_gid_db = {
#ifdef WITH_SELINUX
NULL, /* scontext */
#endif
0644, /* st_mode */
0, /* st_uid */
0, /* st_gid */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
Expand Down
4 changes: 2 additions & 2 deletions src/chage.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ static void open_files (bool readonly)
}
pw_locked = true;
}
if (pw_open (readonly ? O_RDONLY: O_RDWR) == 0) {
if (pw_open (readonly ? O_RDONLY: O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ()));
fail_exit (E_NOPERM);
Expand All @@ -613,7 +613,7 @@ static void open_files (bool readonly)
}
spw_locked = true;
}
if (spw_open (readonly ? O_RDONLY: O_RDWR) == 0) {
if (spw_open (readonly ? O_RDONLY: O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, spw_dbname ());
SYSLOG ((LOG_WARN, "cannot open %s", spw_dbname ()));
Expand Down
2 changes: 1 addition & 1 deletion src/chfn.c
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ static void update_gecos (const char *user, char *gecos)
fail_exit (E_NOPERM);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, pw_dbname ());
fail_exit (E_NOPERM);
Expand Down
4 changes: 2 additions & 2 deletions src/chgpasswd.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ static void open_files (void)
fail_exit (1);
}
gr_locked = true;
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, gr_dbname ());
fail_exit (1);
Expand All @@ -332,7 +332,7 @@ static void open_files (void)
fail_exit (1);
}
sgr_locked = true;
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"),
Prog, sgr_dbname ());
fail_exit (1);
Expand Down
4 changes: 2 additions & 2 deletions src/chpasswd.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ static void open_files (void)
fail_exit (1);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"), Prog, pw_dbname ());
fail_exit (1);
Expand All @@ -328,7 +328,7 @@ static void open_files (void)
fail_exit (1);
}
spw_locked = true;
if (spw_open (O_RDWR) == 0) {
if (spw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, spw_dbname ());
Expand Down
2 changes: 1 addition & 1 deletion src/chsh.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ static void update_shell (const char *user, char *newshell)
fail_exit (1);
}
pw_locked = true;
if (pw_open (O_RDWR) == 0) {
if (pw_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, pw_dbname ());
SYSLOG ((LOG_WARN, "cannot open %s", pw_dbname ()));
fail_exit (1);
Expand Down
4 changes: 2 additions & 2 deletions src/gpasswd.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ static void open_files (void)

add_cleanup (log_gpasswd_failure_system, NULL);

if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, gr_dbname ());
Expand All @@ -380,7 +380,7 @@ static void open_files (void)

#ifdef SHADOWGRP
if (is_shadowgrp) {
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());
Expand Down
4 changes: 2 additions & 2 deletions src/groupadd.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,15 +346,15 @@ static void open_files (void)
add_cleanup (cleanup_report_add_group, group_name);

/* And now open the databases */
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
SYSLOG ((LOG_WARN, "cannot open %s", gr_dbname ()));
exit (E_GRP_UPDATE);
}

#ifdef SHADOWGRP
if (is_shadow_grp) {
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());
Expand Down
4 changes: 2 additions & 2 deletions src/groupdel.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ static void open_files (void)
add_cleanup (cleanup_report_del_group, group_name);

/* An now open the databases */
if (gr_open (O_RDWR) == 0) {
if (gr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, gr_dbname ());
Expand All @@ -257,7 +257,7 @@ static void open_files (void)
}
#ifdef SHADOWGRP
if (is_shadow_grp) {
if (sgr_open (O_RDWR) == 0) {
if (sgr_open (O_CREAT | O_RDWR) == 0) {
fprintf (stderr,
_("%s: cannot open %s\n"),
Prog, sgr_dbname ());
Expand Down
4 changes: 2 additions & 2 deletions src/groupmems.c
Original file line number Diff line number Diff line change
Expand Up @@ -536,14 +536,14 @@ static void open_files (void)
#endif
}

if (gr_open (list ? O_RDONLY : O_RDWR) == 0) {
if (gr_open (list ? O_RDONLY : O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
fail_exit (EXIT_GROUP_FILE);
}

#ifdef SHADOWGRP
if (is_shadowgrp) {
if (sgr_open (list ? O_RDONLY : O_RDWR) == 0) {
if (sgr_open (list ? O_RDONLY : O_CREAT | O_RDWR) == 0) {
fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ());
fail_exit (EXIT_GROUP_FILE);
}
Expand Down
Loading

0 comments on commit e01bad7

Please sign in to comment.