s3:winbindd_cm: remove useless cli_setup_signing_state(*cli, Undefined) call
[Samba/gbeck.git] / source3 / winbindd / idmap_hash / idmap_hash.c
blob42830720f3c5ba32892a5806975f6da560040f86
1 /*
2 * idmap_hash.c
4 * Copyright (C) Gerald Carter <jerry@samba.org> 2007 - 2008
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "winbindd/winbindd.h"
23 #include "idmap_hash.h"
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_IDMAP
28 struct sid_hash_table {
29 DOM_SID *sid;
32 struct sid_hash_table *hashed_domains = NULL;
34 /*********************************************************************
35 Hash a domain SID (S-1-5-12-aaa-bbb-ccc) to a 12bit number
36 ********************************************************************/
38 static uint32_t hash_domain_sid(const DOM_SID *sid)
40 uint32_t hash;
42 if (sid->num_auths != 4)
43 return 0;
45 /* XOR the last three subauths */
47 hash = ((sid->sub_auths[1] ^ sid->sub_auths[2]) ^ sid->sub_auths[3]);
49 /* Take all 32-bits into account when generating the 12-bit
50 hash value */
51 hash = (((hash & 0xFFF00000) >> 20)
52 + ((hash & 0x000FFF00) >> 8)
53 + (hash & 0x000000FF)) & 0x0000FFF;
55 /* return a 12-bit hash value */
57 return hash;
60 /*********************************************************************
61 Hash a Relative ID to a 20 bit number
62 ********************************************************************/
64 static uint32_t hash_rid(uint32_t rid)
66 /* 20 bits for the rid which allows us to support
67 the first 100K users/groups in a domain */
69 return (rid & 0x0007FFFF);
72 /*********************************************************************
73 ********************************************************************/
75 static uint32_t combine_hashes(uint32_t h_domain,
76 uint32_t h_rid)
78 uint32_t return_id = 0;
80 /* shift the hash_domain 19 bits to the left and OR with the
81 hash_rid */
83 return_id = ((h_domain<<19) | h_rid);
85 return return_id;
88 /*********************************************************************
89 ********************************************************************/
91 static void separate_hashes(uint32_t id,
92 uint32_t *h_domain,
93 uint32_t *h_rid)
95 *h_rid = id & 0x0007FFFF;
96 *h_domain = (id & 0x7FF80000) >> 19;
98 return;
102 /*********************************************************************
103 ********************************************************************/
105 static NTSTATUS be_init(struct idmap_domain *dom,
106 const char *params)
108 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
109 struct winbindd_tdc_domain *dom_list = NULL;
110 size_t num_domains = 0;
111 int i;
113 /* If the domain SID hash talbe has been initialized, assume
114 that we completed this function previously */
116 if ( hashed_domains ) {
117 nt_status = NT_STATUS_OK;
118 goto done;
121 if (!wcache_tdc_fetch_list(&dom_list, &num_domains)) {
122 nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE;
123 BAIL_ON_NTSTATUS_ERROR(nt_status);
126 /* Create the hash table of domain SIDs */
128 hashed_domains = TALLOC_ZERO_ARRAY(NULL, struct sid_hash_table, 4096);
129 BAIL_ON_PTR_NT_ERROR(hashed_domains, nt_status);
131 /* create the hash table of domain SIDs */
133 for (i=0; i<num_domains; i++) {
134 uint32_t hash;
136 if (is_null_sid(&dom_list[i].sid))
137 continue;
138 if ((hash = hash_domain_sid(&dom_list[i].sid)) == 0)
139 continue;
141 DEBUG(5,("hash:be_init() Adding %s (%s) -> %d\n",
142 dom_list[i].domain_name,
143 sid_string_dbg(&dom_list[i].sid),
144 hash));
146 hashed_domains[hash].sid = talloc(hashed_domains, DOM_SID);
147 sid_copy(hashed_domains[hash].sid, &dom_list[i].sid);
150 done:
151 return nt_status;
154 /*********************************************************************
155 ********************************************************************/
157 static NTSTATUS unixids_to_sids(struct idmap_domain *dom,
158 struct id_map **ids)
160 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
161 int i;
163 /* initialize the status to avoid suprise */
164 for (i = 0; ids[i]; i++) {
165 ids[i]->status = ID_UNKNOWN;
168 nt_status = be_init(dom, NULL);
169 BAIL_ON_NTSTATUS_ERROR(nt_status);
171 if (!ids) {
172 nt_status = NT_STATUS_INVALID_PARAMETER;
173 BAIL_ON_NTSTATUS_ERROR(nt_status);
176 for (i=0; ids[i]; i++) {
177 uint32_t h_domain, h_rid;
179 ids[i]->status = ID_UNMAPPED;
181 separate_hashes(ids[i]->xid.id, &h_domain, &h_rid);
183 /* Make sure the caller allocated memor for us */
185 if (!ids[i]->sid) {
186 nt_status = NT_STATUS_INVALID_PARAMETER;
187 BAIL_ON_NTSTATUS_ERROR(nt_status);
190 /* If the domain hash doesn't find a SID in the table,
191 skip it */
193 if (!hashed_domains[h_domain].sid)
194 continue;
196 sid_copy(ids[i]->sid, hashed_domains[h_domain].sid);
197 sid_append_rid(ids[i]->sid, h_rid);
198 ids[i]->status = ID_MAPPED;
201 done:
202 return nt_status;
205 /*********************************************************************
206 ********************************************************************/
208 static NTSTATUS sids_to_unixids(struct idmap_domain *dom,
209 struct id_map **ids)
211 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
212 int i;
214 /* initialize the status to avoid suprise */
215 for (i = 0; ids[i]; i++) {
216 ids[i]->status = ID_UNKNOWN;
219 nt_status = be_init(dom, NULL);
220 BAIL_ON_NTSTATUS_ERROR(nt_status);
222 if (!ids) {
223 nt_status = NT_STATUS_INVALID_PARAMETER;
224 BAIL_ON_NTSTATUS_ERROR(nt_status);
227 for (i=0; ids[i]; i++) {
228 DOM_SID sid;
229 uint32_t rid;
230 uint32_t h_domain, h_rid;
232 ids[i]->status = ID_UNMAPPED;
234 sid_copy(&sid, ids[i]->sid);
235 sid_split_rid(&sid, &rid);
237 h_domain = hash_domain_sid(&sid);
238 h_rid = hash_rid(rid);
240 /* Check that both hashes are non-zero*/
242 if (h_domain && h_rid) {
243 ids[i]->xid.id = combine_hashes(h_domain, h_rid);
244 ids[i]->status = ID_MAPPED;
248 done:
249 return nt_status;
252 /*********************************************************************
253 ********************************************************************/
255 static NTSTATUS be_close(struct idmap_domain *dom)
257 if (hashed_domains)
258 talloc_free(hashed_domains);
260 return NT_STATUS_OK;
263 /*********************************************************************
264 ********************************************************************/
266 static NTSTATUS nss_hash_init(struct nss_domain_entry *e )
268 return be_init(NULL, NULL);
271 /**********************************************************************
272 *********************************************************************/
274 static NTSTATUS nss_hash_get_info(struct nss_domain_entry *e,
275 const DOM_SID *sid,
276 TALLOC_CTX *ctx,
277 ADS_STRUCT *ads,
278 LDAPMessage *msg,
279 char **homedir,
280 char **shell,
281 char **gecos,
282 gid_t *p_gid )
284 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
286 nt_status = nss_hash_init(e);
287 BAIL_ON_NTSTATUS_ERROR(nt_status);
289 if (!homedir || !shell || !gecos) {
290 nt_status = NT_STATUS_INVALID_PARAMETER;
291 BAIL_ON_NTSTATUS_ERROR(nt_status);
294 *homedir = talloc_strdup(ctx, lp_template_homedir());
295 BAIL_ON_PTR_NT_ERROR(*homedir, nt_status);
297 *shell = talloc_strdup(ctx, lp_template_shell());
298 BAIL_ON_PTR_NT_ERROR(*shell, nt_status);
300 *gecos = NULL;
302 /* Initialize the gid so that the upper layer fills
303 in the proper Windows primary group */
305 if (*p_gid) {
306 *p_gid = (gid_t)-1;
309 done:
310 return nt_status;
313 /**********************************************************************
314 *********************************************************************/
316 static NTSTATUS nss_hash_map_to_alias(TALLOC_CTX *mem_ctx,
317 struct nss_domain_entry *e,
318 const char *name,
319 char **alias)
321 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
322 const char *value;
324 value = talloc_asprintf(mem_ctx, "%s\\%s", e->domain, name);
325 BAIL_ON_PTR_NT_ERROR(value, nt_status);
327 nt_status = mapfile_lookup_key(mem_ctx, value, alias);
328 BAIL_ON_NTSTATUS_ERROR(nt_status);
330 done:
331 return nt_status;
334 /**********************************************************************
335 *********************************************************************/
337 static NTSTATUS nss_hash_map_from_alias(TALLOC_CTX *mem_ctx,
338 struct nss_domain_entry *e,
339 const char *alias,
340 char **name)
342 return mapfile_lookup_value(mem_ctx, alias, name);
345 /**********************************************************************
346 *********************************************************************/
348 static NTSTATUS nss_hash_close(void)
350 return NT_STATUS_OK;
353 /*********************************************************************
354 Dispatch Tables for IDMap and NssInfo Methods
355 ********************************************************************/
357 static struct idmap_methods hash_idmap_methods = {
358 .init = be_init,
359 .unixids_to_sids = unixids_to_sids,
360 .sids_to_unixids = sids_to_unixids,
361 .close_fn = be_close
364 static struct nss_info_methods hash_nss_methods = {
365 .init = nss_hash_init,
366 .get_nss_info = nss_hash_get_info,
367 .map_to_alias = nss_hash_map_to_alias,
368 .map_from_alias = nss_hash_map_from_alias,
369 .close_fn = nss_hash_close
372 /**********************************************************************
373 Register with the idmap and idmap_nss subsystems. We have to protect
374 against the idmap and nss_info interfaces being in a half-registered
375 state.
376 **********************************************************************/
378 NTSTATUS idmap_hash_init(void)
380 static NTSTATUS idmap_status = NT_STATUS_UNSUCCESSFUL;
381 static NTSTATUS nss_status = NT_STATUS_UNSUCCESSFUL;
383 if ( !NT_STATUS_IS_OK(idmap_status) ) {
384 idmap_status = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
385 "hash", &hash_idmap_methods);
387 if ( !NT_STATUS_IS_OK(idmap_status) ) {
388 DEBUG(0,("Failed to register hash idmap plugin.\n"));
389 return idmap_status;
393 if ( !NT_STATUS_IS_OK(nss_status) ) {
394 nss_status = smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION,
395 "hash", &hash_nss_methods);
396 if ( !NT_STATUS_IS_OK(nss_status) ) {
397 DEBUG(0,("Failed to register hash idmap nss plugin.\n"));
398 return nss_status;
402 return NT_STATUS_OK;