Apply Craig Barratt's fixes to allow multiple exlusion files and patterns.
[Samba/gebeck_regimport.git] / source3 / passdb / pdb_gums.c
blobf34d3a94b5a704714f334b21034988f16a16e8d8
1 /*
2 * GUMS password backend for samba
3 * Copyright (C) Simo Sorce 2003-2004
4 *
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 675
17 * Mass Ave, Cambridge, MA 02139, USA.
20 #include "includes.h"
22 #define SET_OR_FAIL(func, label) do { if (!NT_STATUS_IS_OK(func)) { DEBUG(0, ("%s: Setting gums object data failed!\n", FUNCTION_MACRO)); goto label; } } while(0)
23 #define BOOL_SET_OR_FAIL(func, label) do { if (!func) { DEBUG(0, ("%s: Setting sam object data failed!\n", FUNCTION_MACRO)); goto label; } } while(0)
25 struct gums_gw_data {
26 GUMS_FUNCTIONS *fns;
27 void *handle;
30 static NTSTATUS gums_object_to_sam_account(SAM_ACCOUNT *sa, GUMS_OBJECT *go)
32 NTSTATUS ret;
33 NTTIME nt_time;
34 DATA_BLOB pwd;
36 if (!go || !sa)
37 return NT_STATUS_INVALID_PARAMETER;
39 if (!NT_STATUS_IS_OK(ret = pdb_init_sam(sa))) {
40 DEBUG(0, ("gums_object_to_sam_account: error occurred while creating sam_account object!\n"));
41 goto error;
44 if (gums_get_object_type(go) != GUMS_OBJ_NORMAL_USER)
45 return NT_STATUS_OBJECT_TYPE_MISMATCH;
47 BOOL_SET_OR_FAIL(pdb_set_acct_ctrl(sa, gums_get_user_acct_ctrl(go), PDB_SET), error);
49 /* domain */
50 /* unix_homedir ? */
52 nt_time = gums_get_user_logon_time(go);
53 BOOL_SET_OR_FAIL(pdb_set_logon_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error);
54 nt_time = gums_get_user_logoff_time(go);
55 BOOL_SET_OR_FAIL(pdb_set_logoff_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error);
56 nt_time = gums_get_user_kickoff_time(go);
57 BOOL_SET_OR_FAIL(pdb_set_kickoff_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error);
58 nt_time = gums_get_user_pass_last_set_time(go);
59 BOOL_SET_OR_FAIL(pdb_set_pass_last_set_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error);
60 nt_time = gums_get_user_pass_can_change_time(go);
61 BOOL_SET_OR_FAIL(pdb_set_pass_can_change_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error);
62 nt_time = gums_get_user_pass_must_change_time(go);
63 BOOL_SET_OR_FAIL(pdb_set_pass_must_change_time(sa, nt_time_to_unix(&nt_time), PDB_SET), error);
64 BOOL_SET_OR_FAIL(pdb_set_hours_len(sa, gums_get_user_hours_len(go), PDB_SET), error);
65 BOOL_SET_OR_FAIL(pdb_set_logon_divs(sa, gums_get_user_logon_divs(go), PDB_SET), error);
66 BOOL_SET_OR_FAIL(pdb_set_user_sid(sa, gums_get_object_sid(go), PDB_SET), error);
67 BOOL_SET_OR_FAIL(pdb_set_group_sid(sa, gums_get_user_pri_group(go), PDB_SET), error);
68 BOOL_SET_OR_FAIL(pdb_set_username(sa, gums_get_object_name(go), PDB_SET), error);
69 BOOL_SET_OR_FAIL(pdb_set_nt_username(sa, gums_get_object_name(go), PDB_SET), error);
70 BOOL_SET_OR_FAIL(pdb_set_fullname(sa, gums_get_user_fullname(go), PDB_SET), error);
71 BOOL_SET_OR_FAIL(pdb_set_logon_script(sa, gums_get_user_logon_script(go), PDB_SET), error);
72 BOOL_SET_OR_FAIL(pdb_set_profile_path(sa, gums_get_user_profile_path(go), PDB_SET), error);
73 BOOL_SET_OR_FAIL(pdb_set_dir_drive(sa, gums_get_user_dir_drive(go), PDB_SET), error);
74 BOOL_SET_OR_FAIL(pdb_set_homedir(sa, gums_get_user_homedir(go), PDB_SET), error);
75 BOOL_SET_OR_FAIL(pdb_set_acct_desc(sa, gums_get_object_description(go), PDB_SET), error);
76 BOOL_SET_OR_FAIL(pdb_set_workstations(sa, gums_get_user_workstations(go), PDB_SET), error);
77 BOOL_SET_OR_FAIL(pdb_set_unknown_str(sa, gums_get_user_unknown_str(go), PDB_SET), error);
78 BOOL_SET_OR_FAIL(pdb_set_munged_dial(sa, gums_get_user_munged_dial(go), PDB_SET), error);
80 pwd = gums_get_user_nt_pwd(go);
81 if (!pdb_set_nt_passwd(sa, pwd.data, PDB_SET)) {
82 DEBUG(5, ("gums_object_to_sam_account: unable to set nt password"));
83 data_blob_clear_free(&pwd);
84 ret = NT_STATUS_UNSUCCESSFUL;
85 goto error;
87 data_blob_clear_free(&pwd);
88 pwd = gums_get_user_lm_pwd(go);
89 if (!pdb_set_lanman_passwd(sa, pwd.data, PDB_SET)) {
90 DEBUG(5, ("gums_object_to_sam_account: unable to set lanman password"));
91 data_blob_clear_free(&pwd);
92 ret = NT_STATUS_UNSUCCESSFUL;
93 goto error;
95 data_blob_clear_free(&pwd);
97 BOOL_SET_OR_FAIL(pdb_set_bad_password_count(sa, gums_get_user_bad_password_count(go), PDB_SET), error);
98 BOOL_SET_OR_FAIL(pdb_set_unknown_6(sa, gums_get_user_unknown_6(go), PDB_SET), error);
99 BOOL_SET_OR_FAIL(pdb_set_hours(sa, gums_get_user_hours(go), PDB_SET), error);
101 return NT_STATUS_OK;
103 error:
104 if (sa && (sa->free_fn)) {
105 sa->free_fn(&sa);
108 return ret;
111 static NTSTATUS sam_account_to_gums_object(GUMS_OBJECT *go, SAM_ACCOUNT *sa)
113 NTSTATUS ret;
114 NTTIME nt_time;
115 DATA_BLOB pwd;
117 if (!go || !sa)
118 return NT_STATUS_INVALID_PARAMETER;
121 ret = gums_create_object(go, GUMS_OBJ_NORMAL_USER);
122 if (!NT_STATUS_IS_OK(ret)) {
123 DEBUG(0, ("sam_account_to_gums_object: error occurred while creating gums object!\n"));
124 goto error;
128 /* sec_desc */
130 SET_OR_FAIL(gums_set_object_name(go, pdb_get_username(sa)), error);
132 SET_OR_FAIL(gums_set_object_sid(go, pdb_get_user_sid(sa)), error);
133 SET_OR_FAIL(gums_set_user_pri_group(go, pdb_get_group_sid(sa)), error);
135 if (pdb_get_acct_desc(sa))
136 SET_OR_FAIL(gums_set_object_description(go, pdb_get_acct_desc(sa)), error);
137 if (pdb_get_fullname(sa))
138 SET_OR_FAIL(gums_set_user_fullname(go, pdb_get_fullname(sa)), error);
139 if (pdb_get_homedir(sa))
140 SET_OR_FAIL(gums_set_user_homedir(go, pdb_get_homedir(sa)), error);
141 if (pdb_get_dir_drive(sa))
142 SET_OR_FAIL(gums_set_user_dir_drive(go, pdb_get_dir_drive(sa)), error);
143 if (pdb_get_logon_script(sa))
144 SET_OR_FAIL(gums_set_user_logon_script(go, pdb_get_logon_script(sa)), error);
145 if (pdb_get_profile_path(sa))
146 SET_OR_FAIL(gums_set_user_profile_path(go, pdb_get_profile_path(sa)), error);
147 if (pdb_get_workstations(sa))
148 SET_OR_FAIL(gums_set_user_workstations(go, pdb_get_workstations(sa)), error);
149 if (pdb_get_unknown_str(sa))
150 SET_OR_FAIL(gums_set_user_unknown_str(go, pdb_get_unknown_str(sa)), error);
151 if (pdb_get_munged_dial(sa))
152 SET_OR_FAIL(gums_set_user_munged_dial(go, pdb_get_munged_dial(sa)), error);
153 SET_OR_FAIL(gums_set_user_logon_divs(go, pdb_get_logon_divs(sa)), error);
154 if (pdb_get_hours(sa))
155 SET_OR_FAIL(gums_set_user_hours(go, pdb_get_hours_len(sa), pdb_get_hours(sa)), error);
156 SET_OR_FAIL(gums_set_user_bad_password_count(go, pdb_get_bad_password_count(sa)), error);
157 SET_OR_FAIL(gums_set_user_unknown_6(go, pdb_get_unknown_6(sa)), error);
159 unix_to_nt_time(&nt_time, pdb_get_logon_time(sa));
160 SET_OR_FAIL(gums_set_user_logon_time(go, nt_time), error);
161 unix_to_nt_time(&nt_time, pdb_get_logoff_time(sa));
162 SET_OR_FAIL(gums_set_user_logoff_time(go, nt_time), error);
163 unix_to_nt_time(&nt_time, pdb_get_kickoff_time(sa));
164 SET_OR_FAIL(gums_set_user_kickoff_time(go, nt_time), error);
165 unix_to_nt_time(&nt_time, pdb_get_pass_last_set_time(sa));
166 SET_OR_FAIL(gums_set_user_pass_last_set_time(go, nt_time), error);
167 unix_to_nt_time(&nt_time, pdb_get_pass_can_change_time(sa));
168 SET_OR_FAIL(gums_set_user_pass_can_change_time(go, nt_time), error);
169 unix_to_nt_time(&nt_time, pdb_get_pass_must_change_time(sa));
170 SET_OR_FAIL(gums_set_user_pass_must_change_time(go, nt_time), error);
172 pwd = data_blob(pdb_get_nt_passwd(sa), NT_HASH_LEN);
173 ret = gums_set_user_nt_pwd(go, pwd);
174 data_blob_clear_free(&pwd);
175 if (!NT_STATUS_IS_OK(ret)) {
176 DEBUG(5, ("sam_account_to_gums_object: failed to set nt password!\n"));
177 goto error;
179 pwd = data_blob(pdb_get_lanman_passwd(sa), LM_HASH_LEN);
180 ret = gums_set_user_lm_pwd(go, pwd);
181 data_blob_clear_free(&pwd);
182 if (!NT_STATUS_IS_OK(ret)) {
183 DEBUG(5, ("sam_account_to_gums_object: failed to set lanman password!\n"));
184 goto error;
187 SET_OR_FAIL(gums_set_user_acct_ctrl(go, pdb_get_acct_ctrl(sa)), error);
189 return NT_STATUS_OK;
191 error:
192 gums_reset_object(go);
193 return ret;
196 static NTSTATUS gums_setsampwent(struct pdb_methods *methods, BOOL update)
198 struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data);
200 return ggwd->fns->enumerate_objects_start(&(ggwd->handle), NULL, GUMS_OBJ_NORMAL_USER);
203 static NTSTATUS gums_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT *account)
205 NTSTATUS ret;
206 GUMS_OBJECT *go;
207 struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data);
209 if (!NT_STATUS_IS_OK(ret = ggwd->fns->enumerate_objects_get_next(&go, ggwd->handle))) {
210 return ret;
213 ret = gums_object_to_sam_account(account, go);
215 gums_destroy_object(&go);
216 return ret;
219 static void gums_endsampwent(struct pdb_methods *methods)
221 struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data);
223 ggwd->fns->enumerate_objects_stop(ggwd->handle);
226 /******************************************************************
227 Lookup a name in the SAM database
228 ******************************************************************/
230 static NTSTATUS gums_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *account, const char *name)
232 NTSTATUS ret;
233 GUMS_OBJECT *go;
234 struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data);
236 if (!account || !name)
237 return NT_STATUS_INVALID_PARAMETER;
239 if (!NT_STATUS_IS_OK(ret = ggwd->fns->get_object_from_name(&go, global_myname(), name, GUMS_OBJ_NORMAL_USER))) {
240 DEBUG(10, ("gums_getsampwnam: unable to find account with name %s", name));
241 return ret;
244 ret = gums_object_to_sam_account(account, go);
246 gums_destroy_object(&go);
247 return ret;
250 /***************************************************************************
251 Search by SID
252 **************************************************************************/
254 static NTSTATUS gums_getsampwsid(struct pdb_methods *methods, SAM_ACCOUNT *account, const DOM_SID *sid)
256 NTSTATUS ret;
257 GUMS_OBJECT *go;
258 struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data);
260 if (!account || !sid)
261 return NT_STATUS_INVALID_PARAMETER;
263 if (!NT_STATUS_IS_OK(ret = ggwd->fns->get_object_from_sid(&go, sid, GUMS_OBJ_NORMAL_USER))) {
264 DEBUG(10, ("gums_getsampwsid: unable to find account with sid %s", sid_string_static(sid)));
265 return ret;
268 ret = gums_object_to_sam_account(account, go);
270 gums_destroy_object(&go);
271 return ret;
274 /***************************************************************************
275 Search by rid
276 **************************************************************************/
278 #if 0
280 static NTSTATUS gums_getsampwrid (struct pdb_methods *methods,
281 SAM_ACCOUNT *account, uint32 rid)
283 DOM_SID sid;
285 sid_copy(&sid, get_global_sam_sid());
286 sid_append_rid(&sid, rid);
287 gums_getsampwsid(methods, account, &sid);
289 return NT_STATUS_OK;
292 #endif
294 /***************************************************************************
295 Updates a SAM_ACCOUNT
297 This isn't a particulary practical option for pdb_guest. We certainly don't
298 want to twidde the filesystem, so what should we do?
300 Current plan is to transparently add the account. It should appear
301 as if the pdb_guest version was modified, but its actually stored somehwere.
302 ****************************************************************************/
304 static NTSTATUS gums_add_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *account)
306 NTSTATUS ret;
307 GUMS_OBJECT *go;
308 struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data);
310 if (!account)
311 return NT_STATUS_INVALID_PARAMETER;
313 if (!NT_STATUS_IS_OK(ret = gums_create_object(&go, GUMS_OBJ_NORMAL_USER))) {
314 DEBUG(0, ("gums_add_sam_account: error occurred while creating gums object!\n"));
315 return ret;
318 if (!NT_STATUS_IS_OK(ret = sam_account_to_gums_object(go, account))) {
319 DEBUG(0, ("gums_add_sam_account: error occurred while converting object!\n"));
320 goto done;
323 if (!NT_STATUS_IS_OK(ret = ggwd->fns->set_object(go))) {
324 DEBUG(0, ("gums_add_sam_account: unable to store account!\n"));
325 goto done;
328 done:
329 gums_destroy_object(&go);
330 return ret;
333 static NTSTATUS gums_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *account)
335 NTSTATUS ret;
336 GUMS_OBJECT *go;
337 struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data);
339 if (!account)
340 return NT_STATUS_INVALID_PARAMETER;
342 if (!NT_STATUS_IS_OK(ret = ggwd->fns->get_object_from_sid(&go, pdb_get_user_sid(account), GUMS_OBJ_NORMAL_USER))) {
343 DEBUG(0, ("gums_update_sam_account: update on invalid account!\n"));
344 return ret;
347 if (!NT_STATUS_IS_OK(ret = sam_account_to_gums_object(go, account))) {
348 DEBUG(0, ("gums_update_sam_account: error occurred while converting object!\n"));
349 goto done;
352 if (!NT_STATUS_IS_OK(ret = ggwd->fns->set_object(go))) {
353 DEBUG(0, ("gums_update_sam_account: unable to store account!\n"));
354 goto done;
357 done:
358 gums_destroy_object(&go);
359 return ret;
362 static NTSTATUS gums_delete_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *account)
364 NTSTATUS ret;
365 struct gums_gw_data *ggwd = (struct gums_gw_data *)(methods->private_data);
367 if (!account)
368 return NT_STATUS_INVALID_PARAMETER;
370 if (!NT_STATUS_IS_OK(ret = ggwd->fns->delete_object(pdb_get_user_sid(account)))) {
371 DEBUG(0, ("gums_add_sam_account: unable to store account!\n"));
374 return ret;
378 static void free_gw_private_data(void **vp)
380 struct gums_gw_data *ggwd = (struct gums_gw_data *)vp;
381 ggwd->fns->free_private_data(&(ggwd->fns->private_data));
382 ggwd->fns = NULL;
383 ggwd->handle = NULL;
384 SAFE_FREE(vp);
387 NTSTATUS pdb_init_gums_gateway(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
389 NTSTATUS ret;
390 struct gums_gw_data *ggwd;
392 if (!pdb_context) {
393 DEBUG(0, ("invalid pdb_context specified\n"));
394 return NT_STATUS_UNSUCCESSFUL;
397 if (!NT_STATUS_IS_OK(ret = gums_setup_backend(lp_gums_backend()))) {
398 DEBUG(0, ("pdb_init_gums_gateway: initialization error!\n"));
399 return ret;
402 ggwd = (struct gums_gw_data *)malloc(sizeof(struct gums_gw_data));
403 if (!ggwd)
404 return NT_STATUS_NO_MEMORY;
405 memset(ggwd, 0, sizeof(struct gums_gw_data));
407 if (!NT_STATUS_IS_OK(ret = get_gums_fns(&(ggwd->fns)))) {
408 goto error;
411 if (!NT_STATUS_IS_OK(ret = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
412 goto error;
415 (*pdb_method)->name = "gums_gateway";
417 (*pdb_method)->setsampwent = gums_setsampwent;
418 (*pdb_method)->getsampwent = gums_getsampwent;
419 (*pdb_method)->endsampwent = gums_endsampwent;
420 (*pdb_method)->getsampwnam = gums_getsampwnam;
421 (*pdb_method)->getsampwsid = gums_getsampwsid;
422 (*pdb_method)->add_sam_account = gums_add_sam_account;
423 (*pdb_method)->update_sam_account = gums_update_sam_account;
424 (*pdb_method)->delete_sam_account = gums_delete_sam_account;
426 /* we should do no group mapping here */
427 /* (*pdb_method)->getgrsid = gums_getgrsid;
428 (*pdb_method)->getgrgid = gums_getgrgid;
429 (*pdb_method)->getgrnam = gums_getgrnam;
430 (*pdb_method)->add_group_mapping_entry = gums_add_group_mapping_entry;
431 (*pdb_method)->update_group_mapping_entry = gums_update_group_mapping_entry;
432 (*pdb_method)->delete_group_mapping_entry = gums_delete_group_mapping_entry;
433 (*pdb_method)->enum_group_mapping = gums_enum_group_mapping;*/
435 /* we do not handle groups in guest backend */
436 /* FIXME
437 (*pdb_method)->get_group_info_by_sid = gums_get_group_info_by_sid;
438 (*pdb_method)->get_group_list = gums_get_group_list;
439 (*pdb_method)->get_group_sids = gums_get_group_sids;
440 (*pdb_method)->add_group = gums_add_group;
441 (*pdb_method)->update_group = gums_update_group;
442 (*pdb_method)->delete_group = gums_delete_group;
443 (*pdb_method)->add_sid_to_group = gums_add_sid_to_group;
444 (*pdb_method)->remove_sid_from_group = gums_remove_sid_from_group;
445 (*pdb_method)->get_group_info_by_name = gums_get_group_info_by_name;
446 (*pdb_method)->get_group_info_by_nt_name = gums_get_group_info_by_nt_name;
447 (*pdb_method)->get_group_uids = gums_get_group_uids;
450 (*pdb_method)->private_data = ggwd;
451 (*pdb_method)->free_private_data = free_gw_private_data;
453 return NT_STATUS_OK;
455 error:
456 SAFE_FREE(ggwd);
457 return ret;
460 NTSTATUS pdb_gums_init(void)
462 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "gums", pdb_init_gums_gateway);