blob: d68ec3a498cfc13bcb090dc3098a0b241f09dc04 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <pthread.h>
#include <grp.h>
#include <pwd.h>
#include <stdlib.h>
#include "fuse_dfs.h"
#if PERMS
/**
* getpwuid and getgrgid return static structs so we safeguard the contents
* while retrieving fields using the 2 structs below.
* NOTE: if using both, always get the passwd struct firt!
*/
pthread_mutex_t passwdstruct_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t groupstruct_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
#if PERMS
/**
* Utility for getting the user making the fuse call in char * form
* NOTE: if non-null return, the return must be freed by the caller.
*/
char *getUsername(uid_t uid)
{
//
// Critical section - protect from concurrent calls in different threads.
// since the struct below is static.
// (no returns until end)
//
pthread_mutex_lock(&passwdstruct_mutex);
struct passwd *userinfo = getpwuid(uid);
char * ret = userinfo && userinfo->pw_name ? strdup(userinfo->pw_name) : NULL;
pthread_mutex_unlock(&passwdstruct_mutex);
//
// End critical section
//
return ret;
}
/**
* Cleans up a char ** group pointer
*/
void freeGroups(char **groups, int numgroups) {
if (groups == NULL) {
return;
}
int i ;
for (i = 0; i < numgroups; i++) {
free(groups[i]);
}
free(groups);
}
#define GROUPBUF_SIZE 5
char *getGroup(gid_t gid) {
//
// Critical section - protect from concurrent calls in different threads.
// since the struct below is static.
// (no returns until end)
//
pthread_mutex_lock(&groupstruct_mutex);
struct group* grp = getgrgid(gid);
char * ret = grp && grp->gr_name ? strdup(grp->gr_name) : NULL;
//
// End critical section
//
pthread_mutex_unlock(&groupstruct_mutex);
return ret;
}
/**
* Utility for getting the group from the uid
* NOTE: if non-null return, the return must be freed by the caller.
*/
char *getGroupUid(uid_t uid) {
//
// Critical section - protect from concurrent calls in different threads
// since the structs below are static.
// (no returns until end)
//
pthread_mutex_lock(&passwdstruct_mutex);
pthread_mutex_lock(&groupstruct_mutex);
char *ret = NULL;
struct passwd *userinfo = getpwuid(uid);
if (NULL != userinfo) {
struct group* grp = getgrgid( userinfo->pw_gid);
ret = grp && grp->gr_name ? strdup(grp->gr_name) : NULL;
}
//
// End critical section
//
pthread_mutex_unlock(&groupstruct_mutex);
pthread_mutex_unlock(&passwdstruct_mutex);
return ret;
}
/**
* lookup the gid based on the uid
*/
gid_t getGidUid(uid_t uid) {
//
// Critical section - protect from concurrent calls in different threads
// since the struct below is static.
// (no returns until end)
//
pthread_mutex_lock(&passwdstruct_mutex);
struct passwd *userinfo = getpwuid(uid);
gid_t gid = userinfo == NULL ? 0 : userinfo->pw_gid;
//
// End critical section
//
pthread_mutex_unlock(&passwdstruct_mutex);
return gid;
}
/**
* Utility for getting the groups for the user making the fuse call in char * form
*/
char ** getGroups(uid_t uid, int *num_groups)
{
char *user = getUsername(uid);
if (user == NULL)
return NULL;
char **groupnames = NULL;
// see http://www.openldap.org/lists/openldap-devel/199903/msg00023.html
//#define GETGROUPS_T 1
#ifdef GETGROUPS_T
*num_groups = GROUPBUF_SIZE;
gid_t* grouplist = malloc(GROUPBUF_SIZE * sizeof(gid_t));
assert(grouplist != NULL);
gid_t* tmp_grouplist;
int rtr;
gid_t gid = getGidUid(uid);
if ((rtr = getgrouplist(user, gid, grouplist, num_groups)) == -1) {
// the buffer we passed in is < *num_groups
if ((tmp_grouplist = realloc(grouplist, *num_groups * sizeof(gid_t))) != NULL) {
grouplist = tmp_grouplist;
getgrouplist(user, gid, grouplist, num_groups);
}
}
groupnames = (char**)malloc(sizeof(char*)* (*num_groups) + 1);
assert(groupnames);
int i;
for (i=0; i < *num_groups; i++) {
groupnames[i] = getGroup(grouplist[i]);
if (groupnames[i] == NULL) {
fprintf(stderr, "error could not lookup group %d\n",(int)grouplist[i]);
}
}
free(grouplist);
assert(user != NULL);
groupnames[i] = user;
*num_groups = *num_groups + 1;
#else
int i = 0;
assert(user != NULL);
groupnames[i] = user;
i++;
groupnames[i] = getGroupUid(uid);
if (groupnames[i]) {
i++;
}
*num_groups = i;
#endif
return groupnames;
}
#endif