]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/nfsidmap/nfsidmap.c
Imported upstream 1.2.6
[nfs-utils.git] / utils / nfsidmap / nfsidmap.c
1
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <errno.h>
7
8 #include <pwd.h>
9 #include <grp.h>
10 #include <keyutils.h>
11 #include <nfsidmap.h>
12
13 #include <unistd.h>
14 #include "xlog.h"
15
16 int verbose = 0;
17 char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]";
18
19 #define MAX_ID_LEN   11
20 #define IDMAP_NAMESZ 128
21 #define USER  1
22 #define GROUP 0
23
24 #define PROCKEYS "/proc/keys"
25 #ifndef DEFAULT_KEYRING
26 #define DEFAULT_KEYRING "id_resolver"
27 #endif
28
29 static int keyring_clear(char *keyring);
30
31 #define UIDKEYS 0x1
32 #define GIDKEYS 0x2
33
34 /*
35  * Find either a user or group id based on the name@domain string
36  */
37 int id_lookup(char *name_at_domain, key_serial_t key, int type)
38 {
39         char id[MAX_ID_LEN];
40         uid_t uid = 0;
41         gid_t gid = 0;
42         int rc;
43
44         if (type == USER) {
45                 rc = nfs4_owner_to_uid(name_at_domain, &uid);
46                 sprintf(id, "%u", uid);
47         } else {
48                 rc = nfs4_group_owner_to_gid(name_at_domain, &gid);
49                 sprintf(id, "%u", gid);
50         }
51         if (rc < 0)
52                 xlog_err("id_lookup: %s: failed: %m",
53                         (type == USER ? "nfs4_owner_to_uid" : "nfs4_group_owner_to_gid"));
54
55         if (rc == 0) {
56                 rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
57                 if (rc < 0) {
58                         switch(rc) {
59                         case -EDQUOT:
60                         case -ENFILE:
61                         case -ENOMEM:
62                                 /*
63                                  * The keyring is full. Clear the keyring and try again
64                                  */
65                                 rc = keyring_clear(DEFAULT_KEYRING);
66                                 if (rc == 0)
67                                         rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
68                                 break;
69                         default:
70                                 break;
71                         }
72                 }
73                 if (rc < 0)
74                         xlog_err("id_lookup: keyctl_instantiate failed: %m");
75         }
76
77         return rc;
78 }
79
80 /*
81  * Find the name@domain string from either a user or group id
82  */
83 int name_lookup(char *id, key_serial_t key, int type)
84 {
85         char name[IDMAP_NAMESZ];
86         char domain[NFS4_MAX_DOMAIN_LEN];
87         uid_t uid;
88         gid_t gid;
89         int rc;
90
91         rc = nfs4_get_default_domain(NULL, domain, NFS4_MAX_DOMAIN_LEN);
92         if (rc != 0) {
93                 rc = -1;
94                 xlog_err("name_lookup: nfs4_get_default_domain failed: %m");
95                 goto out;
96         }
97
98         if (type == USER) {
99                 uid = atoi(id);
100                 rc = nfs4_uid_to_name(uid, domain, name, IDMAP_NAMESZ);
101         } else {
102                 gid = atoi(id);
103                 rc = nfs4_gid_to_name(gid, domain, name, IDMAP_NAMESZ);
104         }
105         if (rc < 0)
106                 xlog_err("name_lookup: %s: failed: %m",
107                         (type == USER ? "nfs4_uid_to_name" : "nfs4_gid_to_name"));
108
109         if (rc == 0) {
110                 rc = keyctl_instantiate(key, &name, strlen(name), 0);
111                 if (rc < 0)
112                         xlog_err("name_lookup: keyctl_instantiate failed: %m");
113         }
114 out:
115         return rc;
116 }
117 /*
118  * Clear all the keys on the given keyring
119  */
120 static int keyring_clear(char *keyring)
121 {
122         FILE *fp;
123         char buf[BUFSIZ];
124         key_serial_t key;
125
126         if (keyring == NULL)
127                 keyring = DEFAULT_KEYRING;
128
129         if ((fp = fopen(PROCKEYS, "r")) == NULL) {
130                 xlog_err("fopen(%s) failed: %m", PROCKEYS);
131                 return 1;
132         }
133
134         while(fgets(buf, BUFSIZ, fp) != NULL) {
135                 if (strstr(buf, "keyring") == NULL)
136                         continue;
137                 if (strstr(buf, keyring) == NULL)
138                         continue;
139                 if (verbose) {
140                         *(strchr(buf, '\n')) = '\0';
141                         xlog_warn("clearing '%s'", buf);
142                 }
143                 /*
144                  * The key is the first arugment in the string
145                  */
146                 *(strchr(buf, ' ')) = '\0';
147                 sscanf(buf, "%x", &key);
148                 if (keyctl_clear(key) < 0) {
149                         xlog_err("keyctl_clear(0x%x) failed: %m", key);
150                         fclose(fp);
151                         return 1;
152                 }
153                 fclose(fp);
154                 return 0;
155         }
156         xlog_err("'%s' keyring was not found.", keyring);
157         fclose(fp);
158         return 1;
159 }
160 /*
161  * Revoke a key 
162  */
163 static int key_revoke(char *keystr, int keymask)
164 {
165         FILE *fp;
166         char buf[BUFSIZ], *ptr;
167         key_serial_t key;
168         int mask;
169
170         xlog_syslog(0);
171
172         if ((fp = fopen(PROCKEYS, "r")) == NULL) {
173                 xlog_err("fopen(%s) failed: %m", PROCKEYS);
174                 return 1;
175         }
176
177         while(fgets(buf, BUFSIZ, fp) != NULL) {
178                 if (strstr(buf, "keyring") != NULL)
179                         continue;
180
181                 mask = 0;
182                 if ((ptr = strstr(buf, "uid:")) != NULL)
183                         mask = UIDKEYS;
184                 else if ((ptr = strstr(buf, "gid:")) != NULL)
185                         mask = GIDKEYS;
186                 else 
187                         continue;
188
189                 if ((keymask & mask) == 0)
190                         continue;
191
192                 if (strncmp(ptr+4, keystr, strlen(keystr)) != 0)
193                         continue;
194
195                 if (verbose) {
196                         *(strchr(buf, '\n')) = '\0';
197                         xlog_warn("revoking '%s'", buf);
198                 }
199                 /*
200                  * The key is the first arugment in the string
201                  */
202                 *(strchr(buf, ' ')) = '\0';
203                 sscanf(buf, "%x", &key);
204
205                 if (keyctl_revoke(key) < 0) {
206                         xlog_err("keyctl_revoke(0x%x) failed: %m", key);
207                         fclose(fp);
208                         return 1;
209                 }
210
211                 keymask &= ~mask;
212                 if (keymask == 0) {
213                         fclose(fp);
214                         return 0;
215                 }
216         }
217         xlog_err("'%s' key was not found.", keystr);
218         fclose(fp);
219         return 1;
220 }
221
222 int main(int argc, char **argv)
223 {
224         char *arg;
225         char *value;
226         char *type;
227         int rc = 1, opt;
228         int timeout = 600;
229         key_serial_t key;
230         char *progname, *keystr = NULL;
231         int clearing = 0, keymask = 0;
232
233         /* Set the basename */
234         if ((progname = strrchr(argv[0], '/')) != NULL)
235                 progname++;
236         else
237                 progname = argv[0];
238
239         xlog_open(progname);
240
241         while ((opt = getopt(argc, argv, "u:g:r:ct:v")) != -1) {
242                 switch (opt) {
243                 case 'u':
244                         keymask = UIDKEYS;
245                         keystr = strdup(optarg);
246                         break;
247                 case 'g':
248                         keymask = GIDKEYS;
249                         keystr = strdup(optarg);
250                         break;
251                 case 'r':
252                         keymask = GIDKEYS|UIDKEYS;
253                         keystr = strdup(optarg);
254                         break;
255                 case 'c':
256                         clearing++;
257                         break;
258                 case 'v':
259                         verbose++;
260                         break;
261                 case 't':
262                         timeout = atoi(optarg);
263                         break;
264                 default:
265                         xlog_warn(usage, progname);
266                         break;
267                 }
268         }
269
270         if (keystr) {
271                 rc = key_revoke(keystr, keymask);
272                 return rc;              
273         }
274         if (clearing) {
275                 xlog_syslog(0);
276                 rc = keyring_clear(DEFAULT_KEYRING);
277                 return rc;              
278         }
279
280         xlog_stderr(0);
281         if ((argc - optind) != 2) {
282                 xlog_err("Bad arg count. Check /etc/request-key.conf");
283                 xlog_warn(usage, progname);
284                 return 1;
285         }
286
287         if (verbose)
288                 nfs4_set_debug(verbose, NULL);
289
290         key = strtol(argv[optind++], NULL, 10);
291
292         arg = strdup(argv[optind]);
293         if (arg == NULL) {
294                 xlog_err("strdup failed: %m");
295                 return 1;
296         }
297         type = strtok(arg, ":");
298         value = strtok(NULL, ":");
299
300         if (verbose) {
301                 xlog_warn("key: 0x%lx type: %s value: %s timeout %ld",
302                         key, type, value, timeout);
303         }
304
305         if (strcmp(type, "uid") == 0)
306                 rc = id_lookup(value, key, USER);
307         else if (strcmp(type, "gid") == 0)
308                 rc = id_lookup(value, key, GROUP);
309         else if (strcmp(type, "user") == 0)
310                 rc = name_lookup(value, key, USER);
311         else if (strcmp(type, "group") == 0)
312                 rc = name_lookup(value, key, GROUP);
313
314         /* Set timeout to 10 (600 seconds) minutes */
315         if (rc == 0)
316                 keyctl_set_timeout(key, timeout);
317
318         free(arg);
319         return rc;
320 }