17 #include <selinux/selinux.h>
18 static security_context_t old_context = NULL;
22 /* local function prototypes */
23 static int lrename (const char *, const char *);
24 static int check_link_count (const char *);
25 static int do_lock_file (const char *, const char *);
26 static FILE *fopen_set_perms (const char *, const char *, const struct stat *);
27 static int create_backup (const char *, FILE *);
28 static void free_linked_list (struct commonio_db *);
29 static void add_one_entry (struct commonio_db *, struct commonio_entry *);
30 static int name_is_nis (const char *);
31 static int write_all (const struct commonio_db *);
32 static struct commonio_entry *find_entry_by_name (struct commonio_db *,
34 static struct commonio_entry *next_entry_by_name (struct commonio_db *,
35 struct commonio_entry *pos,
38 static int lock_count = 0;
39 static int nscd_need_reload = 0;
42 * Simple rename(P) alternative that attempts to rename to symlink
45 int lrename (const char *old, const char *new)
48 char resolved_path[PATH_MAX];
53 if (lstat (new, &sb) == 0 && S_ISLNK (sb.st_mode)) {
54 if (realpath (new, resolved_path) == NULL) {
55 perror ("realpath in lrename()");
61 res = rename (old, new);
65 static int check_link_count (const char *file)
69 if (stat (file, &sb) != 0)
79 static int do_lock_file (const char *file, const char *lock)
87 if ((fd = open (file, O_CREAT | O_EXCL | O_WRONLY, 0600)) == -1)
91 snprintf (buf, sizeof buf, "%d", pid);
92 len = strlen (buf) + 1;
93 if (write (fd, buf, len) != len) {
100 if (link (file, lock) == 0) {
101 retval = check_link_count (file);
106 if ((fd = open (lock, O_RDWR)) == -1) {
111 len = read (fd, buf, sizeof (buf) - 1);
119 if ((pid = strtol (buf, (char **) 0, 10)) == 0) {
124 if (kill (pid, 0) == 0) {
129 if (unlink (lock) != 0) {
135 if (link (file, lock) == 0 && check_link_count (file))
143 static FILE *fopen_set_perms (const char *name, const char *mode,
144 const struct stat *sb)
150 fp = fopen (name, mode);
156 if (fchown (fileno (fp), sb->st_uid, sb->st_gid))
159 if (chown (name, sb->st_mode))
164 if (fchmod (fileno (fp), sb->st_mode & 0664))
167 if (chmod (name, sb->st_mode & 0664))
179 static int create_backup (const char *backup, FILE * fp)
187 if (fstat (fileno (fp), &sb))
191 bkfp = fopen (backup, "w");
196 /* TODO: faster copy, not one-char-at-a-time. --marekm */
198 if (fseek (fp, 0, SEEK_SET) == 0)
199 while ((c = getc (fp)) != EOF) {
200 if (putc (c, bkfp) == EOF)
203 if (c != EOF || ferror (fp) || fflush (bkfp)) {
210 ub.actime = sb.st_atime;
211 ub.modtime = sb.st_mtime;
217 static void free_linked_list (struct commonio_db *db)
219 struct commonio_entry *p;
229 db->ops->free (p->eptr);
237 int commonio_setname (struct commonio_db *db, const char *name)
239 snprintf (db->filename, sizeof (db->filename), "%s", name);
244 int commonio_present (const struct commonio_db *db)
246 return (access (db->filename, F_OK) == 0);
250 int commonio_lock_nowait (struct commonio_db *db)
258 snprintf (file, sizeof file, "%s.%ld", db->filename, (long) getpid ());
259 snprintf (lock, sizeof lock, "%s.lock", db->filename);
260 if (do_lock_file (file, lock)) {
269 int commonio_lock (struct commonio_db *db)
273 * only if the system libc has a real lckpwdf() - the one from
274 * lockpw.c calls us and would cause infinite recursion!
278 * Call lckpwdf() on the first lock.
279 * If it succeeds, call *_lock() only once
280 * (no retries, it should always succeed).
282 if (lock_count == 0) {
283 if (lckpwdf () == -1)
284 return 0; /* failure */
287 if (commonio_lock_nowait (db))
288 return 1; /* success */
291 return 0; /* failure */
296 * lckpwdf() not used - do it the old way.
299 #define LOCK_TRIES 15
305 for (i = 0; i < LOCK_TRIES; i++) {
307 sleep (LOCK_SLEEP); /* delay between retries */
308 if (commonio_lock_nowait (db))
309 return 1; /* success */
310 /* no unnecessary retries on "permission denied" errors */
314 return 0; /* failure */
318 static void dec_lock_count (void)
320 if (lock_count > 0) {
322 if (lock_count == 0) {
323 /* Tell nscd when lock count goes to zero,
324 if any of the files were changed. */
325 if (nscd_need_reload) {
326 nscd_flush_cache ("passwd");
327 nscd_flush_cache ("group");
328 nscd_need_reload = 0;
338 int commonio_unlock (struct commonio_db *db)
344 if (!commonio_close (db)) {
352 * Unlock in reverse order: remove the lock file,
353 * then call ulckpwdf() (if used) on last unlock.
356 snprintf (lock, sizeof lock, "%s.lock", db->filename);
365 static void add_one_entry (struct commonio_db *db, struct commonio_entry *p)
377 static int name_is_nis (const char *n)
379 return (n[0] == '+' || n[0] == '-');
384 * New entries are inserted before the first NIS entry. Order is preserved
385 * when db is written out.
387 #ifndef KEEP_NIS_AT_END
388 #define KEEP_NIS_AT_END 1
392 static void add_one_entry_nis (struct commonio_db *, struct commonio_entry *);
395 * Insert an entry between the regular entries, and the NIS entries.
398 add_one_entry_nis (struct commonio_db *db, struct commonio_entry *newp)
400 struct commonio_entry *p;
402 for (p = db->head; p; p = p->next) {
404 (p->eptr ? db->ops->getname (p->eptr) : p->line)) {
406 newp->prev = p->prev;
408 p->prev->next = newp;
415 add_one_entry (db, newp);
417 #endif /* KEEP_NIS_AT_END */
419 /* Initial buffer size, as well as increment if not sufficient
420 (for reading very long lines in group files). */
423 int commonio_open (struct commonio_db *db, int mode)
428 struct commonio_entry *p;
436 if (db->isopen || (mode != O_RDONLY && mode != O_RDWR)) {
440 db->readonly = (mode == O_RDONLY);
441 if (!db->readonly && !db->locked) {
446 db->head = db->tail = db->cursor = NULL;
449 db->fp = fopen (db->filename, db->readonly ? "r" : "r+");
452 * If O_CREAT was specified and the file didn't exist, it will be
453 * created by commonio_close(). We have no entries to read yet. --marekm
456 if ((flags & O_CREAT) && errno == ENOENT) {
463 /* Do not inherit fd in spawned processes (e.g. nscd) */
464 fcntl(fileno(db->fp), F_SETFD, FD_CLOEXEC);
468 if ((is_selinux_enabled () > 0) && (!db->readonly)) {
469 if (fgetfilecon (fileno (db->fp), &db->scontext) < 0) {
476 buf = (char *) malloc (buflen);
480 while (db->ops->fgets (buf, buflen, db->fp)) {
481 while (!(cp = strrchr (buf, '\n')) && !feof (db->fp)) {
485 cp = (char *) realloc (buf, buflen);
490 db->ops->fgets (buf + len, buflen - len, db->fp);
492 if ((cp = strrchr (buf, '\n')))
495 if (!(line = strdup (buf)))
498 if (name_is_nis (line)) {
500 } else if ((eptr = db->ops->parse (line))) {
501 eptr = db->ops->dup (eptr);
506 p = (struct commonio_entry *) malloc (sizeof *p);
514 add_one_entry (db, p);
522 if (db->ops->open_hook && !db->ops->open_hook ())
530 db->ops->free (eptr);
539 free_linked_list (db);
541 if (db->scontext != NULL) {
542 freecon (db->scontext);
553 * Sort given db according to cmp function (usually compares uids)
556 commonio_sort (struct commonio_db *db, int (*cmp) (const void *, const void *))
558 struct commonio_entry **entries, *ptr;
561 for (ptr = db->head; ptr; ptr = ptr->next)
567 entries = malloc (n * sizeof (struct commonio_entry *));
572 for (ptr = db->head; ptr; ptr = ptr->next)
574 qsort (entries, n, sizeof (struct commonio_entry *), cmp);
576 db->head = entries[0];
577 db->tail = entries[--n];
578 db->head->prev = NULL;
579 db->head->next = entries[1];
580 db->tail->prev = entries[n - 1];
581 db->tail->next = NULL;
583 for (i = 1; i < n; i++) {
584 entries[i]->prev = entries[i - 1];
585 entries[i]->next = entries[i + 1];
595 * Sort entries in db according to order in another.
597 int commonio_sort_wrt (struct commonio_db *shadow, struct commonio_db *passwd)
599 struct commonio_entry *head = NULL, *pw_ptr, *spw_ptr;
602 if (!shadow || !shadow->head)
605 for (pw_ptr = passwd->head; pw_ptr; pw_ptr = pw_ptr->next) {
606 if (pw_ptr->eptr == NULL)
608 name = passwd->ops->getname (pw_ptr->eptr);
609 for (spw_ptr = shadow->head; spw_ptr; spw_ptr = spw_ptr->next)
610 if (strcmp (name, shadow->ops->getname (spw_ptr->eptr))
615 commonio_del_entry (shadow, spw_ptr);
616 spw_ptr->next = head;
620 for (spw_ptr = head; spw_ptr; spw_ptr = head) {
624 shadow->head->prev = spw_ptr;
625 spw_ptr->next = shadow->head;
626 shadow->head = spw_ptr;
629 shadow->head->prev = NULL;
636 * write_all - Write the database to its file.
638 * It returns 0 if all the entries could be writen correctly.
640 static int write_all (const struct commonio_db *db)
642 const struct commonio_entry *p;
645 for (p = db->head; p; p = p->next) {
648 if (db->ops->put (eptr, db->fp))
650 } else if (p->line) {
651 if (db->ops->fputs (p->line, db->fp) == EOF)
653 if (putc ('\n', db->fp) == EOF)
661 int commonio_close (struct commonio_db *db)
673 if (!db->changed || db->readonly) {
679 if (db->ops->close_hook && !db->ops->close_hook ())
682 memzero (&sb, sizeof sb);
684 if (fstat (fileno (db->fp), &sb)) {
690 if (db->scontext != NULL) {
691 if (getfscreatecon (&old_context) < 0) {
695 if (setfscreatecon (db->scontext) < 0) {
702 * Create backup file.
704 snprintf (buf, sizeof buf, "%s-", db->filename);
706 if (create_backup (buf, db->fp))
718 * Default permissions for new [g]shadow files.
719 * (passwd and group always exist...)
726 snprintf (buf, sizeof buf, "%s+", db->filename);
728 db->fp = fopen_set_perms (buf, "w", &sb);
738 if (fsync (fileno (db->fp)))
753 if (lrename (buf, db->filename))
756 nscd_need_reload = 1;
763 if (db->scontext != NULL) {
764 if (setfscreatecon (old_context) < 0) {
767 if (old_context != NULL) {
768 freecon (old_context);
771 freecon (db->scontext);
775 free_linked_list (db);
779 static struct commonio_entry *next_entry_by_name (struct commonio_db *db,
780 struct commonio_entry *pos,
783 struct commonio_entry *p;
789 for (p = pos; p; p = p->next) {
791 if (ep && strcmp (db->ops->getname (ep), name) == 0)
797 static struct commonio_entry *find_entry_by_name (struct commonio_db *db,
800 return next_entry_by_name(db, db->head, name);
804 int commonio_update (struct commonio_db *db, const void *eptr)
806 struct commonio_entry *p;
809 if (!db->isopen || db->readonly) {
813 if (!(nentry = db->ops->dup (eptr))) {
817 p = find_entry_by_name (db, db->ops->getname (eptr));
819 if (next_entry_by_name (db, p->next, db->ops->getname (eptr)))
821 fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), db->ops->getname (eptr), db->filename);
824 db->ops->free (p->eptr);
832 /* not found, new entry */
833 p = (struct commonio_entry *) malloc (sizeof *p);
835 db->ops->free (nentry);
845 add_one_entry_nis (db, p);
847 add_one_entry (db, p);
855 void commonio_del_entry (struct commonio_db *db, const struct commonio_entry *p)
858 db->cursor = p->next;
861 p->prev->next = p->next;
866 p->next->prev = p->prev;
874 * commonio_remove - Remove the entry of the given name from the database.
876 int commonio_remove (struct commonio_db *db, const char *name)
878 struct commonio_entry *p;
880 if (!db->isopen || db->readonly) {
884 p = find_entry_by_name (db, name);
889 if (next_entry_by_name (db, p->next, name)) {
890 fprintf (stderr, _("Multiple entries named '%s' in %s. Please fix this with pwck or grpck.\n"), name, db->filename);
894 commonio_del_entry (db, p);
900 db->ops->free (p->eptr);
906 * commonio_locate - Find the first entry with the specified name in
909 * If found, it returns the entry and set the cursor of the database to
912 * Otherwise, it returns NULL.
914 const void *commonio_locate (struct commonio_db *db, const char *name)
916 struct commonio_entry *p;
922 p = find_entry_by_name (db, name);
932 * commonio_rewind - Restore the database cursor to the first entry.
934 * It returns 0 on error, 1 on success.
936 int commonio_rewind (struct commonio_db *db)
947 * commonio_next - Return the next entry of the specified database
949 * It returns the next entry, or NULL if no other entries could be found.
951 const void *commonio_next (struct commonio_db *db)
959 if (db->cursor == NULL)
960 db->cursor = db->head;
962 db->cursor = db->cursor->next;
965 eptr = db->cursor->eptr;
969 db->cursor = db->cursor->next;