fix wrong string handling
[Samba.git] / source / sam / gums_helper.c
blobc22e6cf7ff8d35e53ba322749c2f87c46eb5d16f
1 /*
2 Unix SMB/CIFS implementation.
3 GUMS backends helper functions
4 Copyright (C) Simo Sorce 2002
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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "includes.h"
23 extern GUMS_FUNCTIONS *gums_storage;
25 extern DOM_SID global_sid_World;
26 extern DOM_SID global_sid_Builtin_Administrators;
27 extern DOM_SID global_sid_Builtin_Power_Users;
28 extern DOM_SID global_sid_Builtin_Account_Operators;
29 extern DOM_SID global_sid_Builtin_Server_Operators;
30 extern DOM_SID global_sid_Builtin_Print_Operators;
31 extern DOM_SID global_sid_Builtin_Backup_Operators;
32 extern DOM_SID global_sid_Builtin_Replicator;
33 extern DOM_SID global_sid_Builtin_Users;
34 extern DOM_SID global_sid_Builtin_Guests;
37 /* defines */
39 #define ALLOC_CHECK(str, ptr, err, label) do { if ((ptr) == NULL) { DEBUG(0, ("%s: out of memory!\n", str)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0)
40 #define NTSTATUS_CHECK(str1, str2, err, label) do { if (NT_STATUS_IS_ERR(err)) { DEBUG(0, ("%s: %s failed!\n", str1, str2)); } } while(0)
42 /****************************************************************************
43 Check if a user is a mapped group.
45 This function will check if the group SID is mapped onto a
46 system managed gid or onto a winbind manged sid.
47 In the first case it will be threated like a mapped group
48 and the backend should take the member list with a getgrgid
49 and ignore any user that have been possibly set into the group
50 object.
52 In the second case, the group is a fully SAM managed group
53 served back to the system through winbind. In this case the
54 members of a Local group are "unrolled" to cope with the fact
55 that unix cannot contain groups inside groups.
56 The backend MUST never call any getgr* / getpw* function or
57 loops with winbind may happen.
58 ****************************************************************************/
60 #if 0
61 NTSTATUS is_mapped_group(BOOL *mapped, const DOM_SID *sid)
63 NTSTATUS result;
64 gid_t id;
66 /* look if mapping exist, do not make idmap alloc an uid if SID is not found */
67 result = idmap_get_gid_from_sid(&id, sid, False);
68 if (NT_STATUS_IS_OK(result)) {
69 *mapped = gid_is_in_winbind_range(id);
70 } else {
71 *mapped = False;
74 return result;
76 #endif
78 /****************************************************************************
79 duplicate alloc luid_attr
80 ****************************************************************************/
81 NTSTATUS dupalloc_luid_attr(TALLOC_CTX *ctx, LUID_ATTR **new_la, LUID_ATTR old_la)
83 *new_la = (LUID_ATTR *)talloc(ctx, sizeof(LUID_ATTR));
84 if (*new_la == NULL) {
85 DEBUG(0,("dupalloc_luid_attr: could not Alloc memory to duplicate LUID_ATTR\n"));
86 return NT_STATUS_NO_MEMORY;
89 (*new_la)->luid.high = old_la.luid.high;
90 (*new_la)->luid.low = old_la.luid.low;
91 (*new_la)->attr = old_la.attr;
93 return NT_STATUS_OK;
96 /****************************************************************************
97 initialise a privilege list
98 ****************************************************************************/
99 void gums_init_privilege(PRIVILEGE_SET *priv_set)
101 priv_set->count=0;
102 priv_set->control=0;
103 priv_set->set=NULL;
106 /****************************************************************************
107 add a privilege to a privilege array
108 ****************************************************************************/
109 NTSTATUS gums_add_privilege(PRIVILEGE_SET *priv_set, TALLOC_CTX *ctx, LUID_ATTR set)
111 LUID_ATTR *new_set;
113 /* check if the privilege is not already in the list */
114 if (gums_check_priv_in_privilege(priv_set, set))
115 return NT_STATUS_UNSUCCESSFUL;
117 /* we can allocate memory to add the new privilege */
119 new_set=(LUID_ATTR *)talloc_realloc(ctx, priv_set->set, (priv_set->count+1)*(sizeof(LUID_ATTR)));
120 if (new_set==NULL) {
121 DEBUG(0,("add_privilege: could not Realloc memory to add a new privilege\n"));
122 return NT_STATUS_NO_MEMORY;
125 new_set[priv_set->count].luid.high=set.luid.high;
126 new_set[priv_set->count].luid.low=set.luid.low;
127 new_set[priv_set->count].attr=set.attr;
129 priv_set->count++;
130 priv_set->set=new_set;
132 return NT_STATUS_OK;
135 /****************************************************************************
136 add all the privileges to a privilege array
137 ****************************************************************************/
138 NTSTATUS gums_add_all_privilege(PRIVILEGE_SET *priv_set, TALLOC_CTX *ctx)
140 NTSTATUS result = NT_STATUS_OK;
141 LUID_ATTR set;
143 set.attr=0;
144 set.luid.high=0;
146 set.luid.low=SE_PRIV_ADD_USERS;
147 result = gums_add_privilege(priv_set, ctx, set);
148 NTSTATUS_CHECK("add_all_privilege", "add_privilege", result, done);
150 set.luid.low=SE_PRIV_ADD_MACHINES;
151 result = gums_add_privilege(priv_set, ctx, set);
152 NTSTATUS_CHECK("add_all_privilege", "add_privilege", result, done);
154 set.luid.low=SE_PRIV_PRINT_OPERATOR;
155 result = gums_add_privilege(priv_set, ctx, set);
156 NTSTATUS_CHECK("add_all_privilege", "add_privilege", result, done);
158 done:
159 return result;
162 /****************************************************************************
163 check if the privilege list is empty
164 ****************************************************************************/
165 BOOL gums_check_empty_privilege(PRIVILEGE_SET *priv_set)
167 return (priv_set->count == 0);
170 /****************************************************************************
171 check if the privilege is in the privilege list
172 ****************************************************************************/
173 BOOL gums_check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
175 int i;
177 /* if the list is empty, obviously we can't have it */
178 if (gums_check_empty_privilege(priv_set))
179 return False;
181 for (i=0; i<priv_set->count; i++) {
182 LUID_ATTR *cur_set;
184 cur_set=&priv_set->set[i];
185 /* check only the low and high part. Checking the attr field has no meaning */
186 if( (cur_set->luid.low==set.luid.low) && (cur_set->luid.high==set.luid.high) )
187 return True;
190 return False;
193 /****************************************************************************
194 remove a privilege from a privilege array
195 ****************************************************************************/
196 NTSTATUS gums_remove_privilege(PRIVILEGE_SET *priv_set, TALLOC_CTX *ctx, LUID_ATTR set)
198 LUID_ATTR *new_set;
199 LUID_ATTR *old_set;
200 int i,j;
202 /* check if the privilege is in the list */
203 if (!gums_check_priv_in_privilege(priv_set, set))
204 return NT_STATUS_UNSUCCESSFUL;
206 /* special case if it's the only privilege in the list */
207 if (priv_set->count==1) {
208 gums_init_privilege(priv_set);
209 return NT_STATUS_OK;
213 * the privilege is there, create a new list,
214 * and copy the other privileges
217 old_set = priv_set->set;
219 new_set=(LUID_ATTR *)talloc(ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR)));
220 if (new_set==NULL) {
221 DEBUG(0,("remove_privilege: could not malloc memory for new privilege list\n"));
222 return NT_STATUS_NO_MEMORY;
225 for (i=0, j=0; i<priv_set->count; i++) {
226 if ((old_set[i].luid.low == set.luid.low) &&
227 (old_set[i].luid.high == set.luid.high)) {
228 continue;
231 new_set[j].luid.low = old_set[i].luid.low;
232 new_set[j].luid.high = old_set[i].luid.high;
233 new_set[j].attr = old_set[i].attr;
235 j++;
238 if (j != priv_set->count - 1) {
239 DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n"));
240 DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j));
241 return NT_STATUS_INTERNAL_ERROR;
244 /* ok everything is fine */
246 priv_set->count--;
247 priv_set->set=new_set;
249 return NT_STATUS_OK;
252 /****************************************************************************
253 duplicates a privilege array
254 ****************************************************************************/
255 NTSTATUS gums_dup_priv_set(PRIVILEGE_SET **new_priv_set, TALLOC_CTX *mem_ctx, PRIVILEGE_SET *priv_set)
257 LUID_ATTR *new_set;
258 LUID_ATTR *old_set;
259 int i;
261 *new_priv_set = (PRIVILEGE_SET *)talloc(mem_ctx, sizeof(PRIVILEGE_SET));
262 gums_init_privilege(*new_priv_set);
264 /* special case if there are no privileges in the list */
265 if (priv_set->count == 0) {
266 return NT_STATUS_OK;
270 * create a new list,
271 * and copy the other privileges
274 old_set = priv_set->set;
276 new_set = (LUID_ATTR *)talloc(mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR)));
277 if (new_set==NULL) {
278 DEBUG(0,("remove_privilege: could not malloc memory for new privilege list\n"));
279 return NT_STATUS_NO_MEMORY;
282 for (i=0; i < priv_set->count; i++) {
284 new_set[i].luid.low = old_set[i].luid.low;
285 new_set[i].luid.high = old_set[i].luid.high;
286 new_set[i].attr = old_set[i].attr;
289 (*new_priv_set)->count = priv_set->count;
290 (*new_priv_set)->control = priv_set->control;
291 (*new_priv_set)->set = new_set;
293 return NT_STATUS_OK;
296 #define ALIAS_DEFAULT_SACL_SA_RIGHTS 0x01050013
297 #define ALIAS_DEFAULT_DACL_SA_RIGHTS \
298 (READ_CONTROL_ACCESS | \
299 SA_RIGHT_ALIAS_LOOKUP_INFO | \
300 SA_RIGHT_ALIAS_GET_MEMBERS) /* 0x0002000c */
302 #define ALIAS_DEFAULT_SACL_SEC_ACE_FLAG (SEC_ACE_FLAG_FAILED_ACCESS | SEC_ACE_FLAG_SUCCESSFUL_ACCESS) /* 0xc0 */
305 #if 0
306 NTSTATUS create_builtin_alias_default_sec_desc(SEC_DESC **sec_desc, TALLOC_CTX *ctx)
308 DOM_SID *world = &global_sid_World;
309 DOM_SID *admins = &global_sid_Builtin_Administrators;
310 SEC_ACCESS sa;
311 SEC_ACE sacl_ace;
312 SEC_ACE dacl_aces[2];
313 SEC_ACL *sacl = NULL;
314 SEC_ACL *dacl = NULL;
315 size_t psize;
317 init_sec_access(&sa, ALIAS_DEFAULT_SACL_SA_RIGHTS);
318 init_sec_ace(&sacl_ace, world, SEC_ACE_TYPE_SYSTEM_AUDIT, sa, ALIAS_DEFAULT_SACL_SEC_ACE_FLAG);
320 sacl = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &sacl_ace);
321 if (!sacl) {
322 DEBUG(0, ("build_init_sec_desc: Failed to make SEC_ACL.\n"));
323 return NT_STATUS_NO_MEMORY;
326 init_sec_access(&sa, ALIAS_DEFAULT_DACL_SA_RIGHTS);
327 init_sec_ace(&(dacl_aces[0]), world, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);
328 init_sec_access(&sa, SA_RIGHT_ALIAS_ALL_ACCESS);
329 init_sec_ace(&(dacl_aces[1]), admins, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);
331 dacl = make_sec_acl(ctx, NT4_ACL_REVISION, 2, dacl_aces);
332 if (!sacl) {
333 DEBUG(0, ("build_init_sec_desc: Failed to make SEC_ACL.\n"));
334 return NT_STATUS_NO_MEMORY;
337 *sec_desc = make_sec_desc(ctx, SEC_DESC_REVISION, admins, admins, sacl, dacl, &psize);
338 if (!(*sec_desc)) {
339 DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n"));
340 return NT_STATUS_NO_MEMORY;
343 return NT_STATUS_OK;
346 NTSTATUS sec_desc_add_ace_to_dacl(SEC_DESC *sec_desc, TALLOC_CTX *ctx, DOM_SID *sid, uint32 mask)
348 NTSTATUS result;
349 SEC_ACE *new_aces;
350 unsigned num_aces;
351 int i;
353 num_aces = sec_desc->dacl->num_aces + 1;
354 result = sec_ace_add_sid(ctx, &new_aces, sec_desc->dacl->ace, &num_aces, sid, mask);
355 if (NT_STATUS_IS_OK(result)) {
356 sec_desc->dacl->ace = new_aces;
357 sec_desc->dacl->num_aces = num_aces;
358 sec_desc->dacl->size = SEC_ACL_HEADER_SIZE;
359 for (i = 0; i < num_aces; i++) {
360 sec_desc->dacl->size += sec_desc->dacl->ace[i].size;
363 return result;
366 NTSTATUS gums_init_builtin_groups(void)
368 NTSTATUS result;
369 GUMS_OBJECT g_obj;
370 GUMS_GROUP *g_grp;
371 GUMS_PRIVILEGE g_priv;
373 /* Build the well known Builtin Local Groups */
374 g_obj.type = GUMS_OBJ_GROUP;
375 g_obj.version = 1;
376 g_obj.seq_num = 0;
377 g_obj.mem_ctx = talloc_init("gums_init_backend_acct");
378 if (g_obj.mem_ctx == NULL) {
379 DEBUG(0, ("gums_init_backend: Out of Memory!\n"));
380 return NT_STATUS_NO_MEMORY;
383 /* Administrators * /
385 /* alloc group structure */
386 g_obj.data.group = (GUMS_GROUP *)talloc(g_obj.mem_ctx, sizeof(GUMS_GROUP));
387 ALLOC_CHECK("gums_init_backend", g_obj.data.group, result, done);
389 /* make admins sid */
390 g_grp = (GUMS_GROUP *)g_obj.data.group;
391 sid_copy(g_obj.sid, &global_sid_Builtin_Administrators);
393 /* make security descriptor */
394 result = create_builtin_alias_default_sec_desc(&(g_obj.sec_desc), g_obj.mem_ctx);
395 NTSTATUS_CHECK("gums_init_backend", "create_builtin_alias_default_sec_desc", result, done);
397 /* make privilege set */
398 /* From BDC join trace:
399 SeSecurityPrivilege
400 SeBackupPrivilege
401 SeRestorePrivilege
402 SeSystemtimePrivilege
403 SeShutdownPrivilege
404 SeRemoteShutdownPrivilege
405 SeTakeOwnershipPrivilege
406 SeDebugPrivilege
407 SeSystemEnvironmentPrivilege
408 SeSystemProfilePrivilege
409 SeProfileSingleProcessPrivilege
410 SeIncreaseBasePriorityPrivilege
411 SeLocalDriverPrivilege
412 SeCreatePagefilePrivilege
413 SeIncreaseQuotaPrivilege
416 /* set name */
417 g_obj.name = talloc_strdup(g_obj.mem_ctx, "Administrators");
418 ALLOC_CHECK("gums_init_backend", g_obj.name, result, done);
420 /* set description */
421 g_obj.description = talloc_strdup(g_obj.mem_ctx, "Members can fully administer the computer/domain");
422 ALLOC_CHECK("gums_init_backend", g_obj.description, result, done);
424 /* numebr of group members */
425 g_grp->count = 0;
426 g_grp->members = NULL;
428 /* store Administrators group */
429 result = gums_storage->set_object(&g_obj);
431 /* Power Users */
432 /* Domain Controllers Does NOT have power Users */
434 sid_copy(g_obj.sid, &global_sid_Builtin_Power_Users);
436 /* make privilege set */
437 /* SE_PRIV_??? */
439 /* set name */
440 g_obj.name = talloc_strdup(g_obj.mem_ctx, "Power Users");
441 ALLOC_CHECK("gums_init_backend", g_obj.name, result, done);
443 /* set description */
444 /* > */ g_obj.description = talloc_strdup(g_obj.mem_ctx, "Power Users");
445 ALLOC_CHECK("gums_init_backend", g_obj.description, result, done);
447 /* store Power Users group */
448 result = gums_storage->set_object(&g_obj);
450 /* Account Operators */
452 sid_copy(g_obj.sid, &global_sid_Builtin_Account_Operators);
454 /* make privilege set */
455 /* From BDC join trace:
456 SeShutdownPrivilege
459 /* set name */
460 g_obj.name = talloc_strdup(g_obj.mem_ctx, "Account Operators");
461 ALLOC_CHECK("gums_init_backend", g_obj.name, result, done);
463 /* set description */
464 g_obj.description = talloc_strdup(g_obj.mem_ctx, "Members can administer domain user and group accounts");
465 ALLOC_CHECK("gums_init_backend", g_obj.description, result, done);
467 /* store Account Operators group */
468 result = gums_storage->set_object(&g_obj);
470 /* Server Operators */
472 sid_copy(g_obj.sid, &global_sid_Builtin_Server_Operators);
474 /* make privilege set */
475 /* From BDC join trace:
476 SeBackupPrivilege
477 SeRestorePrivilege
478 SeSystemtimePrivilege
479 SeShutdownPrivilege
480 SeRemoteShutdownPrivilege
483 /* set name */
484 g_obj.name = talloc_strdup(g_obj.mem_ctx, "Server Operators");
485 ALLOC_CHECK("gums_init_backend", g_obj.name, result, done);
487 /* set description */
488 g_obj.description = talloc_strdup(g_obj.mem_ctx, "Members can administer domain servers");
489 ALLOC_CHECK("gums_init_backend", g_obj.description, result, done);
491 /* store Server Operators group */
492 result = gums_storage->set_object(&g_obj);
494 /* Print Operators */
496 sid_copy(g_obj.sid, &global_sid_Builtin_Print_Operators);
498 /* make privilege set */
499 /* From BDC join trace:
500 SeShutdownPrivilege
503 /* set name */
504 g_obj.name = talloc_strdup(g_obj.mem_ctx, "Print Operators");
505 ALLOC_CHECK("gums_init_backend", g_obj.name, result, done);
507 /* set description */
508 g_obj.description = talloc_strdup(g_obj.mem_ctx, "Members can administer domain printers");
509 ALLOC_CHECK("gums_init_backend", g_obj.description, result, done);
511 /* store Print Operators group */
512 result = gums_storage->set_object(&g_obj);
514 /* Backup Operators */
516 sid_copy(g_obj.sid, &global_sid_Builtin_Backup_Operators);
518 /* make privilege set */
519 /* From BDC join trace:
520 SeBackupPrivilege
521 SeRestorePrivilege
522 SeShutdownPrivilege
525 /* set name */
526 g_obj.name = talloc_strdup(g_obj.mem_ctx, "Backup Operators");
527 ALLOC_CHECK("gums_init_backend", g_obj.name, result, done);
529 /* set description */
530 g_obj.description = talloc_strdup(g_obj.mem_ctx, "Members can bypass file security to backup files");
531 ALLOC_CHECK("gums_init_backend", g_obj.description, result, done);
533 /* store Backup Operators group */
534 result = gums_storage->set_object(&g_obj);
536 /* Replicator */
538 sid_copy(g_obj.sid, &global_sid_Builtin_Replicator);
540 /* make privilege set */
541 /* From BDC join trace:
542 SeBackupPrivilege
543 SeRestorePrivilege
544 SeShutdownPrivilege
547 /* set name */
548 g_obj.name = talloc_strdup(g_obj.mem_ctx, "Replicator");
549 ALLOC_CHECK("gums_init_backend", g_obj.name, result, done);
551 /* set description */
552 g_obj.description = talloc_strdup(g_obj.mem_ctx, "Supports file replication in a domain");
553 ALLOC_CHECK("gums_init_backend", g_obj.description, result, done);
555 /* store Replicator group */
556 result = gums_storage->set_object(&g_obj);
558 /* Users */
560 sid_copy(g_obj.sid, &global_sid_Builtin_Users);
562 /* add ACE to sec dsec dacl */
563 sec_desc_add_ace_to_dacl(g_obj.sec_desc, g_obj.mem_ctx, &global_sid_Builtin_Account_Operators, ALIAS_DEFAULT_DACL_SA_RIGHTS);
564 sec_desc_add_ace_to_dacl(g_obj.sec_desc, g_obj.mem_ctx, &global_sid_Builtin_Power_Users, ALIAS_DEFAULT_DACL_SA_RIGHTS);
566 /* set name */
567 g_obj.name = talloc_strdup(g_obj.mem_ctx, "Users");
568 ALLOC_CHECK("gums_init_backend", g_obj.name, result, done);
570 /* set description */
571 g_obj.description = talloc_strdup(g_obj.mem_ctx, "Ordinary users");
572 ALLOC_CHECK("gums_init_backend", g_obj.description, result, done);
574 /* store Users group */
575 result = gums_storage->set_object(&g_obj);
577 /* Guests */
579 sid_copy(g_obj.sid, &global_sid_Builtin_Guests);
581 /* set name */
582 g_obj.name = talloc_strdup(g_obj.mem_ctx, "Guests");
583 ALLOC_CHECK("gums_init_backend", g_obj.name, result, done);
585 /* set description */
586 g_obj.description = talloc_strdup(g_obj.mem_ctx, "Users granted guest access to the computer/domain");
587 ALLOC_CHECK("gums_init_backend", g_obj.description, result, done);
589 /* store Guests group */
590 result = gums_storage->set_object(&g_obj);
592 /* set default privileges */
593 g_priv.type = GUMS_OBJ_GROUP;
594 g_priv.version = 1;
595 g_priv.seq_num = 0;
596 g_priv.mem_ctx = talloc_init("gums_init_backend_priv");
597 if (g_priv.mem_ctx == NULL) {
598 DEBUG(0, ("gums_init_backend: Out of Memory!\n"));
599 return NT_STATUS_NO_MEMORY;
604 done:
605 talloc_destroy(g_obj.mem_ctx);
606 talloc_destroy(g_priv.mem_ctx);
607 return result;
609 #endif