1 | #!/usr/bin/perl |
---|
2 | # |
---|
3 | # This is a sample implementation of a UID/GID GPFS remapping helper |
---|
4 | # application pair, provided for testing and illustrative purposes. It uses |
---|
5 | # the Full Name (a.k.a. gecos) field in /etc/passwd as the globally unique user |
---|
6 | # name. No name-based GID remapping is done in this implementation. When |
---|
7 | # remapping for the purposes of credentials checking (intent is 'credentials'), |
---|
8 | # we do remapping for the UID based on the symbolic name, and replace the |
---|
9 | # entire list of GIDs with the GIDs of the user on the home cluster. |
---|
10 | |
---|
11 | $debug = 0; |
---|
12 | |
---|
13 | if ($#ARGV != 3) |
---|
14 | { |
---|
15 | die("Usage: mmname2uid domain intent nUids nGids\n"); |
---|
16 | } |
---|
17 | |
---|
18 | $domain = $ARGV[0]; |
---|
19 | $intent = $ARGV[1]; |
---|
20 | $nUids = $ARGV[2]; |
---|
21 | $nGids = $ARGV[3]; |
---|
22 | |
---|
23 | # Do basic argument sanity checking |
---|
24 | if ( ($intent ne "credentials") && ($intent ne "stat") && ($intent ne "acl") ) |
---|
25 | { |
---|
26 | die("Invalid intent value: $intent\n"); |
---|
27 | } |
---|
28 | |
---|
29 | if ( ($intent eq "credentials") && ($nUids == 0) ) |
---|
30 | { |
---|
31 | die("The number of UIDs to be remapped cannot be zero\n"); |
---|
32 | } |
---|
33 | |
---|
34 | if ( ($intent eq "credentials") && ($nUids != 1) ) |
---|
35 | { |
---|
36 | die("Only one UID is allowed for credentials remapping\n"); |
---|
37 | } |
---|
38 | |
---|
39 | # In this sample implementation, we replace the entire list of GIDs |
---|
40 | # with a new list when remapping for credentials checking. The matching |
---|
41 | # mmuid2name never outputs any GIDs, so we should not be expecting any |
---|
42 | # (a different implementation may handle this differently) |
---|
43 | if ($intent eq "credentials") |
---|
44 | { |
---|
45 | $nGids = 0; |
---|
46 | } |
---|
47 | |
---|
48 | # Read the list of UIDs and GIDs. Note that the interface conventions |
---|
49 | # stipulate that when the intent is 'stat', two lines of input will be |
---|
50 | # provided for each ID: symbolic name and original numeric ID. |
---|
51 | for ($i = 0; $i < $nUids; $i++) |
---|
52 | { |
---|
53 | $name = <STDIN>; |
---|
54 | print(STDERR $name) if $debug; |
---|
55 | chop($name); |
---|
56 | $gcoss{$name} = $i; |
---|
57 | $uids[$i] = "UNKNOWN USER"; |
---|
58 | if ($intent eq "stat") |
---|
59 | { |
---|
60 | $id = <STDIN>; |
---|
61 | print(STDERR $id) if $debug; |
---|
62 | chop($id); |
---|
63 | $orig_uids[$i] = $id; |
---|
64 | } |
---|
65 | } |
---|
66 | for ($i = 0; $i < $nGids; $i++) |
---|
67 | { |
---|
68 | $gname = <STDIN>; |
---|
69 | print(STDERR $gname) if $debug; |
---|
70 | chop($gname); |
---|
71 | $gnames{$gname} = $i; |
---|
72 | if ($intent eq "stat") |
---|
73 | { |
---|
74 | $id = <STDIN>; |
---|
75 | print(STDERR $id) if $debug; |
---|
76 | chop($id); |
---|
77 | $orig_gids[$i] = $id; |
---|
78 | } |
---|
79 | } |
---|
80 | |
---|
81 | # Go though the list of users, as returned by getpwent (normally it's the |
---|
82 | # list from /etc/passwd or NIS), and find users who have their Full Name |
---|
83 | # matching to one of the input names. |
---|
84 | $nFound = 0; |
---|
85 | while(true) |
---|
86 | { |
---|
87 | @pwent = getpwent(); |
---|
88 | if ($#pwent == -1){ last; } |
---|
89 | $username = $pwent[0]; |
---|
90 | $uid = $pwent[2]; |
---|
91 | $gid = $pwent[3]; |
---|
92 | $gcos = $pwent[6]; |
---|
93 | if (exists $gcoss{$gcos}) |
---|
94 | { |
---|
95 | $uids[$gcoss{$gcos}] = $uid; |
---|
96 | if ($intent eq "credentials") |
---|
97 | { |
---|
98 | $gids[$gcoss{$gcos}] = $gid; |
---|
99 | $usernames[$gcoss{$gcos}] = $username; |
---|
100 | } |
---|
101 | $nFound++; |
---|
102 | last if $nFound >= $nUids; |
---|
103 | } |
---|
104 | } |
---|
105 | endpwent(); |
---|
106 | |
---|
107 | # Get UID/GID of 'nobody'. In this implementation, we return those when the |
---|
108 | # symbolic name is not found in our /etc/passwd. |
---|
109 | @a = getpwnam("nobody"); |
---|
110 | $nobody_uid = $a[2]; |
---|
111 | $nobody_gid = $a[3]; |
---|
112 | |
---|
113 | # In this implementation, the convention is to use "UNKNOWN USER" string |
---|
114 | # to denote a name that has not been found. |
---|
115 | for ($i = 0; $i < $nUids; $i++) |
---|
116 | { |
---|
117 | # if the user is not found, print ids of nobody |
---|
118 | if ($uids[$i] eq "UNKNOWN USER") |
---|
119 | { |
---|
120 | printf("%u\n", $nobody_uid); |
---|
121 | printf("%u\n", $nobody_gid) if ($intent eq "credentials"); |
---|
122 | next; |
---|
123 | } |
---|
124 | |
---|
125 | printf("%u\n", $uids[$i]); |
---|
126 | # if we are remapping for credentials checking, get a list of groups |
---|
127 | # that the user belongs to |
---|
128 | if ($intent eq "credentials") |
---|
129 | { |
---|
130 | # primary gid |
---|
131 | printf("%u\n", $gids[$i]); |
---|
132 | # supplementary groups |
---|
133 | while(true) |
---|
134 | { |
---|
135 | ($name, $passwd, $gid, $members) = getgrent(); |
---|
136 | last if $name eq ""; |
---|
137 | # skip group if it's user's primary group |
---|
138 | next if $gid == $gids[$i]; |
---|
139 | @memberlist = split(' ', $members); |
---|
140 | foreach(@memberlist) |
---|
141 | { |
---|
142 | if ($_ eq $usernames[$i]) |
---|
143 | { |
---|
144 | printf("%u\n", $gid); |
---|
145 | last; |
---|
146 | } |
---|
147 | } |
---|
148 | } |
---|
149 | } |
---|
150 | } |
---|
151 | |
---|
152 | # In this example, we don't do remapping for gids for stat. We choose not |
---|
153 | # to remap gids at all, i.e. return the same gid that was supplied to us. An |
---|
154 | # alternative would be to return gid of 'nobody' for all gids, but that is |
---|
155 | # hardly useful. |
---|
156 | for ($i = 0; $i < $nGids; $i++) |
---|
157 | { |
---|
158 | printf("%u\n", $orig_gids[$i]); |
---|
159 | } |
---|