static int remove_tcbdir (const char *user_name, uid_t user_id) { char *buf; int ret = 0; size_t bufsize = (sizeof TCB_DIR) + strlen (user_name) + 2; if (!getdef_bool ("USE_TCB")) { return 0; } buf = malloc (buflen); if (NULL == buf) { fprintf (stderr, _("%s: Can't allocate memory, " "tcb entry for %s not removed.\n"), Prog, user_name); return 1; } snprintf (buf, buflen, TCB_DIR "/%s", user_name); if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) { fprintf (stderr, _("%s: Cannot drop privileges: %s\n"), Prog, strerror (errno)); shadowtcb_gain_priv (); free (buf); return 1; } /* Only remove directory contents with dropped privileges. * We will regain them and remove the user's tcb directory afterwards. */ if (remove_tree (buf, false) != 0) { fprintf (stderr, _("%s: Cannot remove the content of %s: %s\n"), Prog, buf, strerror (errno)); shadowtcb_gain_priv (); free (buf); return 1; } shadowtcb_gain_priv (); free (buf); if (shadowtcb_remove (user_name) == SHADOWTCB_FAILURE) { fprintf (stderr, _("%s: Cannot remove tcb files for %s: %s\n"), Prog, user_name, strerror (errno)); ret = 1; } return ret; }
int spw_close (void) { int retval = 0; #ifdef WITH_TCB bool use_tcb = getdef_bool ("USE_TCB"); if (use_tcb && (shadowtcb_drop_priv () == SHADOWTCB_FAILURE)) { return 0; } #endif /* WITH_TCB */ retval = commonio_close (&shadow_db); #ifdef WITH_TCB if (use_tcb && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) { return 0; } #endif /* WITH_TCB */ return retval; }
int spw_unlock (void) { #ifdef WITH_TCB int retval = 0; if (!getdef_bool ("USE_TCB")) { #endif /* WITH_TCB */ return commonio_unlock (&shadow_db); #ifdef WITH_TCB } if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) { return 0; } if (ulckpwdf_tcb () == 0) { shadow_db.locked = 0; retval = 1; } if (shadowtcb_gain_priv () == SHADOWTCB_FAILURE) { return 0; } return retval; #endif /* WITH_TCB */ }
static void vipwedit (const char *file, int (*file_lock) (void), int (*file_unlock) (void)) { const char *editor; pid_t pid; struct stat st1, st2; int status; FILE *f; /* FIXME: the following should have variable sizes */ char filebackup[1024], fileedit[1024]; char *to_rename; snprintf (filebackup, sizeof filebackup, "%s-", file); #ifdef WITH_TCB if (tcb_mode) { if ( (mkdir (TCB_DIR "/" SHADOWTCB_SCRATCHDIR, 0700) != 0) && (errno != EEXIST)) { vipwexit (_("failed to create scratch directory"), errno, 1); } if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) { vipwexit (_("failed to drop privileges"), errno, 1); } snprintf (fileedit, sizeof fileedit, TCB_DIR "/" SHADOWTCB_SCRATCHDIR "/.vipw.shadow.%s", user); } else { #endif /* WITH_TCB */ snprintf (fileedit, sizeof fileedit, "%s.edit", file); #ifdef WITH_TCB } #endif /* WITH_TCB */ unlock = file_unlock; filename = file; fileeditname = fileedit; if (access (file, F_OK) != 0) { vipwexit (file, 1, 1); } #ifdef WITH_SELINUX /* if SE Linux is enabled then set the context of all new files to be the context of the file we are editing */ if (is_selinux_enabled () != 0) { security_context_t passwd_context=NULL; int ret = 0; if (getfilecon (file, &passwd_context) < 0) { vipwexit (_("Couldn't get file context"), errno, 1); } ret = setfscreatecon (passwd_context); freecon (passwd_context); if (0 != ret) { vipwexit (_("setfscreatecon () failed"), errno, 1); } } #endif /* WITH_SELINUX */ #ifdef WITH_TCB if (tcb_mode && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) { vipwexit (_("failed to gain privileges"), errno, 1); } #endif /* WITH_TCB */ if (file_lock () == 0) { vipwexit (_("Couldn't lock file"), errno, 5); } filelocked = true; #ifdef WITH_TCB if (tcb_mode && (shadowtcb_drop_priv () == SHADOWTCB_FAILURE)) { vipwexit (_("failed to drop privileges"), errno, 1); } #endif /* WITH_TCB */ /* edited copy has same owners, perm */ if (stat (file, &st1) != 0) { vipwexit (file, 1, 1); } f = fopen (file, "r"); if (NULL == f) { vipwexit (file, 1, 1); } #ifdef WITH_TCB if (tcb_mode && (shadowtcb_gain_priv () == SHADOWTCB_FAILURE)) vipwexit (_("failed to gain privileges"), errno, 1); #endif /* WITH_TCB */ if (create_backup_file (f, fileedit, &st1) != 0) { vipwexit (_("Couldn't make backup"), errno, 1); } (void) fclose (f); createedit = true; editor = getenv ("VISUAL"); if (NULL == editor) { editor = getenv ("EDITOR"); } if (NULL == editor) { editor = DEFAULT_EDITOR; } pid = fork (); if (-1 == pid) { vipwexit ("fork", 1, 1); } else if (0 == pid) { /* use the system() call to invoke the editor so that it accepts command line args in the EDITOR and VISUAL environment vars */ char *buf; buf = (char *) malloc (strlen (editor) + strlen (fileedit) + 2); snprintf (buf, strlen (editor) + strlen (fileedit) + 2, "%s %s", editor, fileedit); if (system (buf) != 0) { fprintf (stderr, "%s: %s: %s\n", progname, editor, strerror (errno)); exit (1); } else { exit (0); } } for (;;) { pid = waitpid (pid, &status, WUNTRACED); if ((pid != -1) && (WIFSTOPPED (status) != 0)) { /* The child (editor) was suspended. * Suspend vipw. */ kill (getpid (), SIGSTOP); /* wake child when resumed */ kill (pid, SIGCONT); } else { break; } } if ( (-1 == pid) || (WIFEXITED (status) == 0) || (WEXITSTATUS (status) != 0)) { vipwexit (editor, 1, 1); } if (stat (fileedit, &st2) != 0) { vipwexit (fileedit, 1, 1); } if (st1.st_mtime == st2.st_mtime) { vipwexit (0, 0, 0); } #ifdef WITH_SELINUX /* unset the fscreatecon */ if (is_selinux_enabled () != 0) { if (setfscreatecon (NULL) != 0) { vipwexit (_("setfscreatecon () failed"), errno, 1); } } #endif /* WITH_SELINUX */ /* * XXX - here we should check fileedit for errors; if there are any, * ask the user what to do (edit again, save changes anyway, or quit * without saving). Use pwck or grpck to do the check. --marekm */ createedit = false; #ifdef WITH_TCB if (tcb_mode) { f = fopen (fileedit, "r"); if (NULL == f) { vipwexit (_("failed to open scratch file"), errno, 1); } if (unlink (fileedit) != 0) { vipwexit (_("failed to unlink scratch file"), errno, 1); } if (shadowtcb_drop_priv () == SHADOWTCB_FAILURE) { vipwexit (_("failed to drop privileges"), errno, 1); } if (stat (file, &st1) != 0) { vipwexit (_("failed to stat edited file"), errno, 1); } to_rename = malloc (strlen (file) + 2); if (NULL == to_rename) { vipwexit (_("failed to allocate memory"), errno, 1); } snprintf (to_rename, strlen (file) + 2, "%s+", file); if (create_backup_file (f, to_rename, &st1) != 0) { free (to_rename); vipwexit (_("failed to create backup file"), errno, 1); } (void) fclose (f); } else { #endif /* WITH_TCB */ to_rename = fileedit; #ifdef WITH_TCB } #endif /* WITH_TCB */ unlink (filebackup); link (file, filebackup); if (rename (to_rename, file) == -1) { fprintf (stderr, _("%s: can't restore %s: %s (your changes are in %s)\n"), progname, file, strerror (errno), to_rename); #ifdef WITH_TCB if (tcb_mode) { free (to_rename); } #endif /* WITH_TCB */ vipwexit (0, 0, 1); } #ifdef WITH_TCB if (tcb_mode) { free (to_rename); if (shadowtcb_gain_priv () == SHADOWTCB_FAILURE) { vipwexit (_("failed to gain privileges"), errno, 1); } } #endif /* WITH_TCB */ if ((*file_unlock) () == 0) { fprintf (stderr, _("%s: failed to unlock %s\n"), progname, fileeditname); SYSLOG ((LOG_ERR, "failed to unlock %s", fileeditname)); /* continue */ } SYSLOG ((LOG_INFO, "file %s edited", fileeditname)); }