less free()s

allocate user info in a structure on the stack, this way memory is managed for
us and we don't have to free most things that would be difficult to free.
master
Alessandro Mauri 3 years ago
parent 3f1bf8c5be
commit 86a6af5073
  1. 109
      us.c

109
us.c

@ -51,6 +51,7 @@
#define MAX_HASH 1024 #define MAX_HASH 1024
#define CONF_LINE_MAX 1024 #define CONF_LINE_MAX 1024
#define GROUPS_MAX 256 #define GROUPS_MAX 256
#define STR_MAX 1024
#define FLAG_PERSIST 0x1 #define FLAG_PERSIST 0x1
#define FLAG_NOPASS 0x2 #define FLAG_NOPASS 0x2
#define FLAG_NOLOG 0x4 #define FLAG_NOLOG 0x4
@ -69,6 +70,14 @@ struct config {
int env_n; int env_n;
}; };
struct user_info {
union {
struct passwd pw;
struct group gr;
} d;
char str[STR_MAX];
};
static void *emalloc(size_t); static void *emalloc(size_t);
static char *estrdup(const char *); static char *estrdup(const char *);
void *erealloc(void *, size_t); void *erealloc(void *, size_t);
@ -76,8 +85,8 @@ static void usage(void);
static void die(const char *, ...); static void die(const char *, ...);
static int perm_set(struct passwd *, struct group *); static int perm_set(struct passwd *, struct group *);
static int authenticate(uid_t, char); static int authenticate(uid_t, char);
static struct passwd* user_to_passwd(const char *); static struct passwd* user_to_passwd(const char *, struct user_info *);
static struct group* group_to_grp(const char *); static struct group* group_to_grp(const char *, struct user_info *);
static int get_config(struct config **, int *); static int get_config(struct config **, int *);
extern char **environ; extern char **environ;
@ -88,6 +97,7 @@ int main(int argc, char *argv[])
char *t_usr = "root", *t_grp = NULL; char *t_usr = "root", *t_grp = NULL;
struct passwd *t_pw; struct passwd *t_pw;
struct group *t_gr; struct group *t_gr;
struct user_info t_gr_info = {0}, t_pw_info = {0};
int opt, err; int opt, err;
int shellflag = 0, envflag = 0, askpass = 0; int shellflag = 0, envflag = 0, askpass = 0;
while ((opt = getopt(argc, argv, "Au:g:C:se")) != -1) { while ((opt = getopt(argc, argv, "Au:g:C:se")) != -1) {
@ -120,7 +130,9 @@ int main(int argc, char *argv[])
/* Get user info */ /* Get user info */
char *shell; char *shell;
uid_t ruid = getuid(); uid_t ruid = getuid();
struct passwd *my_pw = getpwuid(ruid); struct passwd *my_pw = NULL;
struct user_info my_info = {0};
getpwuid_r(ruid, &my_info.d.pw, my_info.str, STR_MAX, &my_pw);
if (!my_pw) { if (!my_pw) {
fprintf(stderr, "getpwid: %s\n", strerror(errno)); fprintf(stderr, "getpwid: %s\n", strerror(errno));
return errno; return errno;
@ -132,10 +144,10 @@ int main(int argc, char *argv[])
die("getgroups:"); die("getgroups:");
/* Get target user and group info */ /* Get target user and group info */
t_pw = user_to_passwd(t_usr); t_pw = user_to_passwd(t_usr, &t_pw_info);
if (!t_pw) if (!t_pw)
die("user_to_passwd:"); die("user_to_passwd:");
t_gr = group_to_grp(t_grp); t_gr = group_to_grp(t_grp, &t_gr_info);
/* Don't have to wait for children */ /* Don't have to wait for children */
struct sigaction sa = {0}; struct sigaction sa = {0};
@ -153,45 +165,44 @@ int main(int argc, char *argv[])
struct env_elem *env_extra = NULL; struct env_elem *env_extra = NULL;
struct config *conf = NULL; struct config *conf = NULL;
int conf_num, conf_flags = 0, env_extra_n = 0; int conf_num, conf_flags = 0, env_extra_n = 0;
if (get_config(&conf, &conf_num) == -1) if (get_config(&conf, &conf_num) <= 0)
die("get_config: invalid arguments"); die("get_config: invalid config");
int here = 0; int here = 0;
for (int i = 0; i < conf_num; i++) { for (int i = 0; i < conf_num; i++) {
struct passwd *who_pw, *as_pw; struct passwd *who_pw, *as_pw;
struct group *who_gr, *as_gr; struct group *who_gr, *as_gr;
struct user_info who_info = {0}, as_info = {0};
int who_usr = conf[i].who[0] == ':' ? 0 : 1; int who_usr = conf[i].who[0] == ':' ? 0 : 1;
int as_usr = conf[i].as[0] == ':' ? 0 : 1; int as_usr = conf[i].as[0] == ':' ? 0 : 1;
if (who_usr) { if (who_usr) {
who_pw = user_to_passwd(conf[i].who); who_pw = user_to_passwd(conf[i].who, &who_info);
if (my_pw->pw_uid != who_pw->pw_uid) { if (!who_pw)
free(who_pw); die("%s not a valid user", conf[i].who);
if (my_pw->pw_uid != who_pw->pw_uid)
continue; continue;
}
} else { } else {
who_gr = group_to_grp(conf[i].who); who_gr = group_to_grp(conf[i].who, &who_info);
if (!who_gr)
die("%s not a valid group", conf[i].who);
gid_t w_gid = who_gr->gr_gid; gid_t w_gid = who_gr->gr_gid;
int x = 0; int x = 0;
for (; x < n_groups && w_gid != my_groups[x]; x++); for (; x < n_groups && w_gid != my_groups[x]; x++);
if (w_gid != my_groups[x]) { if (w_gid != my_groups[x])
free(who_gr);
continue; continue;
}
} }
if (as_usr) { if (as_usr) {
as_pw = user_to_passwd(conf[i].as); as_pw = user_to_passwd(conf[i].as, &as_info);
if (!as_pw) if (!as_pw)
die("%s not a valid user", conf[i].as); die("%s not a valid user", conf[i].as);
if (t_pw->pw_uid != as_pw->pw_uid) { if (t_pw->pw_uid != as_pw->pw_uid)
free(as_pw);
continue; continue;
}
} else if (t_gr) { } else if (t_gr) {
as_gr = group_to_grp(conf[i].as); as_gr = group_to_grp(conf[i].as, &as_info);
if (t_gr->gr_gid != as_gr->gr_gid) { if (!as_gr)
free(as_gr); die("%s not a valid group", conf[i].as);
if (t_gr->gr_gid != as_gr->gr_gid)
continue; continue;
}
} else { } else {
continue; continue;
} }
@ -210,6 +221,16 @@ int main(int argc, char *argv[])
} }
} }
/* We don't need conf anymore */
for (int i = 0; i < conf_num; i++) {
free(conf[i].who);
free(conf[i].as);
if (conf[i].env && conf[i].env_n)
free(conf[i].env);
}
free(conf);
/* No configuration was fount, can't proceed */
if (!here) if (!here)
die("no rule found for user %s", my_name); die("no rule found for user %s", my_name);
@ -228,7 +249,7 @@ int main(int argc, char *argv[])
/* Set argc and argv */ /* Set argc and argv */
int c_argc = argc - optind; int c_argc = argc - optind;
char **c_argv; char **c_argv = NULL;
if (c_argc) { if (c_argc) {
c_argv = emalloc(sizeof(char *) * (c_argc + 1)); c_argv = emalloc(sizeof(char *) * (c_argc + 1));
for (int i = 0; optind < argc; optind++, i++) for (int i = 0; optind < argc; optind++, i++)
@ -487,66 +508,56 @@ static int authenticate(uid_t uid, char ask)
return 0; return 0;
} }
static struct passwd* user_to_passwd(const char *user) static struct passwd* user_to_passwd(const char *user, struct user_info *info)
{ {
if (!user) { if (!user) {
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
struct passwd *pw, *pr; struct passwd *pw;
long uid_l; long uid_l;
errno = 0; errno = 0;
if (user[0] != '#') { if (user[0] != '#') {
pw = getpwnam(user); getpwnam_r(user, &(info->d.pw), info->str, STR_MAX, &pw);
} else { } else {
uid_l = strtol(&user[1], NULL, 10); uid_l = strtol(&user[1], NULL, 10);
if (uid_l < 0 || errno) { if (uid_l < 0 || errno) {
errno = errno ? errno : EINVAL; errno = errno ? errno : EINVAL;
return NULL; return NULL;
} }
pw = getpwuid((uid_t)uid_l); getpwuid_r((uid_t)uid_l, &(info->d.pw), info->str, STR_MAX, &pw);
} }
if (!pw) { if (!pw && !errno)
if (!errno) errno = EINVAL;
errno = EINVAL; return pw;
return NULL;
}
pr = emalloc(sizeof(struct passwd));
memcpy(pr, pw, sizeof(struct passwd));
return pr;
} }
static struct group* group_to_grp(const char *group) static struct group* group_to_grp(const char *group, struct user_info *info)
{ {
if (!group) { if (!group) {
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
struct group *gr, *rr; struct group *gr;
long gid_l; long gid_l;
errno = 0; errno = 0;
if (group[0] != '#') { if (group[0] != '#') {
gr = getgrnam(group); getgrnam_r(group, &(info->d.gr), info->str, STR_MAX, &gr);
} else { } else {
gid_l = strtol(&group[1], NULL, 10); gid_l = strtol(&group[1], NULL, 10);
if (gid_l < 0 || errno) { if (gid_l < 0 || errno) {
errno = errno ? errno : EINVAL; errno = errno ? errno : EINVAL;
return NULL; return NULL;
} }
gr = getgrgid((gid_t)gid_l); getgrgid_r((gid_t)gid_l, &(info->d.gr), info->str, STR_MAX, &gr);
} }
if (!gr) { if (!gr && !errno)
if (!errno) errno = EINVAL;
errno = EINVAL; return gr;
return NULL;
}
rr = emalloc(sizeof(struct group));
memcpy(rr, gr, sizeof(struct group));
return rr;
} }
void die(const char *fmt, ...) void die(const char *fmt, ...)
@ -690,5 +701,5 @@ static int get_config(struct config **conf, int *num)
*num += 1; *num += 1;
} }
fclose(fp); fclose(fp);
return 0; return *num;
} }

Loading…
Cancel
Save