Exemple #1
0
static struct group *
vnextgrent(char const * nam, gid_t gid, int doclose)
{
	struct group * gr = NULL;

	static char * grtmp = NULL;
	static int grlen = 0;
	static char ** mems = NULL;
	static int memlen = 0;

	extendline(&grtmp, &grlen, MAXPATHLEN);
	strlcpy(grtmp, getgrpath(_GROUP), MAXPATHLEN);

	if (grp_fp != NULL || (grp_fp = fopen(grtmp, "r")) != NULL) {
		int done = 0;

		static struct group grp;

		while (!done && fgets(grtmp, grlen, grp_fp) != NULL)
		{
			int i, quickout = 0;
			int mno = 0;
			char * q, * p;
			char * sep = ":\n";

			if ((p = strchr(grtmp, '\n')) == NULL) {
				int l;
				extendline(&grtmp, &grlen, grlen + PWBUFSZ);
				l = strlen(grtmp);
				if (fgets(grtmp + l, grlen - l, grp_fp) == NULL)
				  break;	/* No newline terminator on last line */
			}
			/* Skip comments and empty lines */
			if (*grtmp == '\n' || *grtmp == '#')
				continue;
			i = 0;
			q = p = grtmp;
			bzero(&grp, sizeof grp);
			extendarray(&mems, &memlen, 200);
			while (!quickout && (p = strsep(&q, sep)) != NULL) {
				switch (i++)
				{
				case 0:   /* groupname */
					grp.gr_name = p;
					if (nam) {
						if (strcmp(nam, p) == 0)
							done = 1;
						else
							quickout = 1;
					}
					break;
				case 1:   /* password */
					grp.gr_passwd = p;
					break;
				case 2:   /* gid */
					grp.gr_gid = atoi(p);
					if (gid != (gid_t)-1) {
						if (gid == (gid_t)grp.gr_gid)
							done = 1;
						else
							quickout = 1;
					} else if (nam == NULL)
						done = 1;
					break;
				case 3:
					q = p;
					sep = ",\n";
					break;
				default:
					if (*p) {
						extendarray(&mems, &memlen, mno + 2);
						mems[mno++] = p;
					}
					break;
				}
			}
			grp.gr_mem = mems;
			mems[mno] = NULL;
                }
		if (doclose)
			vendgrent();
		if (done && grp.gr_name) {
			gr = &grp;

			CKNULL(grp.gr_passwd);
		}
	}
	return gr;
}
Exemple #2
0
int
write_userconfig(char const * file)
{
	int             fd;

	if (file == NULL)
		file = _PATH_PW_CONF;

	if ((fd = open(file, O_CREAT | O_RDWR | O_TRUNC | O_EXLOCK, 0644)) != -1) {
		FILE           *fp;

		if ((fp = fdopen(fd, "w")) == NULL)
			close(fd);
		else {
			int             i, j, k;
			int		len = LNBUFSZ;
			char           *buf = malloc(len);

			for (i = _UC_NONE; i < _UC_FIELDS; i++) {
				int             quote = 1;
				char const     *val = buf;

				*buf = '\0';
				switch (i) {
				case _UC_DEFAULTPWD:
					val = boolean_str(config.default_password);
					break;
				case _UC_REUSEUID:
					val = boolean_str(config.reuse_uids);
					break;
				case _UC_REUSEGID:
					val = boolean_str(config.reuse_gids);
					break;
				case _UC_NISPASSWD:
					val = config.nispasswd ? config.nispasswd : "";
					quote = 0;
					break;
				case _UC_DOTDIR:
					val = config.dotdir ? config.dotdir : boolean_str(0);
					break;
				case _UC_NEWMAIL:
					val = config.newmail ? config.newmail : boolean_str(0);
					break;
				case _UC_LOGFILE:
					val = config.logfile ? config.logfile : boolean_str(0);
					break;
				case _UC_HOMEROOT:
					val = config.home;
					break;
				case _UC_HOMEMODE:
					sprintf(buf, "%04o", config.homemode);
					quote = 0;
					break;
				case _UC_SHELLPATH:
					val = config.shelldir;
					break;
				case _UC_SHELLS:
					for (j = k = 0; j < _UC_MAXSHELLS && system_shells[j] != NULL; j++) {
						char	lbuf[64];
						int	l = snprintf(lbuf, sizeof lbuf, "%s\"%s\"", k ? "," : "", system_shells[j]);
						if (l < 0)
							l = 0;
						if (l + k + 1 < len || extendline(&buf, &len, len + LNBUFSZ) != -1) {
							strcpy(buf + k, lbuf);
							k += l;
						}
					}
					quote = 0;
					break;
				case _UC_DEFAULTSHELL:
					val = config.shell_default ? config.shell_default : bourne_shell;
					break;
				case _UC_DEFAULTGROUP:
					val = config.default_group ? config.default_group : "";
					break;
				case _UC_EXTRAGROUPS:
					extendarray(&config.groups, &config.numgroups, 200);
					for (j = k = 0; j < config.numgroups && config.groups[j] != NULL; j++) {
						char	lbuf[64];
						int	l = snprintf(lbuf, sizeof lbuf, "%s\"%s\"", k ? "," : "", config.groups[j]);
						if (l < 0)
							l = 0;
						if (l + k + 1 < len || extendline(&buf, &len, len + 1024) != -1) {
							strcpy(buf + k, lbuf);
							k +=  l;
						}
					}
					quote = 0;
					break;
				case _UC_DEFAULTCLASS:
					val = config.default_class ? config.default_class : "";
					break;
				case _UC_MINUID:
					sprintf(buf, "%lu", (unsigned long) config.min_uid);
					quote = 0;
					break;
				case _UC_MAXUID:
					sprintf(buf, "%lu", (unsigned long) config.max_uid);
					quote = 0;
					break;
				case _UC_MINGID:
					sprintf(buf, "%lu", (unsigned long) config.min_gid);
					quote = 0;
					break;
				case _UC_MAXGID:
					sprintf(buf, "%lu", (unsigned long) config.max_gid);
					quote = 0;
					break;
				case _UC_EXPIRE:
					sprintf(buf, "%d", config.expire_days);
					quote = 0;
					break;
				case _UC_PASSWORD:
					sprintf(buf, "%d", config.password_days);
					quote = 0;
					break;
				case _UC_NONE:
					break;
				}

				if (comments[i])
					fputs(comments[i], fp);

				if (*kwds[i]) {
					if (quote)
						fprintf(fp, "%s = \"%s\"\n", kwds[i], val);
					else
						fprintf(fp, "%s = %s\n", kwds[i], val);
#if debugging
					printf("WROTE: %s = %s\n", kwds[i], val);
#endif
				}
			}
			free(buf);
			return fclose(fp) != EOF;
		}
	}
	return 0;
}
Exemple #3
0
struct userconf *
read_userconfig(char const * file)
{
	FILE           *fp;

	extendarray(&config.groups, &config.numgroups, 200);
	memset(config.groups, 0, config.numgroups * sizeof(char *));
	if (file == NULL)
		file = _PATH_PW_CONF;
	if ((fp = fopen(file, "r")) != NULL) {
		int	    buflen = LNBUFSZ;
		char       *buf = malloc(buflen);

	nextline:
		while (fgets(buf, buflen, fp) != NULL) {
			char           *p;

			while ((p = strchr(buf, '\n')) == NULL) {
				int	  l;
				if (extendline(&buf, &buflen, buflen + LNBUFSZ) == -1) {
					int	ch;
					while ((ch = fgetc(fp)) != '\n' && ch != EOF);
					goto nextline;	/* Ignore it */
				}
				l = strlen(buf);
				if (fgets(buf + l, buflen - l, fp) == NULL)
					break;	/* Unterminated last line */
			}

			if (p != NULL)
				*p = '\0';

			if (*buf && (p = strtok(buf, " \t\r\n=")) != NULL && *p != '#') {
				static char const toks[] = " \t\r\n,=";
				char           *q = strtok(NULL, toks);
				int             i = 0;

				while (i < _UC_FIELDS && strcmp(p, kwds[i]) != 0)
					++i;
#if debugging
				if (i == _UC_FIELDS)
					printf("Got unknown kwd `%s' val=`%s'\n", p, q ? q : "");
				else
					printf("Got kwd[%s]=%s\n", p, q);
#endif
				switch (i) {
				case _UC_DEFAULTPWD:
					config.default_password = boolean_val(q, 1);
					break;
				case _UC_REUSEUID:
					config.reuse_uids = boolean_val(q, 0);
					break;
				case _UC_REUSEGID:
					config.reuse_gids = boolean_val(q, 0);
					break;
				case _UC_NISPASSWD:
					config.nispasswd = (q == NULL || !boolean_val(q, 1))
						? NULL : newstr(q);
					break;
				case _UC_DOTDIR:
					config.dotdir = (q == NULL || !boolean_val(q, 1))
						? NULL : newstr(q);
					break;
				case _UC_NEWMAIL:
					config.newmail = (q == NULL || !boolean_val(q, 1))
						? NULL : newstr(q);
					break;
				case _UC_LOGFILE:
					config.logfile = (q == NULL || !boolean_val(q, 1))
						? NULL : newstr(q);
					break;
				case _UC_HOMEROOT:
					config.home = (q == NULL || !boolean_val(q, 1))
						? "/home" : newstr(q);
					break;
				case _UC_SHELLPATH:
					config.shelldir = (q == NULL || !boolean_val(q, 1))
						? "/bin" : newstr(q);
					break;
				case _UC_SHELLS:
					for (i = 0; i < _UC_MAXSHELLS && q != NULL; i++, q = strtok(NULL, toks))
						system_shells[i] = newstr(q);
					if (i > 0)
						while (i < _UC_MAXSHELLS)
							system_shells[i++] = NULL;
					break;
				case _UC_DEFAULTSHELL:
					config.shell_default = (q == NULL || !boolean_val(q, 1))
						? (char *) bourne_shell : newstr(q);
					break;
				case _UC_DEFAULTGROUP:
					q = unquote(q);
					config.default_group = (q == NULL || !boolean_val(q, 1) || GETGRNAM(q) == NULL)
						? NULL : newstr(q);
					break;
				case _UC_EXTRAGROUPS:
					for (i = 0; q != NULL; q = strtok(NULL, toks)) {
						if (extendarray(&config.groups, &config.numgroups, i + 2) != -1)
							config.groups[i++] = newstr(q);
					}
					if (i > 0)
						while (i < config.numgroups)
							config.groups[i++] = NULL;
					break;
				case _UC_DEFAULTCLASS:
					config.default_class = (q == NULL || !boolean_val(q, 1))
						? NULL : newstr(q);
					break;
				case _UC_MINUID:
					if ((q = unquote(q)) != NULL && isdigit(*q))
						config.min_uid = (uid_t) atol(q);
					break;
				case _UC_MAXUID:
					if ((q = unquote(q)) != NULL && isdigit(*q))
						config.max_uid = (uid_t) atol(q);
					break;
				case _UC_MINGID:
					if ((q = unquote(q)) != NULL && isdigit(*q))
						config.min_gid = (gid_t) atol(q);
					break;
				case _UC_MAXGID:
					if ((q = unquote(q)) != NULL && isdigit(*q))
						config.max_gid = (gid_t) atol(q);
					break;
				case _UC_EXPIRE:
					if ((q = unquote(q)) != NULL && isdigit(*q))
						config.expire_days = atoi(q);
					break;
				case _UC_PASSWORD:
					if ((q = unquote(q)) != NULL && isdigit(*q))
						config.password_days = atoi(q);
					break;
				case _UC_FIELDS:
				case _UC_NONE:
					break;
				}
			}
		}
		free(buf);
		fclose(fp);
	}
	return &config;
}
Exemple #4
0
int
editgroups(char *name, char **groups)
{
	int             rc = 0;
	int             infd;
	char		groupfile[MAXPATHLEN];
	char		grouptmp[MAXPATHLEN];

	strncpy(groupfile, getgrpath(_GROUP), MAXPATHLEN - 5);
	groupfile[MAXPATHLEN - 5] = '\0';
	strcpy(grouptmp, groupfile);
	strcat(grouptmp, ".new");

	if ((infd = open(groupfile, O_RDWR | O_CREAT | O_EXLOCK, 0644)) != -1) {
		FILE           *infp;

		if ((infp = fdopen(infd, "r+")) == NULL)
			close(infd);
		else {
			int             outfd;

			if ((outfd = open(grouptmp, O_RDWR | O_CREAT | O_TRUNC, 0644)) != -1) {
				FILE           *outfp;

				if ((outfp = fdopen(outfd, "w+")) == NULL)
					close(outfd);
				else {
					int		linelen = PWBUFSZ;
					int		outlen =  PWBUFSZ;
					int		memlen = 200; /* Arbitrary */
					char           *line = malloc(linelen);
					char           *outl = malloc(outlen);
					char	      **mems = malloc(memlen * sizeof(char *));
					int		namlen = strlen(name);

					if (line == NULL || outl == NULL || mems == NULL) {
					    mem_abort:
						rc = 0;
					} else {
						while (fgets(line, linelen, infp) != NULL) {
							char           *p;
							int		l;

							while ((p = strchr(line, '\n')) == NULL)
							{
								if (extendline(&line, &linelen, linelen + PWBUFSZ) == -1) {
									goto mem_abort;
								}
								l = strlen(line);
								if (fgets(line + l, linelen - l, infp) == NULL)
									break;	/* No newline terminator on last line */
							}
							l = strlen(line) + namlen + 1;
							if (extendline(&outl, &outlen, l) == -1) {
								goto mem_abort;
							}
							if (*line == '#')
								strcpy(outl, line);
							else if (*line == '\n')
								*outl = '\0';
							else {
								int             i,
									        mno = 0;
								char           *cp = line;
								char const     *sep = ":\n";
								struct group    grp;

								memset(&grp, 0, sizeof grp);
								for (i = 0; (p = strsep(&cp, sep)) != NULL; i++) {
									switch (i) {
									case 0:	/* Group name */
										grp.gr_name = p;
										break;
									case 1:	/* Group password */
										grp.gr_passwd = p;
										break;
									case 2:	/* Group id */
										grp.gr_gid = atoi(p);
										break;
									case 3:	/* Member list */
										cp = p;
										sep = ",\n";
										break;
									default:	/* Individual members */
										if (*p) {
											if (extendarray(&mems, &memlen, mno + 2) == -1) {
												goto mem_abort;
											}
											mems[mno++] = p;
										}
										break;
									}
								}
								if (i < 2)	/* Bail out - insufficient fields */
									continue;

								grp.gr_mem = mems;
								for (i = mno; i < memlen; i++)
									mems[i] = NULL;

								/*
								 * Delete from group, or add to group?
								 */
								if (groups == NULL || isingroup(grp.gr_name, groups) == -1) {	/* Delete */
									int             idx;

									while ((idx = isingroup(name, mems)) != -1) {
										for (i = idx; i < (memlen - 1); i++)
											mems[i] = mems[i + 1];
										mems[i] = NULL;
										--mno;
									}
									/*
									 * Special case - deleting user and group may be user's own
									 */
									if (groups == NULL && mems[0] == NULL && strcmp(name, grp.gr_name) == 0) {
										/*
										 * First, make _sure_ we don't have other members
										 */
										struct passwd  *pwd;

										SETPWENT();
										while ((pwd = GETPWENT()) != NULL && (gid_t)pwd->pw_gid != (gid_t)grp.gr_gid);
										ENDPWENT();
										if (pwd == NULL)	/* No members at all */
											continue;	/* Drop the group */
									}
								} else if (isingroup(name, mems) == -1) {
									if (extendarray(&mems, &memlen, mno + 2) == -1) {
										goto mem_abort;
									}
									grp.gr_mem = mems;    /* May have realloced() */
									mems[mno++] = name;
									mems[mno  ] = NULL;
								}
								fmtgrentry(&outl, &outlen, &grp, PWF_GROUP);
							}
							fputs(outl, outfp);
						}
						if (fflush(outfp) != EOF) {
							rc = 1;

							/*
							 * Copy data back into the original file and truncate
							 */
							rewind(infp);
							rewind(outfp);
							while (fgets(outl, outlen, outfp) != NULL)
								fputs(outl, infp);

							/*
							 * This is a gross hack, but we may have corrupted the
							 * original file.
							 */
							if (fflush(infp) == EOF || ferror(infp))
								rc = rename(grouptmp, groupfile) == 0;
							else
								ftruncate(infd, ftell(infp));
						}
					}
					free(mems);
					free(outl);
			    		free(line);
					fclose(outfp);
				}
				remove(grouptmp);
			}
			fclose(infp);
		}
	}
	return rc;
}
Exemple #5
0
int
fileupdate(char const * filename, mode_t fmode, char const * newline, char const * prefix, int pfxlen, int updmode)
{
	int     rc = 0;

	if (pfxlen <= 1)
		rc = EINVAL;
	else {
		int    infd = open(filename, O_RDWR | O_CREAT, fmode);

		if (infd == -1)
			rc = errno;
		else {
			FILE   *infp = fdopen(infd, "r+");

			if (infp == NULL) {
				rc = errno;		/* Assumes fopen(3) sets errno from open(2) */
				close(infd);
			} else {
				int       outfd;
				char      file[MAXPATHLEN];

				strcpy(file, filename);
				strcat(file, ".new");
				outfd = open(file, O_RDWR | O_CREAT | O_TRUNC | O_EXLOCK, fmode);
				if (outfd == -1)
					rc = errno;
				else {
					FILE    *outfp = fdopen(outfd, "w+");

					if (outfp == NULL) {
						rc = errno;
						close(outfd);
					} else {
						int   updated = UPD_CREATE;
						int		linesize = PWBUFSZ;
						char  *line = malloc(linesize);

					nextline:
						while (fgets(line, linesize, infp) != NULL) {
							char  *p = strchr(line, '\n');

							while ((p = strchr(line, '\n')) == NULL) {
								int	l;
								if (extendline(&line, &linesize, linesize + PWBUFSZ) == -1) {
									int	ch;
									fputs(line, outfp);
									while ((ch = fgetc(infp)) != EOF) {
										fputc(ch, outfp);
										if (ch == '\n')
											break;
									}
									goto nextline;
								}
								l = strlen(line);
								if (fgets(line + l, linesize - l, infp) == NULL)
									break;
							}
							if (*line != '#' && *line != '\n') {
								if (!updated && strncmp(line, prefix, pfxlen) == 0) {
									updated = updmode == UPD_REPLACE ? UPD_REPLACE : UPD_DELETE;

									/*
									 * Only actually write changes if updating
									 */
									if (updmode == UPD_REPLACE)
										strcpy(line, newline);
									else if (updmode == UPD_DELETE)
										continue;
								}
							}
							fputs(line, outfp);
						}

						/*
						 * Now, we need to decide what to do: If we are in
						 * update mode, and no record was updated, then error If
						 * we are in insert mode, and record already exists,
						 * then error
						 */
						if (updmode != updated)
							/* -1 return means:
							 * update,delete=no user entry
							 * create=entry exists
							 */
							rc = -1;
						else {

							/*
							 * If adding a new record, append it to the end
							 */
							if (updmode == UPD_CREATE)
								fputs(newline, outfp);

							/*
							 * Flush the file and check for the result
							 */
							if (fflush(outfp) == EOF)
								rc = errno;	/* Failed to update */
							else {
								/*
								 * Copy data back into the
								 * original file and truncate
								 */
								rewind(infp);
								rewind(outfp);
								while (fgets(line, linesize, outfp) != NULL)
									fputs(line, infp);

								/*
								 * If there was a problem with copying
								 * we will just rename 'file.new' 
								 * to 'file'.
								 * This is a gross hack, but we may have
								 * corrupted the original file
								 * Unfortunately, it will lose the inode
								 * and hence the lock.
								 */
								if (fflush(infp) == EOF || ferror(infp))
									rename(file, filename);
								else
									ftruncate(infd, ftell(infp));
							}
						}
						free(line);
						fclose(outfp);
					}
					remove(file);
				}
				fclose(infp);
			}
		}
	}
	return rc;
}