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);
64 strget(const char *str, const char *substr)
70 substrptr = strstr(str, substr);
75 sublen = strlen(substr);
78 /* if there's nothing after the prefix, return NULL */
79 if (*substrptr == '\0')
86 * Convert a string representation of unsigned int into a numeric one. Also
87 * check for incomplete string conversion and overflow.
90 str_to_uint(const char *src, unsigned int *dst)
96 tmp = strtoul(src, &end, 0);
103 *dst = (unsigned int)tmp;
108 cifs_idmap(const key_serial_t key, const char *key_descr)
113 struct cifs_uxid cuxid;
116 * Use winbind to convert received string to a SID and lookup
117 * name and map that SID to an uid. If either of these
118 * function calls return with an error, return an error the
119 * upcall caller. Otherwise instanticate a key using that uid.
121 * The same applies to SID and gid mapping.
123 sidstr = strget(key_descr, "os:");
125 rc = str_to_sid(plugin_handle, sidstr, &sid);
127 syslog(LOG_DEBUG, "Unable to convert owner string %s "
128 "to SID: %s", key_descr, plugin_errmsg);
132 rc = sids_to_ids(plugin_handle, &sid, 1, &cuxid);
133 if (rc || (cuxid.type != CIFS_UXID_TYPE_UID &&
134 cuxid.type != CIFS_UXID_TYPE_BOTH)) {
135 syslog(LOG_DEBUG, "Unable to convert %s to "
136 "UID: %s", key_descr, plugin_errmsg);
137 rc = rc ? rc : -EINVAL;
140 rc = keyctl_instantiate(key, &cuxid.id.uid, sizeof(uid_t), 0);
142 syslog(LOG_ERR, "%s: key inst: %s", __func__,
148 sidstr = strget(key_descr, "gs:");
150 rc = str_to_sid(plugin_handle, sidstr, &sid);
152 syslog(LOG_DEBUG, "Unable to convert group string %s "
153 "to SID: %s", key_descr, plugin_errmsg);
157 rc = sids_to_ids(plugin_handle, &sid, 1, &cuxid);
158 if (rc || (cuxid.type != CIFS_UXID_TYPE_GID &&
159 cuxid.type != CIFS_UXID_TYPE_BOTH)) {
160 syslog(LOG_DEBUG, "Unable to convert %s to "
161 "GID: %s", key_descr, plugin_errmsg);
162 rc = rc ? rc : -EINVAL;
165 rc = keyctl_instantiate(key, &cuxid.id.gid, sizeof(gid_t), 0);
167 syslog(LOG_ERR, "%s: key inst: %s", __func__,
173 sidstr = strget(key_descr, "oi:");
175 rc = str_to_uint(sidstr, (unsigned int *)&cuxid.id.uid);
177 syslog(LOG_ERR, "Unable to convert %s to uid: %s",
178 sidstr, strerror(rc));
181 cuxid.type = CIFS_UXID_TYPE_UID;
183 syslog(LOG_DEBUG, "SID: %s, uid: %u", sidstr, cuxid.id.uid);
184 rc = ids_to_sids(plugin_handle, &cuxid, 1, &sid);
185 if (rc || sid.revision == 0) {
186 syslog(LOG_DEBUG, "uid %u to SID error: %s",
187 cuxid.id.uid, plugin_errmsg);
191 rc = keyctl_instantiate(key, &sid, sizeof(struct cifs_sid), 0);
193 syslog(LOG_ERR, "%s: key inst: %s", __func__,
199 sidstr = strget(key_descr, "gi:");
201 rc = str_to_uint(sidstr, (unsigned int *)&cuxid.id.gid);
203 syslog(LOG_ERR, "Unable to convert %s to gid: %s",
204 sidstr, strerror(rc));
207 cuxid.type = CIFS_UXID_TYPE_GID;
209 syslog(LOG_DEBUG, "SID: %s, gid: %u", sidstr, cuxid.id.gid);
210 rc = ids_to_sids(plugin_handle, &cuxid, 1, &sid);
211 if (rc || sid.revision == 0) {
212 syslog(LOG_DEBUG, "gid %u to SID error: %s",
213 cuxid.id.gid, plugin_errmsg);
217 rc = keyctl_instantiate(key, &sid, sizeof(struct cifs_sid), 0);
219 syslog(LOG_ERR, "%s: key inst: %s", __func__,
225 syslog(LOG_DEBUG, "Invalid key: %s", key_descr);
231 int main(const int argc, char *const argv[])
235 key_serial_t key = 0;
237 unsigned int timeout = 600; /* default idmap cache timeout */
239 openlog(prog, 0, LOG_DAEMON);
241 while ((c = getopt_long(argc, argv, "ht:v",
242 long_options, NULL)) != -1) {
249 rc = str_to_uint(optarg, &timeout);
251 syslog(LOG_ERR, "bad timeout value %s: %s",
252 optarg, strerror(rc));
258 printf("version: %s\n", VERSION);
262 syslog(LOG_ERR, "unknown option: %c", c);
268 /* is there a key? */
269 if (argc <= optind) {
274 /* get key and keyring values */
276 key = strtol(argv[optind], NULL, 10);
279 syslog(LOG_ERR, "Invalid key format: %s", strerror(errno));
283 if (init_plugin(&plugin_handle)) {
284 plugin_handle = NULL;
285 syslog(LOG_ERR, "Unable to initialize ID mapping plugin: %s",
290 /* set timeout on key */
291 rc = keyctl_set_timeout(key, timeout);
293 syslog(LOG_ERR, "unable to set key timeout: %s",
295 goto out_exit_plugin;
298 rc = keyctl_describe_alloc(key, &buf);
300 syslog(LOG_ERR, "keyctl_describe_alloc failed: %s",
302 goto out_exit_plugin;
305 syslog(LOG_DEBUG, "key description: %s", buf);
307 rc = cifs_idmap(key, buf);
309 exit_plugin(plugin_handle);