]> git.decadent.org.uk Git - nfs-utils.git/blob - utils/nfsidmap/nfsidmap.c
nfsidmap: Allow keys to be cleared from the keyring
[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
7 #include <pwd.h>
8 #include <grp.h>
9 #include <keyutils.h>
10 #include <nfsidmap.h>
11
12 #include <unistd.h>
13 #include "xlog.h"
14
15 int verbose = 0;
16 char *usage="Usage: %s [-v] [-c || [-t timeout] key desc]";
17
18 #define MAX_ID_LEN   11
19 #define IDMAP_NAMESZ 128
20 #define USER  1
21 #define GROUP 0
22
23 #define PROCKEYS "/proc/keys"
24 #ifndef DEFAULT_KEYRING
25 #define DEFAULT_KEYRING "id_resolver"
26 #endif
27
28
29 /*
30  * Find either a user or group id based on the name@domain string
31  */
32 int id_lookup(char *name_at_domain, key_serial_t key, int type)
33 {
34         char id[MAX_ID_LEN];
35         uid_t uid = 0;
36         gid_t gid = 0;
37         int rc;
38
39         if (type == USER) {
40                 rc = nfs4_owner_to_uid(name_at_domain, &uid);
41                 sprintf(id, "%u", uid);
42         } else {
43                 rc = nfs4_group_owner_to_gid(name_at_domain, &gid);
44                 sprintf(id, "%u", gid);
45         }
46         if (rc < 0)
47                 xlog_err("id_lookup: %s: failed: %m",
48                         (type == USER ? "nfs4_owner_to_uid" : "nfs4_group_owner_to_gid"));
49
50         if (rc == 0) {
51                 rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
52                 if (rc < 0)
53                         xlog_err("id_lookup: keyctl_instantiate failed: %m");
54         }
55
56         return rc;
57 }
58
59 /*
60  * Find the name@domain string from either a user or group id
61  */
62 int name_lookup(char *id, key_serial_t key, int type)
63 {
64         char name[IDMAP_NAMESZ];
65         char domain[NFS4_MAX_DOMAIN_LEN];
66         uid_t uid;
67         gid_t gid;
68         int rc;
69
70         rc = nfs4_get_default_domain(NULL, domain, NFS4_MAX_DOMAIN_LEN);
71         if (rc != 0) {
72                 rc = -1;
73                 xlog_err("name_lookup: nfs4_get_default_domain failed: %m");
74                 goto out;
75         }
76
77         if (type == USER) {
78                 uid = atoi(id);
79                 rc = nfs4_uid_to_name(uid, domain, name, IDMAP_NAMESZ);
80         } else {
81                 gid = atoi(id);
82                 rc = nfs4_gid_to_name(gid, domain, name, IDMAP_NAMESZ);
83         }
84         if (rc < 0)
85                 xlog_err("name_lookup: %s: failed: %m",
86                         (type == USER ? "nfs4_uid_to_name" : "nfs4_gid_to_name"));
87
88         if (rc == 0) {
89                 rc = keyctl_instantiate(key, &name, strlen(name), 0);
90                 if (rc < 0)
91                         xlog_err("name_lookup: keyctl_instantiate failed: %m");
92         }
93 out:
94         return rc;
95 }
96 /*
97  * Clear all the keys on the given keyring
98  */
99 static int keyring_clear(char *keyring)
100 {
101         FILE *fp;
102         char buf[BUFSIZ];
103         key_serial_t key;
104
105         xlog_syslog(0);
106         if (keyring == NULL)
107                 keyring = DEFAULT_KEYRING;
108
109         if ((fp = fopen(PROCKEYS, "r")) == NULL) {
110                 xlog_err("fopen(%s) failed: %m", PROCKEYS);
111                 return 1;
112         }
113
114         while(fgets(buf, BUFSIZ, fp) != NULL) {
115                 if (strstr(buf, "keyring") == NULL)
116                         continue;
117                 if (strstr(buf, keyring) == NULL)
118                         continue;
119                 if (verbose) {
120                         *(strchr(buf, '\n')) = '\0';
121                         xlog_warn("clearing '%s'", buf);
122                 }
123                 /*
124                  * The key is the first arugment in the string
125                  */
126                 *(strchr(buf, ' ')) = '\0';
127                 sscanf(buf, "%x", &key);
128                 if (keyctl_clear(key) < 0) {
129                         xlog_err("keyctl_clear(0x%x) failed: %m", key);
130                         fclose(fp);
131                         return 1;
132                 }
133                 fclose(fp);
134                 return 0;
135         }
136         xlog_err("'%s' keyring was not found.", keyring);
137         fclose(fp);
138         return 1;
139 }
140
141 int main(int argc, char **argv)
142 {
143         char *arg;
144         char *value;
145         char *type;
146         int rc = 1, opt;
147         int timeout = 600;
148         key_serial_t key;
149         char *progname;
150         int clearring;
151
152         /* Set the basename */
153         if ((progname = strrchr(argv[0], '/')) != NULL)
154                 progname++;
155         else
156                 progname = argv[0];
157
158         xlog_open(progname);
159
160         while ((opt = getopt(argc, argv, "ct:v")) != -1) {
161                 switch (opt) {
162                 case 'c':
163                         clearring++;
164                         break;
165                 case 'v':
166                         verbose++;
167                         break;
168                 case 't':
169                         timeout = atoi(optarg);
170                         break;
171                 default:
172                         xlog_warn(usage, progname);
173                         break;
174                 }
175         }
176
177         if (clearring) {
178                 rc = keyring_clear(DEFAULT_KEYRING);
179                 return rc;              
180         }
181
182         xlog_stderr(0);
183         if ((argc - optind) != 2) {
184                 xlog_err("Bad arg count. Check /etc/request-key.conf");
185                 xlog_warn(usage, progname);
186                 return 1;
187         }
188
189         if (verbose)
190                 nfs4_set_debug(verbose, NULL);
191
192         key = strtol(argv[optind++], NULL, 10);
193
194         arg = strdup(argv[optind]);
195         if (arg == NULL) {
196                 xlog_err("strdup failed: %m");
197                 return 1;
198         }
199         type = strtok(arg, ":");
200         value = strtok(NULL, ":");
201
202         if (verbose) {
203                 xlog_warn("key: %ld type: %s value: %s timeout %ld",
204                         key, type, value, timeout);
205         }
206
207         if (strcmp(type, "uid") == 0)
208                 rc = id_lookup(value, key, USER);
209         else if (strcmp(type, "gid") == 0)
210                 rc = id_lookup(value, key, GROUP);
211         else if (strcmp(type, "user") == 0)
212                 rc = name_lookup(value, key, USER);
213         else if (strcmp(type, "group") == 0)
214                 rc = name_lookup(value, key, GROUP);
215
216         /* Set timeout to 10 (600 seconds) minutes */
217         if (rc == 0)
218                 keyctl_set_timeout(key, timeout);
219
220         free(arg);
221         return rc;
222 }