Wednesday, September 3, 2014

Unix Prog: Supplementary Groups

1. Supplementary Groups

In modern Unix system, one user can belong to more than one group besides the primary group.

In Current Implementation(UBUNTU):
 ubuntu@ip-172-31-23-227:~$ grep ubuntu /etc/passwd  
 ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash  
 ubuntu@ip-172-31-23-227:~$ grep ubuntu /etc/group  
 adm:x:4:syslog,ubuntu  
 dialout:x:20:ubuntu  
 cdrom:x:24:ubuntu  
 floppy:x:25:ubuntu  
 sudo:x:27:ubuntu  
 audio:x:29:ubuntu  
 dip:x:30:ubuntu  
 video:x:44:ubuntu  
 plugdev:x:46:ubuntu  
 netdev:x:102:ubuntu  
 ubuntu:x:1000:  
 Above code means, at /etc/passwd, current user: "ubuntu" has user id(3rd field): 1000, group id(4th field): 1000, which is also its primary group.

At /etc/group, it lists all groups information at this system, for one group record, it is "group name, group password, group id, and then lastly a list of users". In this case, user "ubuntu" belongs to many groups listed here.

2. System Calls:
getgroups is used to return all groups current process belong to.
setgroups is used to set up related groups for the current user
initgroups is used to initialize current user's groups.
 ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h  
 ......  
 /* If SIZE is zero, return the number of supplementary groups  
   the calling process is in. Otherwise, fill in the group IDs  
   of its supplementary groups in LIST and return the number written. */  
 extern int getgroups (int __size, __gid_t __list[]) __THROW __wur;  
 ......  
 ubuntu@ip-172-31-23-227:~$ less /usr/include/grp.h  
 ......  
 /* Set the group set for the current user to GROUPS (N of them). */  
 extern int setgroups (size_t __n, const __gid_t *__groups) __THROW;  
 ......  
 /* Initialize the group set for the current user  
   by reading the group database and using all groups  
   of which USER is a member. Also include GROUP.  
   
   This function is not part of POSIX and therefore no official  
   cancellation point. But due to similarity with an POSIX interface  
   or due to the implementation it is a cancellation point and  
   therefore not marked with __THROW. */  
 extern int initgroups (const char *__user, __gid_t __group);  
 ......  

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<grp.h>  
   
 int getCurrentGroups(int* gids)  
 {  
  // Get group list cuurent user belongs to  
  int num_group;  
  if((num_group = getgroups(100, gids)) < 0) {  
   printf("getgroups error!\n");  
   exit(1);  
  }  
   
  int i;  
  printf("number of groups: %d\n", num_group);  
  for (i = 0; i < num_group; i++) {  
   printf("%d ", gids[i]);  
  }  
  printf("\n");  
   
  return num_group;  
 }  
   
 int main(int argc, char* argv[])  
 {  
  int gids[100];  
  int num_group;  
   
  num_group = getCurrentGroups(gids);  
   
  // Setup group list, note, we need to have super  
  // user permission to call following system calls  
  gids[num_group] = 3;  
  if(setgroups(num_group+1, gids) < 0) {  
   printf("setgroups error!\n");  
   exit(2);  
  }  
   
  num_group = getCurrentGroups(gids);  
   
  // Init groups  
  if(initgroups("root", 0) < 0) {  
   printf("initgroups error!\n");  
   exit(3);  
  }  
   
  num_group = getCurrentGroups(gids);  
   
  exit(0);  
 }  

shell:
1) Run the program will current user, failed on setgroups, since it needs super user permission
2) Run the program with the super user permission, good for this time. It firstly get all user groups of super user "root", it only belongs to one group with id 0, then we use "setgroups" to add another groupid 3 to super user, then we call getgroups to output groups again, we have a new group! Lastly we call initgroups with user name "root", and basegid: 0 per password file, it just scan the password file and group file and load up every thing.

This example indicate that: all these system calls never touch the password file and group file, even if we call "setgroups" to change the supplementary group information we only change it temporarily for current process, it won't be change permanently on disk.
 ubuntu@ip-172-31-23-227:~$ ./io.out  
 number of groups: 11  
 4 20 24 25 27 29 30 44 46 102 1000  
 setgroups error!  
 ubuntu@ip-172-31-23-227:~$ sudo ./io.out  
 number of groups: 1  
 0  
 number of groups: 2  
 0 3  
 number of groups: 1  
 0  

No comments:

Post a Comment