Rewrite/shrink by tito.

This commit is contained in:
Rob Landley 2006-04-04 19:19:53 +00:00
parent ab8736064b
commit 9a2dd51237
2 changed files with 95 additions and 252 deletions

View File

@ -5,48 +5,20 @@
* Copyright (C) 1999 by Lineo, inc. and John Beppu
* Copyright (C) 1999,2000,2001 by John Beppu <beppu@codepoet.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*
*/
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "busybox.h"
#include "pwd_.h"
#include "grp_.h"
/* structs __________________________ */
/* data _____________________________ */
/* defaults : should this be in an external file? */
static const char default_passwd[] = "x";
/* make sure gr_name isn't taken, make sure gid is kosher
* return 1 on failure */
static int group_study(const char *filename, struct group *g)
static int group_study(struct group *g)
{
FILE *etc_group;
gid_t desired;
@ -54,16 +26,16 @@ static int group_study(const char *filename, struct group *g)
struct group *grp;
const int max = 65000;
etc_group = bb_xfopen(filename, "r");
etc_group = bb_xfopen(bb_path_group_file, "r");
/* make sure gr_name isn't taken, make sure gid is kosher */
desired = g->gr_gid;
while ((grp = fgetgrent(etc_group))) {
if ((strcmp(grp->gr_name, g->gr_name)) == 0) {
bb_error_msg_and_die("%s: group already in use\n", g->gr_name);
bb_error_msg_and_die("%s: group already in use", g->gr_name);
}
if ((desired) && grp->gr_gid == desired) {
bb_error_msg_and_die("%d: gid has already been allocated\n",
bb_error_msg_and_die("%d: gid already in use",
desired);
}
if ((grp->gr_gid > g->gr_gid) && (grp->gr_gid < max)) {
@ -83,56 +55,33 @@ static int group_study(const char *filename, struct group *g)
}
/* append a new user to the passwd file */
static int addgroup(const char *filename, char *group, gid_t gid, const char *user)
static int addgroup(char *group, gid_t gid, const char *user)
{
FILE *etc_group;
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
FILE *etc_gshadow;
#endif
FILE *file;
struct group gr;
/* group:passwd:gid:userlist */
static const char entryfmt[] = "%s:%s:%d:%s\n";
/* make sure gid and group haven't already been allocated */
gr.gr_gid = gid;
gr.gr_name = group;
if (group_study(filename, &gr))
if (group_study(&gr))
return 1;
/* add entry to group */
etc_group = bb_xfopen(filename, "a");
file = bb_xfopen(bb_path_group_file, "a");
/* group:passwd:gid:userlist */
fprintf(file, "%s:%s:%d:%s\n", group, "x", gr.gr_gid, user);
fclose(file);
fprintf(etc_group, entryfmt, group, default_passwd, gr.gr_gid, user);
fclose(etc_group);
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
/* add entry to gshadow if necessary */
if (access(bb_path_gshadow_file, F_OK|W_OK) == 0) {
etc_gshadow = bb_xfopen(bb_path_gshadow_file, "a");
fprintf(etc_gshadow, "%s:!::\n", group);
fclose(etc_gshadow);
}
#if ENABLE_FEATURE_SHADOWPASSWDS
file = bb_xfopen(bb_path_gshadow_file, "a");
fprintf(file, "%s:!::\n", group);
fclose(file);
#endif
/* return 1; */
return 0;
}
#ifndef CONFIG_ADDUSER
static inline void if_i_am_not_root(void)
{
if (geteuid()) {
bb_error_msg_and_die( "Only root may add a user or group to the system.");
}
}
#else
extern void if_i_am_not_root(void);
#endif
/*
* addgroup will take a login_name as its first parameter.
*
@ -143,29 +92,22 @@ extern void if_i_am_not_root(void);
int addgroup_main(int argc, char **argv)
{
char *group;
char *user;
gid_t gid = 0;
/* check for min, max and missing args and exit on error */
bb_opt_complementally = "-1:?2:?";
/* get remaining args */
if(bb_getopt_ulflags(argc, argv, "g:", &group)) {
if (bb_getopt_ulflags(argc, argv, "g:", &group)) {
gid = bb_xgetlarg(group, 10, 0, LONG_MAX);
}
/* move past the commandline options */
argv += optind;
if (optind < argc) {
group = argv[optind];
optind++;
} else {
bb_show_usage();
/* need to be root */
if(geteuid()) {
bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
}
if (optind < argc) {
user = argv[optind];
} else {
user = "";
}
if_i_am_not_root();
/* werk */
return addgroup(bb_path_group_file, group, gid, user);
return addgroup(argv[0], gid, (argv[1]) ? argv[1] : "");
}

View File

@ -8,44 +8,20 @@
* Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <getopt.h>
#include <sys/stat.h>
#include "busybox.h"
#define DONT_SET_PASS (1 << 4)
#define DONT_MAKE_HOME (1 << 6)
/* structs __________________________ */
typedef struct {
uid_t u;
gid_t g;
} Id;
/* data _____________________________ */
/* defaults : should this be in an external file? */
static const char default_passwd[] = "x";
static const char default_gecos[] = "Linux User,,,";
static const char default_home_prefix[] = "/home";
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
/* shadow in use? */
static int shadow_enabled = 0;
#endif
/* remix */
/* EDR recoded such that the uid may be passed in *p */
static int passwd_study(const char *filename, struct passwd *p)
@ -56,9 +32,7 @@ static int passwd_study(const char *filename, struct passwd *p)
const int min = 500;
const int max = 65000;
passwd = bb_wfopen(filename, "r");
if (!passwd)
return 4;
passwd = bb_xfopen(filename, "r");
/* EDR if uid is out of bounds, set to min */
if ((p->pw_uid > max) || (p->pw_uid < min))
@ -100,11 +74,11 @@ static int passwd_study(const char *filename, struct passwd *p)
return 0;
}
static void addgroup_wrapper(const char *login, gid_t gid)
static void addgroup_wrapper(struct passwd *p)
{
char *cmd;
cmd = bb_xasprintf("addgroup -g %d \"%s\"", gid, login);
cmd = bb_xasprintf("addgroup -g %d \"%s\"", p->pw_gid, p->pw_name);
system(cmd);
free(cmd);
}
@ -119,92 +93,63 @@ static void passwd_wrapper(const char *login)
}
/* putpwent(3) remix */
static int adduser(const char *filename, struct passwd *p, int makehome, int setpass)
static int adduser(struct passwd *p, unsigned long flags)
{
FILE *passwd;
int r;
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
FILE *shadow;
struct spwd *sp;
#endif
int new_group = 1;
/* if using a pre-existing group, don't create one */
if (p->pw_gid != 0)
new_group = 0;
FILE *file;
/* make sure everything is kosher and setup uid && gid */
passwd = bb_wfopen(filename, "a");
if (passwd == NULL) {
return 1;
}
fseek(passwd, 0, SEEK_END);
file = bb_xfopen(bb_path_passwd_file, "a");
fseek(file, 0, SEEK_END);
/* if (passwd_study(filename, p) == 0) { */
r = passwd_study(filename, p);
if (r) {
if (r == 1)
bb_error_msg("%s: login already in use", p->pw_name);
else if (r == 2)
bb_error_msg("illegal uid or no uids left");
else if (r == 3)
bb_error_msg("group name %s already in use", p->pw_name);
else
bb_error_msg("generic error.");
return 1;
}
switch (passwd_study(bb_path_passwd_file, p)) {
case 1:
bb_error_msg_and_die("%s: login already in use", p->pw_name);
case 2:
bb_error_msg_and_die("illegal uid or no uids left");
case 3:
bb_error_msg_and_die("%s: group name already in use", p->pw_name);
}
/* add to passwd */
if (putpwent(p, passwd) == -1) {
return 1;
if (putpwent(p, file) == -1) {
bb_perror_nomsg_and_die();
}
fclose(passwd);
fclose(file);
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
#if ENABLE_FEATURE_SHADOWPASSWDS
/* add to shadow if necessary */
if (shadow_enabled) {
shadow = bb_wfopen(bb_path_shadow_file, "a");
if (shadow == NULL) {
return 1;
}
fseek(shadow, 0, SEEK_END);
sp = pwd_to_spwd(p);
sp->sp_max = 99999; /* debianish */
sp->sp_warn = 7;
fprintf(shadow, "%s:!:%ld:%ld:%ld:%ld:::\n",
sp->sp_namp, sp->sp_lstchg, sp->sp_min, sp->sp_max,
sp->sp_warn);
fclose(shadow);
}
file = bb_xfopen(bb_path_shadow_file, "a");
fseek(file, 0, SEEK_END);
fprintf(file, "%s:!:%ld:%d:%d:%d:::\n",
p->pw_name, /* username */
time(NULL) / 86400, /* sp->sp_lstchg */
0, /* sp->sp_min */
99999, /* sp->sp_max */
7); /* sp->sp_warn */
fclose(file);
#endif
if (new_group) {
/* add to group */
/* addgroup should be responsible for dealing w/ gshadow */
addgroup_wrapper(p->pw_name, p->pw_gid);
/* add to group */
/* addgroup should be responsible for dealing w/ gshadow */
/* if using a pre-existing group, don't create one */
if (p->pw_gid == 0) {
addgroup_wrapper(p);
}
/* Clear the umask for this process so it doesn't
* * screw up the permissions on the mkdir and chown. */
umask(0);
if (makehome) {
/* mkdir */
if (mkdir(p->pw_dir, 0755)) {
bb_perror_msg("%s", p->pw_dir);
}
/* Set the owner and group so it is owned by the new user. */
if (chown(p->pw_dir, p->pw_uid, p->pw_gid)) {
bb_perror_msg("%s", p->pw_dir);
}
/* Now fix up the permissions to 2755. Can't do it before now
* since chown will clear the setgid bit */
if (chmod(p->pw_dir, 02755)) {
bb_perror_msg("%s", p->pw_dir);
}
if (!(flags & DONT_MAKE_HOME)) {
/* Set the owner and group so it is owned by the new user,
then fix up the permissions to 2755. Can't do it before
since chown will clear the setgid bit */
if (mkdir(p->pw_dir, 0755)
|| chown(p->pw_dir, p->pw_uid, p->pw_gid)
|| chmod(p->pw_dir, 02755)) {
bb_perror_msg("%s", p->pw_dir);
}
}
if (setpass) {
if (!(flags & DONT_SET_PASS)) {
/* interactively set passwd */
passwd_wrapper(p->pw_name);
}
@ -212,22 +157,6 @@ static int adduser(const char *filename, struct passwd *p, int makehome, int set
return 0;
}
/* return current uid (root is always uid == 0, right?) */
#ifndef CONFIG_ADDGROUP
static inline void if_i_am_not_root(void)
#else
void if_i_am_not_root(void)
#endif
{
if (geteuid()) {
bb_error_msg_and_die( "Only root may add a user or group to the system.");
}
}
#define SETPASS (1 << 4)
#define MAKEHOME (1 << 6)
/*
* adduser will take a login_name as its first parameter.
*
@ -240,62 +169,34 @@ void if_i_am_not_root(void)
int adduser_main(int argc, char **argv)
{
struct passwd pw;
const char *login;
const char *gecos = default_gecos;
const char *home = NULL;
const char *shell = DEFAULT_SHELL;
const char *usegroup = NULL;
int flags;
int setpass = 1;
int makehome = 1;
unsigned long flags;
/* init */
if (argc < 2) {
bb_show_usage();
}
/* get args */
flags = bb_getopt_ulflags(argc, argv, "h:g:s:G:DSH", &home, &gecos, &shell, &usegroup);
pw.pw_gecos = "Linux User,,,";
pw.pw_shell = (char *)DEFAULT_SHELL;
pw.pw_dir = NULL;
if (flags & SETPASS) {
setpass = 0;
}
if (flags & MAKEHOME) {
makehome = 0;
}
/* check for min, max and missing args and exit on error */
bb_opt_complementally = "-1:?1:?";
flags = bb_getopt_ulflags(argc, argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup);
/* got root? */
if_i_am_not_root();
/* get login */
if (optind >= argc) {
bb_error_msg_and_die( "no user specified");
}
login = argv[optind];
if(geteuid()) {
bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
}
/* create string for $HOME if not specified already */
if (!home) {
home = concat_path_file(default_home_prefix, login);
if (!pw.pw_dir) {
snprintf(bb_common_bufsiz1, BUFSIZ, "/home/%s", argv[optind]);
pw.pw_dir = &bb_common_bufsiz1[0];
}
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
/* is /etc/shadow in use? */
shadow_enabled = (0 == access(bb_path_shadow_file, F_OK));
#endif
/* create a passwd struct */
pw.pw_name = (char *)login;
pw.pw_passwd = (char *)default_passwd;
pw.pw_name = argv[optind];
pw.pw_passwd = "x";
pw.pw_uid = 0;
pw.pw_gid = 0;
pw.pw_gecos = (char *)gecos;
pw.pw_dir = (char *)home;
pw.pw_shell = (char *)shell;
if (usegroup) {
/* Add user to a group that already exists */
pw.pw_gid = bb_xgetgrnam(usegroup);
/* exits on error */
}
pw.pw_gid = (usegroup) ? bb_xgetgrnam(usegroup) : 0; /* exits on failure */
/* grand finale */
return adduser(bb_path_passwd_file, &pw, makehome, setpass);
return adduser(&pw, flags);
}