/* * private_getspnam_r() * * A private implementation of getspnam_r which does *not* fall back to * other services possibly defined in nsswitch.conf. * * Behaves like getspnam_r(). Since we use fgetspent_t(), all numeric * fields that are undefined in /etc/shadow will be set to -1. * */ struct spwd * private_getspnam_r(const char *name, struct spwd *result, char *buffer, int buflen) { FILE *fp; int found; fp = fopen(SHADOW, "rF"); if (fp == NULL) return (NULL); found = 0; while (!found && fgetspent_r(fp, result, buffer, buflen) != NULL) { if (strcmp(name, result->sp_namp) == 0) found = 1; } (void) fclose(fp); if (!found) { (void) memset(buffer, 0, buflen); (void) memset(result, 0, sizeof (*result)); return (NULL); } return (result); }
struct spwd * fgetspent(FILE *f) { nss_XbyY_buf_t *b = get_spbuf(); return (b == NULL ? NULL : fgetspent_r(f, b->result, b->buffer, b->buflen)); }
struct spwd *fgetspent(FILE * file) { int ret; static char line_buff[PWD_BUFFER_SIZE]; static struct spwd spwd; struct spwd *result; LOCK; if ((ret=fgetspent_r(file, &spwd, line_buff, sizeof(line_buff), &result)) == 0) { UNLOCK; return &spwd; } UNLOCK; __set_errno(ret); return NULL; }
static gboolean fgetspent_callback (void (* callback) (struct spwd *, gpointer), gpointer user_data) { struct spwd spb; struct spwd *sp; gchar *buffer; gsize buflen; FILE *fp; int ret; fp = fopen (cockpit_bridge_path_shadow, "r"); if (fp == NULL) { g_message ("unable to open %s: %s", cockpit_bridge_path_shadow, g_strerror (errno)); return FALSE; } buflen = 16 * 1024; buffer = g_malloc (buflen); for (;;) { ret = fgetspent_r (fp, &spb, buffer, buflen, &sp); if (ret == 0) { callback (sp, user_data); } else { g_free (buffer); fclose (fp); return (ret == ENOENT); } } }
/* * files_update_shadow(char *name, struct spwd *spwd) * * update the shadow password file SHADOW to contain the spwd structure * "spwd" for user "name" */ int files_update_shadow(char *name, struct spwd *spwd) { struct stat64 stbuf; FILE *dst; FILE *src; struct spwd cur; char buf[SPW_SCRATCH_SIZE]; int tempfd; mode_t filemode; int result = -1; int err = PWU_SUCCESS; /* Mode of the shadow file should be 400 or 000 */ if (stat64(SHADOW, &stbuf) < 0) { err = PWU_STAT_FAILED; goto shadow_exit; } /* copy mode from current shadow file (0400 or 0000) */ filemode = stbuf.st_mode & S_IRUSR; /* * we can't specify filemodes to fopen(), and we SHOULD NOT * set umask in multi-thread safe libraries, so we use * a combination of open() and fdopen() */ tempfd = open(SHADTEMP, O_WRONLY|O_CREAT|O_TRUNC, filemode); if (tempfd < 0) { err = PWU_OPEN_FAILED; goto shadow_exit; } (void) fchown(tempfd, (uid_t)0, stbuf.st_gid); if ((dst = fdopen(tempfd, "wF")) == NULL) { err = PWU_OPEN_FAILED; goto shadow_exit; } if ((src = fopen(SHADOW, "rF")) == NULL) { err = PWU_OPEN_FAILED; (void) fclose(dst); (void) unlink(SHADTEMP); goto shadow_exit; } /* * copy old shadow to temporary file while replacing the entry * that matches "name". */ while (fgetspent_r(src, &cur, buf, sizeof (buf)) != NULL) { if (strcmp(cur.sp_namp, name) == 0) result = putspent(spwd, dst); else result = putspent(&cur, dst); if (result != 0) { err = PWU_WRITE_FAILED; (void) fclose(src); (void) fclose(dst); goto shadow_exit; } } (void) fclose(src); if (fclose(dst) != 0) { /* * Something went wrong (ENOSPC for example). Don't * use the resulting temporary file! */ err = PWU_CLOSE_FAILED; (void) unlink(SHADTEMP); goto shadow_exit; } /* * Rename stmp to shadow: * 1. make sure /etc/oshadow is gone * 2. ln /etc/shadow /etc/oshadow * 3. mv /etc/stmp /etc/shadow */ if (unlink(OSHADOW) && access(OSHADOW, 0) == 0) { err = PWU_UPDATE_FAILED; (void) unlink(SHADTEMP); goto shadow_exit; } if (link(SHADOW, OSHADOW) == -1) { err = PWU_UPDATE_FAILED; (void) unlink(SHADTEMP); goto shadow_exit; } if (rename(SHADTEMP, SHADOW) == -1) { err = PWU_UPDATE_FAILED; (void) unlink(SHADTEMP); goto shadow_exit; } (void) unlink(OSHADOW); shadow_exit: return (err); }