| /** |
| * 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 |