About passwd, deluser and delgroup

Tito farmatito at tiscali.it
Thu Apr 6 19:14:37 UTC 2006


On Thursday 6 April 2006 16:28, Rob Landley wrote:
> On Wednesday 05 April 2006 3:09 am, Tito wrote:
> > Hi Rob,
> >
> > I was thinking about the fact if it would be possible to
> > reuse these functions (maybe with some minor modifications)
> >
> > static int update_passwd(const struct passwd *pw)
> > static int update_passwd_file(FILE *fp, const char *dest, const char
> > *username)
> >
> > of your pending passwd rewrite to be used also
> > by deluser and delgroup.
> > In this case they could be moved to libbb and
> > the behaviour of all applets writing to password files would be
> > consistent and more secure.
> >
> > BTW, by looking at the cleaned up versions of adduser
> > and addgroup it seems to me that they open the password
> 
> They weren't that cleaned up.  And it turns out it wasn't all the files I've 
> touched (didn't think so).  At the first deleted file that's still under 
> source control, sed stops with an error.  And I've deleted a lot of files.  
> And I'm maybe half done at this point...
> 
> > files in an insecure way.
> > What would happen if two
> > programs try to write to the file
> > at the same time?
> 
> If the new file is a constant filename (which is not a security problem 
> if /etc isn't world writeable) then O_EXCL should fail if it already exists.  

OK.

> The theory is to create a new version and then atomic rename it over the old 
> one.  (The backup is done via a hard link first, so the old one should remain 
> unmodified.  No need to actually copy the data and set the date and all 
> that.)
> 
>     // Create new file, as one atomic operation with the right permissions and
>     // ownership because doing chmod or chown after create opens a race.
> 
>     if ((out_fd = bb_xopen(dest, O_CREAT|O_EXCL,
>             ENABLE_FEATURE_SHADOWPASSWDS ? 0600 : 0644)) < 0) return 0;

I' m trying to use about the same routine in deluser and delgroup which
by the way I'm unifying in one file together with delline.c.
The code is:

static void del_line_matching(const char *login, const char *filename)
{
	char *line;
	FILE *passwd;
	FILE *temp;
	char *new_file = "/etc/ptmp";
	int fd;
	int found = 0;
	struct stat statbuf;
	struct flock lock;

	/* open file */
	passwd = bb_xfopen(filename, "r+");

	/*get mode */
	xstat(filename, &statbuf);

	/* Lock the password file before updating */
	lock.l_type = F_WRLCK;
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;
	if (fcntl(fileno(passwd), F_SETLK, &lock) == 0) {
		/* Be paranoid about who's going to own this file. */
		setuid(0);
		setgid(0);	
		/* get fd */
		if ((fd = open(new_file, O_WRONLY | O_CREAT | O_EXCL, statbuf.st_mode)) != -1) {
			/* get stream */
			if ((temp = fdopen(fd,"w"))) {
				/* Loop through entries, copying each one except the one we want to remove */
				while ((line = bb_get_line_from_file(passwd)) != NULL) {
					if ((strncmp(login, line, strlen(login)) == 0) && line[strlen(login)] == ':') {
						found++;
					} else {
						fputs(line, temp);
					}
					free(line);
				}
				if (!found) {
					bb_error_msg("'%s' not found in '%s'", login, filename);
				} else {
					/* Be sure the new file was written to disk */
					if (!fflush(temp) && !fsync(fileno(temp)) && !fclose(temp)) {
						if (rename(new_file, filename)) {
							bb_error_msg("Can't rename %s to %s", new_file, filename);
						}
					}
				}
			}
		}
		/* Delete new copy in case it didn't get renamed. */
		unlink(new_file);
	}
	/* Remove lock */
	lock.l_type = F_UNLCK;
	fcntl(fileno(passwd), F_SETLK, &lock);
	/* close original file */
	fclose(passwd);
}

This should work with /etc/passwd /etc/shadow, /etc/group and /etc/gshadow

Comments and hints form the list members about the security of 
this code are wellcome as I'm not that good in this things....

TIA 

Ciao,
Tito

  
> I've pondered putting in some kind of recovery code there (check to see if the 
> date on the file that exists is more than X seconds in the past, and delete 
> it if so), but I haven't convinced myself it's worth the bytes.  Still 
> working on it, slowly, in the background...
> 
> Rob



More information about the busybox mailing list