2 * Unix SMB/CIFS implementation.
3 * SMB parameters and setup
4 * Copyright (C) Andrew Tridgell 1992-1998
5 * Copyright (C) Simo Sorce 2000-2002
6 * Copyright (C) Gerald Carter 2000
7 * Copyright (C) Jeremy Allison 2001
8 * Copyright (C) Andrew Bartlett 2002
10 * This program is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License as published by the Free
12 * Software Foundation; either version 2 of the License, or (at your option)
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20 * You should have received a copy of the GNU General Public License along with
21 * this program; if not, write to the Free Software Foundation, Inc., 675
22 * Mass Ave, Cambridge, MA 02139, USA.
27 #include "tdbsam2_parse_info.h"
29 static int tdbgumm_debug_level = DBGC_ALL;
31 #define DBGC_CLASS tdbgumm_debug_level
33 #define TDBSAM_VERSION 20021215
34 #define TDB_FILE_NAME "tdbsam2.tdb"
35 #define NAMEPREFIX "NAME_"
36 #define SIDPREFIX "SID_"
37 #define PRIVILEGEPREFIX "PRIV_"
39 #define TDB_FORMAT_STRING "ddB"
41 #define TALLOC_CHECK(ptr, err, label) do { if ((ptr) == NULL) { DEBUG(0, ("%s: Out of memory!\n", __FUNCTION__)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0)
42 #define SET_OR_FAIL(func, label) do { if (NT_STATUS_IS_ERR(func)) { DEBUG(0, ("%s: Setting gums object data failed!\n", __FUNCTION__)); goto label; } } while(0)
44 struct tdbsam2_enum_objs {
49 struct tdbsam2_enum_objs *next;
53 struct tdbsam2_domain_data *domain;
54 struct tdbsam2_user_data *user;
55 struct tdbsam2_group_data *group;
58 struct tdbsam2_object {
61 union tdbsam2_data data;
64 static TDB_CONTEXT *tdbsam2_db;
66 struct tdbsam2_enum_objs **teo_handlers;
68 static NTSTATUS init_tdbsam2_object_from_buffer(struct tdbsam2_object *object, TALLOC_CTX *mem_ctx, char *buffer, int size)
71 NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
77 len = tdb_unpack (buffer, size, TDB_FORMAT_STRING,
80 &data_size, &obj_data);
85 /* version is checked inside this function so that backward compatibility code can be
87 this way we can easily handle database format upgrades */
88 if (object->version != TDBSAM_VERSION) {
89 DEBUG(3,("init_tdbsam2_object_from_buffer: Error, db object has wrong tdbsam version!\n"));
93 /* be sure the string is terminated before trying to parse it */
94 if (obj_data[data_size - 1] != '\0')
95 obj_data[data_size - 1] = '\0';
97 switch (object->type) {
99 object->data.domain = (struct tdbsam2_domain_data *)talloc(mem_ctx, sizeof(struct tdbsam2_domain_data));
100 TALLOC_CHECK(object->data.domain, ret, done);
101 memset(object->data.domain, 0, sizeof(struct tdbsam2_domain_data));
103 iret = gen_parse(mem_ctx, pinfo_tdbsam2_domain_data, (char *)(object->data.domain), obj_data);
107 object->data.group = (struct tdbsam2_group_data *)talloc(mem_ctx, sizeof(struct tdbsam2_group_data));
108 TALLOC_CHECK(object->data.group, ret, done);
109 memset(object->data.group, 0, sizeof(struct tdbsam2_group_data));
111 iret = gen_parse(mem_ctx, pinfo_tdbsam2_group_data, (char *)(object->data.group), obj_data);
113 case GUMS_OBJ_NORMAL_USER:
114 object->data.user = (struct tdbsam2_user_data *)talloc(mem_ctx, sizeof(struct tdbsam2_user_data));
115 TALLOC_CHECK(object->data.user, ret, done);
116 memset(object->data.user, 0, sizeof(struct tdbsam2_user_data));
118 iret = gen_parse(mem_ctx, pinfo_tdbsam2_user_data, (char *)(object->data.user), obj_data);
121 DEBUG(3,("init_tdbsam2_object_from_buffer: Error, wrong object type number!\n"));
126 DEBUG(0,("init_tdbsam2_object_from_buffer: Fatal Error! Unable to parse object!\n"));
127 DEBUG(0,("init_tdbsam2_object_from_buffer: DB Corrupted ?"));
137 static NTSTATUS init_buffer_from_tdbsam2_object(char **buffer, size_t *len, TALLOC_CTX *mem_ctx, struct tdbsam2_object *object)
145 return NT_STATUS_INVALID_PARAMETER;
147 switch (object->type) {
148 case GUMS_OBJ_DOMAIN:
149 buf1 = gen_dump(mem_ctx, pinfo_tdbsam2_domain_data, (char *)(object->data.domain), 0);
153 buf1 = gen_dump(mem_ctx, pinfo_tdbsam2_group_data, (char *)(object->data.group), 0);
155 case GUMS_OBJ_NORMAL_USER:
156 buf1 = gen_dump(mem_ctx, pinfo_tdbsam2_user_data, (char *)(object->data.user), 0);
159 DEBUG(3,("init_buffer_from_tdbsam2_object: Error, wrong object type number!\n"));
160 return NT_STATUS_UNSUCCESSFUL;
164 DEBUG(0, ("init_buffer_from_tdbsam2_object: Fatal Error! Unable to dump object!\n"));
165 return NT_STATUS_UNSUCCESSFUL;
168 buflen = tdb_pack(NULL, 0, TDB_FORMAT_STRING,
171 strlen(buf1) + 1, buf1);
173 *buffer = talloc(mem_ctx, buflen);
174 TALLOC_CHECK(*buffer, ret, done);
176 *len = tdb_pack(*buffer, buflen, TDB_FORMAT_STRING,
179 strlen(buf1) + 1, buf1);
181 if (*len != buflen) {
182 DEBUG(0, ("init_tdb_data_from_tdbsam2_object: somthing odd is going on here: bufflen (%d) != len (%d) in tdb_pack operations!\n",
185 ret = NT_STATUS_UNSUCCESSFUL;
194 static NTSTATUS opentdb(void)
198 get_private_directory(tdbfile);
199 pstrcat(tdbfile, "/");
200 pstrcat(tdbfile, TDB_FILE_NAME);
202 tdbsam2_db = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
205 DEBUG(0, ("opentdb: Unable to open database (%s)!\n", tdbfile));
206 return NT_STATUS_UNSUCCESSFUL;
213 static NTSTATUS get_object_by_sid(TALLOC_CTX *mem_ctx, struct tdbsam2_object *obj, const DOM_SID *sid)
219 if (!obj || !mem_ctx || !sid)
220 return NT_STATUS_INVALID_PARAMETER;
222 if (NT_STATUS_IS_ERR(ret = opentdb())) {
226 slprintf(keystr, sizeof(keystr)-1, "%s%s", SIDPREFIX, sid_string_static(sid));
228 key.dsize = strlen(keystr) + 1;
230 data = tdb_fetch(tdbsam2_db, key);
232 DEBUG(5, ("get_object_by_sid: Error fetching database, domain entry not found!\n"));
233 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam2_db)));
234 DEBUGADD(5, (" Key: %s\n", keystr));
235 return NT_STATUS_UNSUCCESSFUL;
238 if (NT_STATUS_IS_ERR(init_tdbsam2_object_from_buffer(obj, mem_ctx, data.dptr, data.dsize))) {
239 SAFE_FREE(data.dptr);
240 DEBUG(0, ("get_object_by_sid: Error fetching database, malformed entry!\n"));
241 return NT_STATUS_UNSUCCESSFUL;
243 SAFE_FREE(data.dptr);
249 static NTSTATUS get_object_by_name(TALLOC_CTX *mem_ctx, struct tdbsam2_object *obj, const char* name)
258 int obj_version, obj_type, obj_sidstr_len, len;
260 if (!obj || !mem_ctx || !name)
261 return NT_STATUS_INVALID_PARAMETER;
263 if (NT_STATUS_IS_ERR(ret = opentdb())) {
267 unix_strlower(name, -1, objname, sizeof(objname));
269 slprintf(keystr, sizeof(keystr)-1, "%s%s", NAMEPREFIX, objname);
271 key.dsize = strlen(keystr) + 1;
273 data = tdb_fetch(tdbsam2_db, key);
275 DEBUG(5, ("get_object_by_name: Error fetching database, domain entry not found!\n"));
276 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam2_db)));
277 DEBUGADD(5, (" Key: %s\n", keystr));
278 return NT_STATUS_UNSUCCESSFUL;
281 len = tdb_unpack(data.dptr, data.dsize, TDB_FORMAT_STRING,
284 &obj_sidstr_len, &obj_sidstr);
286 SAFE_FREE(data.dptr);
288 if (len == -1 || obj_version != TDBSAM_VERSION || obj_sidstr_len <= 0) {
289 DEBUG(5, ("get_object_by_name: Error unpacking database object!\n"));
290 return NT_STATUS_UNSUCCESSFUL;
293 if (!string_to_sid(&sid, obj_sidstr)) {
294 DEBUG(5, ("get_object_by_name: Error invalid sid string found in database object!\n"));
295 SAFE_FREE(obj_sidstr);
296 return NT_STATUS_UNSUCCESSFUL;
298 SAFE_FREE(obj_sidstr);
300 return get_object_by_sid(mem_ctx, obj, &sid);
303 static NTSTATUS store_object(TALLOC_CTX *mem_ctx, struct tdbsam2_object *object, BOOL new_obj)
307 TDB_DATA data, key, key2;
312 if (NT_STATUS_IS_ERR(ret = opentdb())) {
322 ret = init_buffer_from_tdbsam2_object(&(data.dptr), &(data.dsize), mem_ctx, object);
323 if (NT_STATUS_IS_ERR(ret))
326 switch (object->type) {
327 case GUMS_OBJ_DOMAIN:
328 slprintf(keystr, sizeof(keystr) - 1, "%s%s", SIDPREFIX, sid_string_static(object->data.domain->dom_sid));
329 slprintf(namestr, sizeof(namestr) - 1, "%s%s", NAMEPREFIX, object->data.domain->name);
333 slprintf(keystr, sizeof(keystr) - 1, "%s%s", SIDPREFIX, sid_string_static(object->data.group->group_sid));
334 slprintf(namestr, sizeof(namestr) - 1, "%s%s", NAMEPREFIX, object->data.group->name);
336 case GUMS_OBJ_NORMAL_USER:
337 slprintf(keystr, sizeof(keystr) - 1, "%s%s", SIDPREFIX, sid_string_static(object->data.user->user_sid));
338 slprintf(namestr, sizeof(namestr) - 1, "%s%s", NAMEPREFIX, object->data.user->name);
341 return NT_STATUS_UNSUCCESSFUL;
345 key.dsize = strlen(keystr) + 1;
347 if ((r = tdb_store(tdbsam2_db, key, data, flag)) != TDB_SUCCESS) {
348 DEBUG(0, ("store_object: Unable to modify SAM!\n"));
349 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam2_db)));
350 DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr));
351 if (r == TDB_ERR_EXISTS) return NT_STATUS_UNSUCCESSFUL;
352 return NT_STATUS_INTERNAL_DB_ERROR;
356 key2.dsize = strlen(namestr) + 1;
358 if ((r = tdb_store(tdbsam2_db, key2, key, flag)) != TDB_SUCCESS) {
359 DEBUG(0, ("store_object: Unable to modify SAM!\n"));
360 DEBUGADD(0, (" Error: %s", tdb_errorstr(tdbsam2_db)));
361 DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr));
362 if (r == TDB_ERR_EXISTS) return NT_STATUS_UNSUCCESSFUL;
363 return NT_STATUS_INTERNAL_DB_ERROR;
365 /* TODO: update the general database counter */
366 /* TODO: update this entry counter too */
371 static NTSTATUS get_next_sid(TALLOC_CTX *mem_ctx, DOM_SID **sid)
374 struct tdbsam2_object obj;
375 DOM_SID *dom_sid = get_global_sam_sid();
378 /* TODO: LOCK DOMAIN OBJECT */
379 ret = get_object_by_sid(mem_ctx, &obj, dom_sid);
380 if (NT_STATUS_IS_ERR(ret)) {
381 DEBUG(0, ("get_next_sid: unable to get root Domain object!\n"));
382 ret = NT_STATUS_INTERNAL_DB_ERROR;
386 new_rid = obj.data.domain->next_rid;
388 /* Increment the RID Counter */
389 obj.data.domain->next_rid++;
391 /* Store back Domain object */
392 ret = store_object(mem_ctx, &obj, False);
393 if (NT_STATUS_IS_ERR(ret)) {
394 DEBUG(0, ("get_next_sid: unable to update root Domain object!\n"));
395 ret = NT_STATUS_INTERNAL_DB_ERROR;
398 /* TODO: UNLOCK DOMAIN OBJECT */
400 *sid = sid_dup_talloc(mem_ctx, dom_sid);
401 TALLOC_CHECK(*sid, ret, error);
403 if (!sid_append_rid(*sid, new_rid)) {
404 DEBUG(0, ("get_next_sid: unable to build new SID !?!\n"));
405 ret = NT_STATUS_UNSUCCESSFUL;
415 static NTSTATUS user_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_user_data *userdata)
419 if (!object || !userdata) {
420 DEBUG(0, ("tdbsam2_user_data_to_gums_object: no NULL pointers are accepted here!\n"));
421 return NT_STATUS_UNSUCCESSFUL;
424 /* userdata->xcounter */
425 /* userdata->sec_desc */
427 SET_OR_FAIL(gums_set_object_sid(*object, userdata->user_sid), error);
428 SET_OR_FAIL(gums_set_object_name(*object, userdata->name), error);
430 SET_OR_FAIL(gums_set_user_pri_group(*object, userdata->group_sid), error);
432 if (userdata->description)
433 SET_OR_FAIL(gums_set_object_description(*object, userdata->description), error);
435 if (userdata->full_name)
436 SET_OR_FAIL(gums_set_user_fullname(*object, userdata->full_name), error);
438 if (userdata->home_dir)
439 SET_OR_FAIL(gums_set_user_homedir(*object, userdata->home_dir), error);
441 if (userdata->dir_drive)
442 SET_OR_FAIL(gums_set_user_dir_drive(*object, userdata->dir_drive), error);
444 if (userdata->logon_script)
445 SET_OR_FAIL(gums_set_user_logon_script(*object, userdata->logon_script), error);
447 if (userdata->profile_path)
448 SET_OR_FAIL(gums_set_user_profile_path(*object, userdata->profile_path), error);
450 if (userdata->workstations)
451 SET_OR_FAIL(gums_set_user_workstations(*object, userdata->workstations), error);
453 if (userdata->unknown_str)
454 SET_OR_FAIL(gums_set_user_unknown_str(*object, userdata->unknown_str), error);
456 if (userdata->munged_dial)
457 SET_OR_FAIL(gums_set_user_munged_dial(*object, userdata->munged_dial), error);
459 SET_OR_FAIL(gums_set_user_logon_divs(*object, userdata->logon_divs), error);
460 SET_OR_FAIL(gums_set_user_hours_len(*object, userdata->hours_len), error);
463 SET_OR_FAIL(gums_set_user_hours(*object, userdata->hours), error);
465 SET_OR_FAIL(gums_set_user_unknown_3(*object, userdata->unknown_3), error);
466 SET_OR_FAIL(gums_set_user_unknown_5(*object, userdata->unknown_5), error);
467 SET_OR_FAIL(gums_set_user_unknown_6(*object, userdata->unknown_6), error);
469 SET_OR_FAIL(gums_set_user_logon_time(*object, *(userdata->logon_time)), error);
470 SET_OR_FAIL(gums_set_user_logoff_time(*object, *(userdata->logoff_time)), error);
471 SET_OR_FAIL(gums_set_user_kickoff_time(*object, *(userdata->kickoff_time)), error);
472 SET_OR_FAIL(gums_set_user_pass_last_set_time(*object, *(userdata->pass_last_set_time)), error);
473 SET_OR_FAIL(gums_set_user_pass_can_change_time(*object, *(userdata->pass_can_change_time)), error);
474 SET_OR_FAIL(gums_set_user_pass_must_change_time(*object, *(userdata->pass_must_change_time)), error);
480 talloc_destroy((*object)->mem_ctx);
485 static NTSTATUS group_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_group_data *groupdata)
489 if (!object || !groupdata) {
490 DEBUG(0, ("tdbsam2_group_data_to_gums_object: no NULL pointers are accepted here!\n"));
491 return NT_STATUS_UNSUCCESSFUL;
494 /* groupdata->xcounter */
495 /* groupdata->sec_desc */
497 SET_OR_FAIL(gums_set_object_sid(*object, groupdata->group_sid), error);
498 SET_OR_FAIL(gums_set_object_name(*object, groupdata->name), error);
500 if (groupdata->description)
501 SET_OR_FAIL(gums_set_object_description(*object, groupdata->description), error);
503 if (groupdata->count)
504 SET_OR_FAIL(gums_set_group_members(*object, groupdata->count, groupdata->members), error);
510 talloc_destroy((*object)->mem_ctx);
515 static NTSTATUS domain_data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_domain_data *domdata)
520 if (!object || !*object || !domdata) {
521 DEBUG(0, ("tdbsam2_domain_data_to_gums_object: no NULL pointers are accepted here!\n"));
522 return NT_STATUS_UNSUCCESSFUL;
525 /* domdata->xcounter */
526 /* domdata->sec_desc */
528 SET_OR_FAIL(gums_set_object_sid(*object, domdata->dom_sid), error);
529 SET_OR_FAIL(gums_set_object_name(*object, domdata->name), error);
531 if (domdata->description)
532 SET_OR_FAIL(gums_set_object_description(*object, domdata->description), error);
538 talloc_destroy((*object)->mem_ctx);
543 static NTSTATUS data_to_gums_object(GUMS_OBJECT **object, struct tdbsam2_object *data)
548 if (!object || !data) {
549 DEBUG(0, ("tdbsam2_user_data_to_gums_object: no NULL structure pointers are accepted here!\n"));
550 ret = NT_STATUS_INVALID_PARAMETER;
554 ret = gums_create_object(object, data->type);
555 if (NT_STATUS_IS_ERR(ret)) {
556 DEBUG(5, ("tdbsam2_user_data_to_gums_object: error creating gums object!\n"));
560 switch (data->type) {
561 case GUMS_OBJ_DOMAIN:
562 ret = domain_data_to_gums_object(object, data->data.domain);
565 case GUMS_OBJ_NORMAL_USER:
566 ret = user_data_to_gums_object(object, data->data.user);
571 ret = group_data_to_gums_object(object, data->data.group);
575 ret = NT_STATUS_UNSUCCESSFUL;
583 /* GUMM object functions */
585 static NTSTATUS tdbsam2_get_domain_sid(DOM_SID *sid, const char* name)
589 struct tdbsam2_object obj;
594 return NT_STATUS_INVALID_PARAMETER;
596 mem_ctx = talloc_init("tdbsam2_get_domain_sid");
598 DEBUG(0, ("tdbsam2_new_object: Out of memory!\n"));
599 return NT_STATUS_NO_MEMORY;
602 if (NT_STATUS_IS_ERR(ret = opentdb())) {
606 unix_strlower(name, -1, domname, sizeof(domname));
608 ret = get_object_by_name(mem_ctx, &obj, domname);
610 if (NT_STATUS_IS_ERR(ret)) {
611 DEBUG(0, ("tdbsam2_get_domain_sid: Error fetching database!\n"));
615 if (obj.type != GUMS_OBJ_DOMAIN) {
616 DEBUG(5, ("tdbsam2_get_domain_sid: Requested object is not a domain!\n"));
617 ret = NT_STATUS_UNSUCCESSFUL;
621 sid_copy(sid, obj.data.domain->dom_sid);
626 talloc_destroy(mem_ctx);
630 static NTSTATUS tdbsam2_set_domain_sid (const DOM_SID *sid, const char *name)
634 struct tdbsam2_object obj;
639 return NT_STATUS_INVALID_PARAMETER;
641 mem_ctx = talloc_init("tdbsam2_set_domain_sid");
643 DEBUG(0, ("tdbsam2_new_object: Out of memory!\n"));
644 return NT_STATUS_NO_MEMORY;
647 if (tdbsam2_db == NULL) {
648 if (NT_STATUS_IS_ERR(ret = opentdb())) {
653 unix_strlower(name, -1, domname, sizeof(domname));
655 /* TODO: we need to lock this entry until updated! */
657 ret = get_object_by_name(mem_ctx, &obj, domname);
659 if (NT_STATUS_IS_ERR(ret)) {
660 DEBUG(0, ("tdbsam2_get_domain_sid: Error fetching database!\n"));
664 if (obj.type != GUMS_OBJ_DOMAIN) {
665 DEBUG(5, ("tdbsam2_get_domain_sid: Requested object is not a domain!\n"));
666 ret = NT_STATUS_UNSUCCESSFUL;
670 sid_copy(obj.data.domain->dom_sid, sid);
672 ret = store_object(mem_ctx, &obj, False);
675 /* TODO: unlock here */
676 if (mem_ctx) talloc_destroy(mem_ctx);
681 NTSTATUS (*get_sequence_number) (void);
684 extern DOM_SID global_sid_NULL;
686 static NTSTATUS tdbsam2_new_object(DOM_SID *sid, const char *name, const int obj_type)
690 struct tdbsam2_object obj;
692 NTTIME zero_time = {0,0};
693 const char *defpw = "NOPASSWORDXXXXXX";
694 uint8 defhours[21] = {255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255};
697 DEBUG(0, ("tdbsam2_new_object: no NULL pointers are accepted here!\n"));
698 return NT_STATUS_INVALID_PARAMETER;
701 mem_ctx = talloc_init("tdbsam2_new_object");
703 DEBUG(0, ("tdbsam2_new_object: Out of memory!\n"));
704 return NT_STATUS_NO_MEMORY;
708 obj.version = TDBSAM_VERSION;
711 case GUMS_OBJ_NORMAL_USER:
712 obj.data.user = (struct tdbsam2_user_data *)talloc_zero(mem_ctx, sizeof(struct tdbsam2_user_data));
713 TALLOC_CHECK(obj.data.user, ret, done);
715 get_next_sid(mem_ctx, &(obj.data.user->user_sid));
716 TALLOC_CHECK(obj.data.user->user_sid, ret, done);
717 sid_copy(sid, obj.data.user->user_sid);
719 obj.data.user->name = talloc_strdup(mem_ctx, name);
720 TALLOC_CHECK(obj.data.user, ret, done);
722 obj.data.user->xcounter = 1;
723 /*obj.data.user->sec_desc*/
724 obj.data.user->description = "";
725 obj.data.user->group_sid = &global_sid_NULL;
726 obj.data.user->logon_time = &zero_time;
727 obj.data.user->logoff_time = &zero_time;
728 obj.data.user->kickoff_time = &zero_time;
729 obj.data.user->pass_last_set_time = &zero_time;
730 obj.data.user->pass_can_change_time = &zero_time;
731 obj.data.user->pass_must_change_time = &zero_time;
733 obj.data.user->full_name = "";
734 obj.data.user->home_dir = "";
735 obj.data.user->dir_drive = "";
736 obj.data.user->logon_script = "";
737 obj.data.user->profile_path = "";
738 obj.data.user->workstations = "";
739 obj.data.user->unknown_str = "";
740 obj.data.user->munged_dial = "";
742 obj.data.user->lm_pw_ptr = defpw;
743 obj.data.user->nt_pw_ptr = defpw;
745 obj.data.user->logon_divs = 168;
746 obj.data.user->hours_len = 21;
747 obj.data.user->hours = &defhours;
749 obj.data.user->unknown_3 = 0x00ffffff;
750 obj.data.user->unknown_5 = 0x00020000;
751 obj.data.user->unknown_6 = 0x000004ec;
756 obj.data.group = (struct tdbsam2_group_data *)talloc_zero(mem_ctx, sizeof(struct tdbsam2_group_data));
757 TALLOC_CHECK(obj.data.group, ret, done);
759 get_next_sid(mem_ctx, &(obj.data.group->group_sid));
760 TALLOC_CHECK(obj.data.group->group_sid, ret, done);
761 sid_copy(sid, obj.data.group->group_sid);
763 obj.data.group->name = talloc_strdup(mem_ctx, name);
764 TALLOC_CHECK(obj.data.group, ret, done);
766 obj.data.group->xcounter = 1;
767 /*obj.data.group->sec_desc*/
768 obj.data.group->description = "";
772 case GUMS_OBJ_DOMAIN:
774 /* FIXME: should we check against global_sam_sid to make it impossible
775 to store more than one domain ? */
777 obj.data.domain = (struct tdbsam2_domain_data *)talloc_zero(mem_ctx, sizeof(struct tdbsam2_domain_data));
778 TALLOC_CHECK(obj.data.domain, ret, done);
780 obj.data.domain->dom_sid = sid_dup_talloc(mem_ctx, get_global_sam_sid());
781 TALLOC_CHECK(obj.data.domain->dom_sid, ret, done);
782 sid_copy(sid, obj.data.domain->dom_sid);
784 obj.data.domain->name = talloc_strdup(mem_ctx, name);
785 TALLOC_CHECK(obj.data.domain, ret, done);
787 obj.data.domain->xcounter = 1;
788 /*obj.data.domain->sec_desc*/
789 obj.data.domain->next_rid = 0x3e9;
790 obj.data.domain->description = "";
796 ret = NT_STATUS_UNSUCCESSFUL;
800 ret = store_object(mem_ctx, &obj, True);
803 talloc_destroy(mem_ctx);
807 static NTSTATUS tdbsam2_delete_object(const DOM_SID *sid)
810 struct tdbsam2_object obj;
816 DEBUG(0, ("tdbsam2_delete_object: no NULL pointers are accepted here!\n"));
817 return NT_STATUS_INVALID_PARAMETER;
820 mem_ctx = talloc_init("tdbsam2_delete_object");
822 DEBUG(0, ("tdbsam2_delete_object: Out of memory!\n"));
823 return NT_STATUS_NO_MEMORY;
826 if (tdbsam2_db == NULL) {
827 if (NT_STATUS_IS_ERR(ret = opentdb())) {
832 slprintf(keystr, sizeof(keystr)-1, "%s%s", SIDPREFIX, sid_string_static(sid));
834 key.dsize = strlen(keystr) + 1;
836 data = tdb_fetch(tdbsam2_db, key);
838 DEBUG(5, ("tdbsam2_delete_object: Error fetching database, SID entry not found!\n"));
839 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam2_db)));
840 DEBUGADD(5, (" Key: %s\n", keystr));
841 ret = NT_STATUS_UNSUCCESSFUL;
845 if (tdb_delete(tdbsam2_db, key) != TDB_SUCCESS) {
846 DEBUG(5, ("tdbsam2_delete_object: Error deleting object!\n"));
847 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam2_db)));
848 DEBUGADD(5, (" Key: %s\n", keystr));
849 ret = NT_STATUS_UNSUCCESSFUL;
853 if (NT_STATUS_IS_ERR(init_tdbsam2_object_from_buffer(&obj, mem_ctx, data.dptr, data.dsize))) {
854 SAFE_FREE(data.dptr);
855 DEBUG(0, ("tdbsam2_delete_object: Error fetching database, malformed entry!\n"));
856 ret = NT_STATUS_UNSUCCESSFUL;
861 case GUMS_OBJ_DOMAIN:
862 /* TODO: SHOULD WE ALLOW TO DELETE DOMAINS ? */
863 slprintf(keystr, sizeof(keystr) - 1, "%s%s", NAMEPREFIX, obj.data.domain->name);
867 slprintf(keystr, sizeof(keystr) - 1, "%s%s", NAMEPREFIX, obj.data.group->name);
869 case GUMS_OBJ_NORMAL_USER:
870 slprintf(keystr, sizeof(keystr) - 1, "%s%s", NAMEPREFIX, obj.data.user->name);
873 ret = NT_STATUS_UNSUCCESSFUL;
878 key.dsize = strlen(keystr) + 1;
880 if (tdb_delete(tdbsam2_db, key) != TDB_SUCCESS) {
881 DEBUG(5, ("tdbsam2_delete_object: Error deleting object!\n"));
882 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(tdbsam2_db)));
883 DEBUGADD(5, (" Key: %s\n", keystr));
884 ret = NT_STATUS_UNSUCCESSFUL;
888 /* TODO: update the general database counter */
891 SAFE_FREE(data.dptr);
892 talloc_destroy(mem_ctx);
896 static NTSTATUS tdbsam2_get_object_from_sid(GUMS_OBJECT **object, const DOM_SID *sid, const int obj_type)
899 struct tdbsam2_object obj;
902 if (!object || !sid) {
903 DEBUG(0, ("tdbsam2_get_object_from_sid: no NULL pointers are accepted here!\n"));
904 return NT_STATUS_INVALID_PARAMETER;
907 mem_ctx = talloc_init("tdbsam2_get_object_from_sid");
909 DEBUG(0, ("tdbsam2_get_object_from_sid: Out of memory!\n"));
910 return NT_STATUS_NO_MEMORY;
913 ret = get_object_by_sid(mem_ctx, &obj, sid);
914 if (NT_STATUS_IS_ERR(ret) || (obj_type && obj.type != obj_type)) {
915 DEBUG(0, ("tdbsam2_get_object_from_sid: error fetching object or wrong object type!\n"));
919 ret = data_to_gums_object(object, &obj);
920 if (NT_STATUS_IS_ERR(ret)) {
921 DEBUG(0, ("tdbsam2_get_object_from_sid: error setting object data!\n"));
926 talloc_destroy(mem_ctx);
930 static NTSTATUS tdbsam2_get_object_from_name(GUMS_OBJECT **object, const char *name, const int obj_type)
933 struct tdbsam2_object obj;
936 if (!object || !name) {
937 DEBUG(0, ("tdbsam2_get_object_from_sid: no NULL pointers are accepted here!\n"));
938 return NT_STATUS_INVALID_PARAMETER;
941 mem_ctx = talloc_init("tdbsam2_get_object_from_sid");
943 DEBUG(0, ("tdbsam2_get_object_from_sid: Out of memory!\n"));
944 return NT_STATUS_NO_MEMORY;
947 ret = get_object_by_name(mem_ctx, &obj, name);
948 if (NT_STATUS_IS_ERR(ret) || (obj_type && obj.type != obj_type)) {
949 DEBUG(0, ("tdbsam2_get_object_from_sid: error fetching object or wrong object type!\n"));
953 ret = data_to_gums_object(object, &obj);
954 if (NT_STATUS_IS_ERR(ret)) {
955 DEBUG(0, ("tdbsam2_get_object_from_sid: error setting object data!\n"));
960 talloc_destroy(mem_ctx);
964 /* This function is used to get the list of all objects changed since base_time, it is
965 used to support PDC<->BDC synchronization */
966 NTSTATUS (*get_updated_objects) (GUMS_OBJECT **objects, const NTTIME base_time);
968 static NTSTATUS tdbsam2_enumerate_objects_start(void *handle, const DOM_SID *sid, const int obj_type)
970 struct tdbsam2_enum_objs *teo, *t;
973 teo = (struct tdbsam2_enum_objs *)calloc(1, sizeof(struct tdbsam2_enum_objs));
975 DEBUG(0, ("tdbsam2_enumerate_objects_start: Out of Memory!\n"));
976 return NT_STATUS_NO_MEMORY;
979 teo->type = obj_type;
981 sid_to_string(teo->dom_sid, sid);
984 get_private_directory(tdbfile);
985 pstrcat(tdbfile, "/");
986 pstrcat(tdbfile, TDB_FILE_NAME);
988 teo->db = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600);
991 DEBUG(0, ("tdbsam2_enumerate_objects_start: Unable to open database (%s)!\n", tdbfile));
993 return NT_STATUS_UNSUCCESSFUL;
1008 teo->key = tdb_firstkey(teo->db);
1010 return NT_STATUS_OK;
1013 static NTSTATUS tdbsam2_enumerate_objects_get_next(GUMS_OBJECT **object, void *handle)
1016 TALLOC_CTX *mem_ctx;
1018 struct tdbsam2_enum_objs *teo;
1019 struct tdbsam2_object obj;
1020 const char *prefix = SIDPREFIX;
1021 const int preflen = strlen(prefix);
1023 if (!object || !handle) {
1024 DEBUG(0, ("tdbsam2_get_object_from_sid: no NULL pointers are accepted here!\n"));
1025 return NT_STATUS_INVALID_PARAMETER;
1028 teo = (struct tdbsam2_enum_objs *)handle;
1030 mem_ctx = talloc_init("tdbsam2_enumerate_objects_get_next");
1032 DEBUG(0, ("tdbsam2_enumerate_objects_get_next: Out of memory!\n"));
1033 return NT_STATUS_NO_MEMORY;
1036 while ((teo->key.dsize != 0)) {
1037 int len, version, type, size;
1040 if (strncmp(teo->key.dptr, prefix, preflen)) {
1041 teo->key = tdb_nextkey(teo->db, teo->key);
1046 if (strncmp(&(teo->key.dptr[preflen]), teo->dom_sid, strlen(teo->dom_sid))) {
1047 teo->key = tdb_nextkey(teo->db, teo->key);
1052 data = tdb_fetch(teo->db, teo->key);
1054 DEBUG(5, ("tdbsam2_enumerate_objects_get_next: Error fetching database, SID entry not found!\n"));
1055 DEBUGADD(5, (" Error: %s\n", tdb_errorstr(teo->db)));
1056 DEBUGADD(5, (" Key: %s\n", teo->key.dptr));
1057 ret = NT_STATUS_UNSUCCESSFUL;
1061 len = tdb_unpack (data.dptr, data.dsize, TDB_FORMAT_STRING,
1067 DEBUG(5, ("tdbsam2_enumerate_objects_get_next: Error unable to unpack data!\n"));
1068 ret = NT_STATUS_UNSUCCESSFUL;
1073 if (teo->type && type != teo->type) {
1074 SAFE_FREE(data.dptr);
1076 teo->key = tdb_nextkey(teo->db, teo->key);
1083 if (data.dsize != 0) {
1084 if (NT_STATUS_IS_ERR(init_tdbsam2_object_from_buffer(&obj, mem_ctx, data.dptr, data.dsize))) {
1085 SAFE_FREE(data.dptr);
1086 DEBUG(0, ("tdbsam2_enumerate_objects_get_next: Error fetching database, malformed entry!\n"));
1087 ret = NT_STATUS_UNSUCCESSFUL;
1090 SAFE_FREE(data.dptr);
1093 ret = data_to_gums_object(object, &obj);
1096 talloc_destroy(mem_ctx);
1100 static NTSTATUS tdbsam2_enumerate_objects_stop(void *handle)
1102 struct tdbsam2_enum_objs *teo, *t, *p;
1104 teo = (struct tdbsam2_enum_objs *)handle;
1106 if (*teo_handlers == teo) {
1107 *teo_handlers = teo->next;
1114 DEBUG(0, ("tdbsam2_enumerate_objects_stop: Error, handle not found!\n"));
1115 return NT_STATUS_UNSUCCESSFUL;
1124 return NT_STATUS_OK;
1127 /* This function MUST be used ONLY by PDC<->BDC replication code or recovery tools.
1128 Never use this function to update an object in the database, use set_object_values() */
1129 NTSTATUS (*set_object) (const GUMS_OBJECT *object);
1131 /* set object values function */
1132 NTSTATUS (*set_object_values) (DOM_SID *sid, uint32 count, GUMS_DATA_SET *data_set);
1134 /* Group related functions */
1135 NTSTATUS (*add_memberss_to_group) (const DOM_SID *group, const DOM_SID **members);
1136 NTSTATUS (*delete_members_from_group) (const DOM_SID *group, const DOM_SID **members);
1137 NTSTATUS (*enumerate_group_members) (DOM_SID **members, const DOM_SID *sid, const int type);
1139 NTSTATUS (*get_sid_groups) (DOM_SID **groups, const DOM_SID *sid);
1141 NTSTATUS (*lock_sid) (const DOM_SID *sid);
1142 NTSTATUS (*unlock_sid) (const DOM_SID *sid);
1144 /* privileges related functions */
1146 NTSTATUS (*add_members_to_privilege) (const LUID_ATTR *priv, const DOM_SID **members);
1147 NTSTATUS (*delete_members_from_privilege) (const LUID_ATTR *priv, const DOM_SID **members);
1148 NTSTATUS (*enumerate_privilege_members) (DOM_SID **members, const LUID_ATTR *priv);
1149 NTSTATUS (*get_sid_privileges) (DOM_SID **privs, const DOM_SID *sid);
1150 /* warning!: set_privilege will overwrite a prior existing privilege if such exist */
1151 NTSTATUS (*set_privilege) (GUMS_PRIVILEGE *priv);
1154 int gumm_init(GUMS_FUNCTIONS **storage)
1163 int main(int argc, char *argv[])
1169 printf ("not enough arguments!\n");
1173 if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
1174 fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
1178 ret = tdbsam2_new_object(&dsid, "_domain_", GUMS_OBJ_DOMAIN);
1179 if (NT_STATUS_IS_OK(ret)) {
1180 printf ("_domain_ created, sid=%s\n", sid_string_static(&dsid));
1182 printf ("_domain_ creation error n. 0x%08x\n", ret.v);
1184 ret = tdbsam2_new_object(&dsid, argv[1], GUMS_OBJ_NORMAL_USER);
1185 if (NT_STATUS_IS_OK(ret)) {
1186 printf ("%s user created, sid=%s\n", argv[1], sid_string_static(&dsid));
1188 printf ("%s user creation error n. 0x%08x\n", argv[1], ret.v);