bindfs/src/userinfo.c

178 lines
4.0 KiB
C

/*
Copyright 2006,2007,2008 Martin Pärtel <martin.partel@gmail.com>
This file is part of bindfs.
bindfs 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.
bindfs 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 bindfs. If not, see <http://www.gnu.org/licenses/>.
*/
#include "userinfo.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int user_uid(const char *username, uid_t *ret)
{
struct passwd pwbuf, *pwbufp = NULL;
char *buf;
size_t buflen;
int res;
uid_t uid;
char *endptr;
/* Check whether the string is a numerical UID */
uid = strtol(username, &endptr, 10);
if (*endptr == '\0') {
buflen = 1024;
buf = malloc(buflen);
res = getpwuid_r(uid, &pwbuf, buf, buflen, &pwbufp);
if (res != 0) {
if (res != ERANGE) { /* don't care if buffer was too small */
free(buf);
return 0;
}
}
free(buf);
*ret = uid;
return 1;
}
/* Process user name */
buflen = 1024;
buf = malloc(buflen);
res = getpwnam_r(username, &pwbuf, buf, buflen, &pwbufp);
while(res == ERANGE) {
buflen *= 2;
buf = realloc(buf, buflen);
res = getpwnam_r(username, &pwbuf, buf, buflen, &pwbufp);
}
if (pwbufp == NULL) {
free(buf);
return 0;
}
*ret = pwbuf.pw_uid;
free(buf);
return 1;
}
int group_gid(const char *groupname, gid_t *ret)
{
struct group gbuf, *gbufp = NULL;
char *buf;
size_t buflen;
int res;
gid_t gid;
char *endptr;
/* Check whether the string is a numerical GID */
gid = strtol(groupname, &endptr, 10);
if (*endptr == '\0') {
buflen = 1024;
buf = malloc(buflen);
res = getgrgid_r(gid, &gbuf, buf, buflen, &gbufp);
if (res != 0) {
if (res != ERANGE) { /* don't care if buffer was too small */
free(buf);
return 0;
}
}
free(buf);
*ret = gid;
return 1;
}
/* Process group name */
buflen = 1024;
buf = malloc(buflen);
res = getgrnam_r(groupname, &gbuf, buf, buflen, &gbufp);
while(res == ERANGE) {
buflen *= 2;
buf = realloc(buf, buflen);
res = getgrnam_r(groupname, &gbuf, buf, buflen, &gbufp);
}
if (gbufp == NULL) {
free(buf);
return 0;
}
*ret = gbuf.gr_gid;
free(buf);
return 1;
}
int user_belongs_to_group(uid_t uid, gid_t gid)
{
struct passwd pwbuf, *pwbufp = NULL;
struct group grbuf, *grbufp = NULL;
char *buf;
size_t buflen;
int member;
uid_t member_uid;
int res;
buflen = 1024;
buf = malloc(buflen);
res = getpwuid_r(uid, &pwbuf, buf, buflen, &pwbufp);
while(res == ERANGE) {
buflen *= 2;
buf = realloc(buf, buflen);
res = getpwuid_r(uid, &pwbuf, buf, buflen, &pwbufp);
}
if (pwbufp == NULL)
goto no;
if (gid == pwbuf.pw_gid)
goto yes;
/* we reuse the same buf because we don't need the passwd info any more */
res = getgrgid_r(gid, &grbuf, buf, buflen, &grbufp);
while(res == ERANGE) {
buflen *= 2;
buf = realloc(buf, buflen);
res = getgrgid_r(gid, &grbuf, buf, buflen, &grbufp);
}
if (grbufp == NULL)
goto no;
for (member = 0; grbuf.gr_mem[member] != NULL; ++member) {
if (user_uid(grbuf.gr_mem[member], &member_uid))
if (member_uid == uid)
goto yes;
}
goto no;
yes:
free(buf);
return 1;
no:
free(buf);
return 0;
}