1/* 2 Unix SMB/CIFS implementation. 3 4 Winbind rpc backend functions 5 6 Copyright (C) Tim Potter 2000-2001,2003 7 Copyright (C) Simo Sorce 2003 8 Copyright (C) Volker Lendecke 2004 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 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., 675 Mass Ave, Cambridge, MA 02139, USA. 23*/ 24 25#include "includes.h" 26#include "winbindd.h" 27 28#undef DBGC_CLASS 29#define DBGC_CLASS DBGC_WINBIND 30 31static void 32add_member(const char *domain, const char *user, 33 char **members, int *num_members) 34{ 35 fstring name; 36 37 fill_domain_username(name, domain, user); 38 safe_strcat(name, ",", sizeof(name)-1); 39 string_append(members, name); 40 *num_members += 1; 41} 42 43/********************************************************************** 44 Add member users resulting from sid. Expand if it is a domain group. 45**********************************************************************/ 46 47static void 48add_expanded_sid(const DOM_SID *sid, char **members, int *num_members) 49{ 50 DOM_SID dom_sid; 51 uint32 rid; 52 struct winbindd_domain *domain; 53 int i; 54 55 char *domain_name = NULL; 56 char *name = NULL; 57 enum SID_NAME_USE type; 58 59 uint32 num_names; 60 DOM_SID **sid_mem; 61 char **names; 62 uint32 *types; 63 64 NTSTATUS result; 65 66 TALLOC_CTX *mem_ctx = talloc_init("add_expanded_sid"); 67 68 if (mem_ctx == NULL) { 69 DEBUG(1, ("talloc_init failed\n")); 70 return; 71 } 72 73 sid_copy(&dom_sid, sid); 74 sid_split_rid(&dom_sid, &rid); 75 76 domain = find_lookup_domain_from_sid(sid); 77 78 if (domain == NULL) { 79 DEBUG(3, ("Could not find domain for sid %s\n", 80 sid_string_static(sid))); 81 goto done; 82 } 83 84 result = domain->methods->sid_to_name(domain, mem_ctx, sid, 85 &domain_name, &name, &type); 86 87 if (!NT_STATUS_IS_OK(result)) { 88 DEBUG(3, ("sid_to_name failed for sid %s\n", 89 sid_string_static(sid))); 90 goto done; 91 } 92 93 DEBUG(10, ("Found name %s, type %d\n", name, type)); 94 95 if (type == SID_NAME_USER) { 96 add_member(domain_name, name, members, num_members); 97 goto done; 98 } 99 100 if (type != SID_NAME_DOM_GRP) { 101 DEBUG(10, ("Alias member %s neither user nor group, ignore\n", 102 name)); 103 goto done; 104 } 105 106 /* Expand the domain group, this must be done via the target domain */ 107 108 domain = find_domain_from_sid(sid); 109 110 if (domain == NULL) { 111 DEBUG(3, ("Could not find domain from SID %s\n", 112 sid_string_static(sid))); 113 goto done; 114 } 115 116 result = domain->methods->lookup_groupmem(domain, mem_ctx, 117 sid, &num_names, 118 &sid_mem, &names, 119 &types); 120 121 if (!NT_STATUS_IS_OK(result)) { 122 DEBUG(10, ("Could not lookup group members for %s: %s\n", 123 name, nt_errstr(result))); 124 goto done; 125 } 126 127 for (i=0; i<num_names; i++) { 128 DEBUG(10, ("Adding group member SID %s\n", 129 sid_string_static(sid_mem[i]))); 130 131 if (types[i] != SID_NAME_USER) { 132 DEBUG(1, ("Hmmm. Member %s of group %s is no user. " 133 "Ignoring.\n", names[i], name)); 134 continue; 135 } 136 137 add_member(domain->name, names[i], members, num_members); 138 } 139 140 done: 141 talloc_destroy(mem_ctx); 142 return; 143} 144 145BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain, 146 DOM_SID *group_sid, 147 int *num_gr_mem, char **gr_mem, int *gr_mem_len) 148{ 149 DOM_SID *members; 150 int i, num_members; 151 152 *num_gr_mem = 0; 153 *gr_mem = NULL; 154 *gr_mem_len = 0; 155 156 if (!pdb_enum_aliasmem(group_sid, &members, &num_members)) 157 return True; 158 159 for (i=0; i<num_members; i++) { 160 add_expanded_sid(&members[i], gr_mem, num_gr_mem); 161 } 162 163 SAFE_FREE(members); 164 165 if (*gr_mem != NULL) { 166 int len; 167 168 /* We have at least one member, strip off the last "," */ 169 len = strlen(*gr_mem); 170 (*gr_mem)[len-1] = '\0'; 171 *gr_mem_len = len; 172 } 173 174 return True; 175} 176 177/* Query display info for a domain. This returns enough information plus a 178 bit extra to give an overview of domain users for the User Manager 179 application. */ 180static NTSTATUS query_user_list(struct winbindd_domain *domain, 181 TALLOC_CTX *mem_ctx, 182 uint32 *num_entries, 183 WINBIND_USERINFO **info) 184{ 185 /* We don't have users */ 186 *num_entries = 0; 187 *info = NULL; 188 return NT_STATUS_OK; 189} 190 191/* list all domain groups */ 192static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, 193 TALLOC_CTX *mem_ctx, 194 uint32 *num_entries, 195 struct acct_info **info) 196{ 197 /* We don't have domain groups */ 198 *num_entries = 0; 199 *info = NULL; 200 return NT_STATUS_OK; 201} 202 203/* List all domain groups */ 204 205static NTSTATUS enum_local_groups(struct winbindd_domain *domain, 206 TALLOC_CTX *mem_ctx, 207 uint32 *num_entries, 208 struct acct_info **info) 209{ 210 struct acct_info *talloced_info; 211 212 /* Hmm. One billion aliases should be enough for a start */ 213 214 if (!pdb_enum_aliases(&domain->sid, 0, 1000000000, 215 num_entries, info)) { 216 /* Nothing to report, just exit. */ 217 return NT_STATUS_OK; 218 } 219 220 talloced_info = (struct acct_info *)TALLOC_MEMDUP(mem_ctx, *info, 221 *num_entries * sizeof(struct acct_info)); 222 223 SAFE_FREE(*info); 224 *info = talloced_info; 225 226 return NT_STATUS_OK; 227} 228 229/* convert a single name to a sid in a domain */ 230static NTSTATUS name_to_sid(struct winbindd_domain *domain, 231 TALLOC_CTX *mem_ctx, 232 const char *domain_name, 233 const char *name, 234 DOM_SID *sid, 235 enum SID_NAME_USE *type) 236{ 237 DEBUG(10, ("Finding name %s\n", name)); 238 239 if (!pdb_find_alias(name, sid)) 240 return NT_STATUS_NONE_MAPPED; 241 242 if (sid_check_is_in_builtin(sid)) 243 *type = SID_NAME_WKN_GRP; 244 else 245 *type = SID_NAME_ALIAS; 246 247 return NT_STATUS_OK; 248} 249 250/* 251 convert a domain SID to a user or group name 252*/ 253static NTSTATUS sid_to_name(struct winbindd_domain *domain, 254 TALLOC_CTX *mem_ctx, 255 const DOM_SID *sid, 256 char **domain_name, 257 char **name, 258 enum SID_NAME_USE *type) 259{ 260 struct acct_info info; 261 262 DEBUG(10, ("Converting SID %s\n", sid_string_static(sid))); 263 264 if (!pdb_get_aliasinfo(sid, &info)) 265 return NT_STATUS_NONE_MAPPED; 266 267 *domain_name = talloc_strdup(mem_ctx, domain->name); 268 *name = talloc_strdup(mem_ctx, info.acct_name); 269 if (sid_check_is_in_builtin(sid)) 270 *type = SID_NAME_WKN_GRP; 271 else 272 *type = SID_NAME_ALIAS; 273 274 return NT_STATUS_OK; 275} 276 277/* Lookup user information from a rid or username. */ 278static NTSTATUS query_user(struct winbindd_domain *domain, 279 TALLOC_CTX *mem_ctx, 280 const DOM_SID *user_sid, 281 WINBIND_USERINFO *user_info) 282{ 283 return NT_STATUS_NO_SUCH_USER; 284} 285 286/* Lookup groups a user is a member of. I wish Unix had a call like this! */ 287static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, 288 TALLOC_CTX *mem_ctx, 289 const DOM_SID *user_sid, 290 uint32 *num_groups, DOM_SID ***user_gids) 291{ 292 return NT_STATUS_NO_SUCH_USER; 293} 294 295static NTSTATUS lookup_useraliases(struct winbindd_domain *domain, 296 TALLOC_CTX *mem_ctx, 297 uint32 num_sids, DOM_SID **sids, 298 uint32 *num_aliases, uint32 **aliases) 299{ 300 return NT_STATUS_NO_SUCH_USER; 301} 302 303/* Lookup group membership given a rid. */ 304static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, 305 TALLOC_CTX *mem_ctx, 306 const DOM_SID *group_sid, uint32 *num_names, 307 DOM_SID ***sid_mem, char ***names, 308 uint32 **name_types) 309{ 310 return NT_STATUS_OK; 311} 312 313/* find the sequence number for a domain */ 314static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) 315{ 316 *seq = 1; 317 return NT_STATUS_OK; 318} 319 320/* get a list of trusted domains */ 321static NTSTATUS trusted_domains(struct winbindd_domain *domain, 322 TALLOC_CTX *mem_ctx, 323 uint32 *num_domains, 324 char ***names, 325 char ***alt_names, 326 DOM_SID **dom_sids) 327{ 328 NTSTATUS nt_status; 329 int enum_ctx = 0; 330 int num_sec_domains; 331 TRUSTDOM **domains; 332 *num_domains = 0; 333 *names = NULL; 334 *alt_names = NULL; 335 *dom_sids = NULL; 336 do { 337 int i; 338 nt_status = secrets_get_trusted_domains(mem_ctx, &enum_ctx, 1, 339 &num_sec_domains, 340 &domains); 341 *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names, char *, 342 num_sec_domains + *num_domains); 343 *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names, char *, 344 num_sec_domains + *num_domains); 345 *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids, DOM_SID, 346 num_sec_domains + *num_domains); 347 348 for (i=0; i< num_sec_domains; i++) { 349 if (pull_ucs2_talloc(mem_ctx, &(*names)[*num_domains], 350 domains[i]->name) == -1) { 351 return NT_STATUS_NO_MEMORY; 352 } 353 (*alt_names)[*num_domains] = NULL; 354 (*dom_sids)[*num_domains] = domains[i]->sid; 355 (*num_domains)++; 356 } 357 358 } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES)); 359 360 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) { 361 return NT_STATUS_OK; 362 } 363 return nt_status; 364} 365 366/* find the domain sid for a domain */ 367static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) 368{ 369 sid_copy(sid, &domain->sid); 370 return NT_STATUS_OK; 371} 372 373/* find alternate names list for the domain 374 * should we look for netbios aliases?? 375 SSS */ 376static NTSTATUS alternate_name(struct winbindd_domain *domain) 377{ 378 DEBUG(3,("pdb: alternate_name\n")); 379 380 return NT_STATUS_OK; 381} 382 383 384/* the rpc backend methods are exposed via this structure */ 385struct winbindd_methods passdb_methods = { 386 False, 387 query_user_list, 388 enum_dom_groups, 389 enum_local_groups, 390 name_to_sid, 391 sid_to_name, 392 query_user, 393 lookup_usergroups, 394 lookup_useraliases, 395 lookup_groupmem, 396 sequence_number, 397 trusted_domains, 398 domain_sid, 399 alternate_name 400}; 401