3 * Copyright (C) Shirish Pargaonkar (shirishp@us.ibm.com) 2011
5 * Used by /sbin/request-key.conf for handling
6 * cifs upcall for SID to uig/gid and uid/gid to SID mapping.
7 * You should have keyutils installed and add
8 * this lines to /etc/request-key.conf file:
10 create cifs.idmap * * /usr/local/sbin/cifs.idmap %k
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #endif /* HAVE_CONFIG_H */
33 #include <sys/types.h>
45 #include "idmap_plugin.h"
47 static void *plugin_handle;
49 static const char *prog = "cifs.idmap";
51 static const struct option long_options[] = {
52 {"help", 0, NULL, 'h'},
53 {"timeout", 1, NULL, 't'},
54 {"version", 0, NULL, 'v'},
58 static void usage(void)
60 fprintf(stderr, "Usage: %s [-h] [-v] [-t timeout] key_serial\n", prog);
63 char *strget(const char *str, const char *substr)
69 substrptr = strstr(str, substr);
74 sublen = strlen(substr);
77 /* if there's nothing after the prefix, return NULL */
78 if (*substrptr == '\0')
85 * Convert a string representation of unsigned int into a numeric one. Also
86 * check for incomplete string conversion and overflow.
89 str_to_uint(const char *src, unsigned int *dst)
95 tmp = strtoul(src, &end, 0);
102 *dst = (unsigned int)tmp;
107 cifs_idmap(const key_serial_t key, const char *key_descr)
112 struct cifs_uxid cuxid;
115 * Use winbind to convert received string to a SID and lookup
116 * name and map that SID to an uid. If either of these
117 * function calls return with an error, return an error the
118 * upcall caller. Otherwise instanticate a key using that uid.
120 * The same applies to SID and gid mapping.
122 sidstr = strget(key_descr, "os:");
124 rc = str_to_sid(plugin_handle, sidstr, &sid);
126 syslog(LOG_DEBUG, "Unable to convert owner string %s "
127 "to SID: %s", key_descr, plugin_errmsg);
131 rc = sids_to_ids(plugin_handle, &sid, 1, &cuxid);
132 if (rc || (cuxid.type != CIFS_UXID_TYPE_UID &&
133 cuxid.type != CIFS_UXID_TYPE_BOTH)) {
134 syslog(LOG_DEBUG, "Unable to convert %s to "
135 "UID: %s", key_descr, plugin_errmsg);
136 rc = rc ? rc : -EINVAL;
139 rc = keyctl_instantiate(key, &cuxid.id.uid, sizeof(uid_t), 0);
141 syslog(LOG_ERR, "%s: key inst: %s", __func__,
147 sidstr = strget(key_descr, "gs:");
149 rc = str_to_sid(plugin_handle, sidstr, &sid);
151 syslog(LOG_DEBUG, "Unable to convert group string %s "
152 "to SID: %s", key_descr, plugin_errmsg);
156 rc = sids_to_ids(plugin_handle, &sid, 1, &cuxid);
157 if (rc || (cuxid.type != CIFS_UXID_TYPE_GID &&
158 cuxid.type != CIFS_UXID_TYPE_BOTH)) {
159 syslog(LOG_DEBUG, "Unable to convert %s to "
160 "GID: %s", key_descr, plugin_errmsg);
161 rc = rc ? rc : -EINVAL;
164 rc = keyctl_instantiate(key, &cuxid.id.gid, sizeof(gid_t), 0);
166 syslog(LOG_ERR, "%s: key inst: %s", __func__,
172 sidstr = strget(key_descr, "oi:");
174 rc = str_to_uint(sidstr, (unsigned int *)&cuxid.id.uid);
176 syslog(LOG_ERR, "Unable to convert %s to uid: %s",
177 sidstr, strerror(rc));
180 cuxid.type = CIFS_UXID_TYPE_UID;
182 syslog(LOG_DEBUG, "SID: %s, uid: %u", sidstr, cuxid.id.uid);
183 rc = ids_to_sids(plugin_handle, &cuxid, 1, &sid);
184 if (rc || sid.revision == 0) {
185 syslog(LOG_DEBUG, "uid %u to SID error: %s",
186 cuxid.id.uid, plugin_errmsg);
190 rc = keyctl_instantiate(key, &sid, sizeof(struct cifs_sid), 0);
192 syslog(LOG_ERR, "%s: key inst: %s", __func__,
198 sidstr = strget(key_descr, "gi:");
200 rc = str_to_uint(sidstr, (unsigned int *)&cuxid.id.gid);
202 syslog(LOG_ERR, "Unable to convert %s to gid: %s",
203 sidstr, strerror(rc));
206 cuxid.type = CIFS_UXID_TYPE_GID;
208 syslog(LOG_DEBUG, "SID: %s, gid: %u", sidstr, cuxid.id.gid);
209 rc = ids_to_sids(plugin_handle, &cuxid, 1, &sid);
210 if (rc || sid.revision == 0) {
211 syslog(LOG_DEBUG, "gid %u to SID error: %s",
212 cuxid.id.gid, plugin_errmsg);
216 rc = keyctl_instantiate(key, &sid, sizeof(struct cifs_sid), 0);
218 syslog(LOG_ERR, "%s: key inst: %s", __func__,
224 syslog(LOG_DEBUG, "Invalid key: %s", key_descr);
230 int main(const int argc, char *const argv[])
234 key_serial_t key = 0;
236 unsigned int timeout = 600; /* default idmap cache timeout */
238 openlog(prog, 0, LOG_DAEMON);
240 while ((c = getopt_long(argc, argv, "ht:v",
241 long_options, NULL)) != -1) {
248 rc = str_to_uint(optarg, &timeout);
250 syslog(LOG_ERR, "bad timeout value %s: %s",
251 optarg, strerror(rc));
257 printf("version: %s\n", VERSION);
261 syslog(LOG_ERR, "unknown option: %c", c);
267 /* is there a key? */
268 if (argc <= optind) {
273 /* get key and keyring values */
275 key = strtol(argv[optind], NULL, 10);
278 syslog(LOG_ERR, "Invalid key format: %s", strerror(errno));
282 if (init_plugin(&plugin_handle)) {
283 plugin_handle = NULL;
284 syslog(LOG_ERR, "Unable to initialize ID mapping plugin: %s",
289 /* set timeout on key */
290 rc = keyctl_set_timeout(key, timeout);
292 syslog(LOG_ERR, "unable to set key timeout: %s",
294 goto out_exit_plugin;
297 rc = keyctl_describe_alloc(key, &buf);
299 syslog(LOG_ERR, "keyctl_describe_alloc failed: %s",
301 goto out_exit_plugin;
304 syslog(LOG_DEBUG, "key description: %s", buf);
306 rc = cifs_idmap(key, buf);
308 exit_plugin(plugin_handle);