cifs-utils: convert setcifsacl to use the plugin interface
[jlayton/cifs-utils.git] / idmapwb.c
1 /*
2  * Winbind ID Mapping Plugin
3  * Copyright (C) 2012 Jeff Layton (jlayton@samba.org)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif /* HAVE_CONFIG_H */
22
23 #include <stdint.h>
24 #include <endian.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <stdbool.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <wbclient.h>
31
32 #include "cifsidmap.h"
33
34 static const char **plugin_errmsg;
35
36 /*
37  * Winbind keeps wbcDomainSid fields in host-endian. Copy fields from the
38  * csid to the wsid, while converting the subauthority fields from LE.
39  */
40 static void
41 csid_to_wsid(struct wbcDomainSid *wsid, const struct cifs_sid *csid)
42 {
43         int i;
44         uint8_t num_subauth = (csid->num_subauth <= WBC_MAXSUBAUTHS) ?
45                                 csid->num_subauth : WBC_MAXSUBAUTHS;
46
47         wsid->sid_rev_num = csid->revision;
48         wsid->num_auths = num_subauth;
49         for (i = 0; i < NUM_AUTHS; i++)
50                 wsid->id_auth[i] = csid->authority[i];
51         for (i = 0; i < num_subauth; i++)
52                 wsid->sub_auths[i] = le32toh(csid->sub_auth[i]);
53 }
54
55 /*
56  * Winbind keeps wbcDomainSid fields in host-endian. Copy fields from the
57  * wsid to the csid, while converting the subauthority fields to LE.
58  */
59 static void
60 wsid_to_csid(struct cifs_sid *csid, struct wbcDomainSid *wsid)
61 {
62         int i;
63         uint8_t num_subauth = (wsid->num_auths <= SID_MAX_SUB_AUTHORITIES) ?
64                                 wsid->num_auths : SID_MAX_SUB_AUTHORITIES;
65
66         csid->revision = wsid->sid_rev_num;
67         csid->num_subauth = num_subauth;
68         for (i = 0; i < NUM_AUTHS; i++)
69                 csid->authority[i] = wsid->id_auth[i];
70         for (i = 0; i < num_subauth; i++)
71                 csid->sub_auth[i] = htole32(wsid->sub_auths[i]);
72 }
73
74 int
75 cifs_idmap_sid_to_str(void *handle __attribute__ ((unused)),
76                         const struct cifs_sid *csid, char **string)
77 {
78         int rc;
79         wbcErr wbcrc;
80         char *domain = NULL;
81         char *name = NULL;
82         enum wbcSidType sntype;
83         struct wbcDomainSid wsid;
84         size_t len;
85
86         csid_to_wsid(&wsid, csid);
87
88         wbcrc = wbcLookupSid(&wsid, &domain, &name, &sntype);
89         if (!WBC_ERROR_IS_OK(wbcrc)) {
90                 *plugin_errmsg = wbcErrorString(wbcrc);
91                 return -EIO;
92         }
93
94         /* +1 for '\\' and +1 for NULL terminator */
95         len = strlen(domain) + 1 + strlen(name) + 1;
96
97         *string = malloc(len);
98         if (!*string) {
99                 *plugin_errmsg = "Unable to allocate memory";
100                 rc = -ENOMEM;
101                 goto out;
102         }
103
104         rc = snprintf(*string, len, "%s\\%s", domain, name);
105         if (rc >= (long)len) {
106                 free(*string);
107                 *plugin_errmsg = "Resulting string was truncated";
108                 *string = NULL;
109                 rc = -EIO;
110         } else {
111                 rc = 0;
112         }
113 out:
114         wbcFreeMemory(domain);
115         wbcFreeMemory(name);
116         return rc;
117 }
118
119 int
120 cifs_idmap_str_to_sid(void *handle __attribute__ ((unused)),
121                         const char *orig, struct cifs_sid *csid)
122 {
123         wbcErr wbcrc;
124         char *name, *domain, *sidstr;
125         enum wbcSidType type;
126         struct wbcDomainSid wsid;
127
128         sidstr = strdup(orig);
129         if (!sidstr) {
130                 *plugin_errmsg = "Unable to copy string";
131                 return -ENOMEM;
132         }
133
134         name = strchr(sidstr, '\\');
135         if (!name) {
136                 /* might be a raw string representation of SID */
137                 wbcrc = wbcStringToSid(sidstr, &wsid);
138                 if (WBC_ERROR_IS_OK(wbcrc))
139                         goto convert_sid;
140
141                 domain = "";
142                 name = sidstr;
143         } else {
144                 domain = sidstr;
145                 *name = '\0';
146                 ++name;
147         }
148
149         wbcrc = wbcLookupName(domain, name, &wsid, &type);
150         /* FIXME: map these to better POSIX error codes? */
151         if (!WBC_ERROR_IS_OK(wbcrc)) {
152                 *plugin_errmsg = wbcErrorString(wbcrc);
153                 free(sidstr);
154                 return -EIO;
155         }
156
157 convert_sid:
158         wsid_to_csid(csid, &wsid);
159         free(sidstr);
160         return 0;
161 }
162
163 /*
164  * For the winbind plugin, we don't need to do anything special on
165  * init or exit
166  */
167 int
168 cifs_idmap_init_plugin(void **handle __attribute__((unused)), const char **errmsg)
169 {
170         plugin_errmsg = errmsg;
171         return 0;
172 }
173
174 void
175 cifs_idmap_exit_plugin(void *handle __attribute__((unused)))
176 {
177         return;
178 }