From 74c17c71675a60edaa47b280b0b4e2190ddcaee0 Mon Sep 17 00:00:00 2001 From: Michael Vetter Date: Wed, 9 Nov 2022 14:41:31 +0100 Subject: [PATCH] Add support for skeleton files from /usr/etc/skel This patch is used by openSUSE to make useradd look for skeleton files in /usr/etc/skel additionally to /etc/skel in accordance with https://uapi-group.org/specifications/specs/base_directory_specification/ --- libmisc/copydir.c | 18 ++++++++++++++++++ src/useradd.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/libmisc/copydir.c b/libmisc/copydir.c index b692aa95..5e569b8f 100644 --- a/libmisc/copydir.c +++ b/libmisc/copydir.c @@ -448,6 +448,14 @@ static int copy_entry (const struct path_info *src, const struct path_info *dst, old_uid, new_uid, old_gid, new_gid); } + /* + * If the destination already exists do nothing. + * This is after the copy_dir above to still iterate into subdirectories. + */ + if (fstatat(dst->dirfd, dst->name, &sb, AT_SYMLINK_NOFOLLOW) != -1) { + return 0; + } + /* * Copy any symbolic links */ @@ -507,6 +515,7 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst, gid_t old_gid, gid_t new_gid) { int err = 0; + struct stat dst_sb; /* * Create a new target directory, make it owned by @@ -518,6 +527,15 @@ static int copy_dir (const struct path_info *src, const struct path_info *dst, return -1; } #endif /* WITH_SELINUX */ + /* + * If the destination is already a directory, don't change it + * but copy into it (recursively). + */ + if (fstatat(dst->dirfd, dst->name, &dst_sb, AT_SYMLINK_NOFOLLOW) == 0 && S_ISDIR(dst_sb.st_mode)) { + return (copy_tree (src, dst, false, reset_selinux, + old_uid, new_uid, old_gid, new_gid) != 0); + } + if ( (mkdirat (dst->dirfd, dst->name, 0700) != 0) || (chownat_if_needed (dst, statp, old_uid, new_uid, old_gid, new_gid) != 0) diff --git a/src/useradd.c b/src/useradd.c index 87abd6e3..d167e9e9 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -61,6 +61,9 @@ #ifndef SKEL_DIR #define SKEL_DIR "/etc/skel" #endif +#ifndef USRSKELDIR +#define USRSKELDIR "/usr/etc/skel" +#endif #ifndef USER_DEFAULTS_FILE #define USER_DEFAULTS_FILE "/etc/default/useradd" #define NEW_USER_FILE "/etc/default/nuaddXXXXXX" @@ -85,6 +88,7 @@ static const char *def_gname = "other"; static const char *def_home = "/home"; static const char *def_shell = "/bin/bash"; static const char *def_template = SKEL_DIR; +static const char *def_usrtemplate = USRSKELDIR; static const char *def_create_mail_spool = "yes"; static const char *def_log_init = "yes"; @@ -190,6 +194,7 @@ static bool home_added = false; #define DINACT "INACTIVE=" #define DEXPIRE "EXPIRE=" #define DSKEL "SKEL=" +#define DUSRSKEL "USRSKEL=" #define DCREATE_MAIL_SPOOL "CREATE_MAIL_SPOOL=" #define DLOG_INIT "LOG_INIT=" @@ -473,6 +478,29 @@ static void get_defaults (void) } } + /* + * Default Usr Skeleton information + */ + else if (MATCH (buf, DUSRSKEL)) { + if ('\0' == *cp) { + cp = USRSKELDIR; /* XXX warning: const */ + } + + if(prefix[0]) { + size_t len; + int wlen; + char* _def_usrtemplate; /* avoid const warning */ + + len = strlen(prefix) + strlen(cp) + 2; + _def_usrtemplate = xmalloc(len); + wlen = snprintf(_def_usrtemplate, len, "%s/%s", prefix, cp); + assert (wlen == (int) len -1); + def_usrtemplate = _def_usrtemplate; + } + else { + def_usrtemplate = xstrdup (cp); + } + } /* * Create by default user mail spool or not ? */ @@ -516,6 +544,7 @@ static void show_defaults (void) printf ("EXPIRE=%s\n", def_expire); printf ("SHELL=%s\n", def_shell); printf ("SKEL=%s\n", def_template); + printf ("USRSKEL=%s\n", def_usrtemplate); printf ("CREATE_MAIL_SPOOL=%s\n", def_create_mail_spool); printf ("LOG_INIT=%s\n", def_log_init); } @@ -545,6 +574,7 @@ static int set_defaults (void) bool out_expire = false; bool out_shell = false; bool out_skel = false; + bool out_usrskel = false; bool out_create_mail_spool = false; bool out_log_init = false; size_t len; @@ -661,6 +691,9 @@ static int set_defaults (void) } else if (!out_skel && MATCH (buf, DSKEL)) { fprintf (ofp, DSKEL "%s\n", def_template); out_skel = true; + } else if (!out_usrskel && MATCH (buf, DUSRSKEL)) { + fprintf (ofp, DUSRSKEL "%s\n", def_usrtemplate); + out_usrskel = true; } else if (!out_create_mail_spool && MATCH (buf, DCREATE_MAIL_SPOOL)) { fprintf (ofp, @@ -698,6 +731,8 @@ static int set_defaults (void) fprintf (ofp, DSHELL "%s\n", def_shell); if (!out_skel) fprintf (ofp, DSKEL "%s\n", def_template); + if (!out_usrskel) + fprintf (ofp, DUSRSKEL "%s\n", def_usrtemplate); if (!out_create_mail_spool) fprintf (ofp, DCREATE_MAIL_SPOOL "%s\n", def_create_mail_spool); @@ -2745,6 +2780,8 @@ int main (int argc, char **argv) if (home_added) { copy_tree (def_template, prefix_user_home, false, true, (uid_t)-1, user_id, (gid_t)-1, user_gid); + copy_tree (def_usrtemplate, prefix_user_home, false, false, + (uid_t)-1, user_id, (gid_t)-1, user_gid); } else { fprintf (stderr, _("%s: warning: the home directory %s already exists.\n"