2 * MySQL password backend for samba
3 * Copyright (C) Jelmer Vernooij 2002
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)
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
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.
21 #include <mysql/mysql.h>
23 #define CONFIG_TABLE_DEFAULT "user"
24 #define CONFIG_LOGON_TIME_DEFAULT "logon_time"
25 #define CONFIG_LOGOFF_TIME_DEFAULT "logoff_time"
26 #define CONFIG_KICKOFF_TIME_DEFAULT "kickoff_time"
27 #define CONFIG_PASS_LAST_SET_TIME_DEFAULT "pass_last_set_time"
28 #define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT "pass_can_change_time"
29 #define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT "pass_must_change_time"
30 #define CONFIG_USERNAME_DEFAULT "username"
31 #define CONFIG_DOMAIN_DEFAULT "domain"
32 #define CONFIG_NT_USERNAME_DEFAULT "nt_username"
33 #define CONFIG_FULLNAME_DEFAULT "nt_fullname"
34 #define CONFIG_HOME_DIR_DEFAULT "home_dir"
35 #define CONFIG_DIR_DRIVE_DEFAULT "dir_drive"
36 #define CONFIG_LOGON_SCRIPT_DEFAULT "logon_script"
37 #define CONFIG_PROFILE_PATH_DEFAULT "profile_path"
38 #define CONFIG_ACCT_DESC_DEFAULT "acct_desc"
39 #define CONFIG_WORKSTATIONS_DEFAULT "workstations"
40 #define CONFIG_UNKNOWN_STR_DEFAULT "unknown_str"
41 #define CONFIG_MUNGED_DIAL_DEFAULT "munged_dial"
42 #define CONFIG_UID_DEFAULT "uid"
43 #define CONFIG_GID_DEFAULT "gid"
44 #define CONFIG_USER_SID_DEFAULT "user_sid"
45 #define CONFIG_GROUP_SID_DEFAULT "group_sid"
46 #define CONFIG_LM_PW_DEFAULT "lm_pw"
47 #define CONFIG_NT_PW_DEFAULT "nt_pw"
48 #define CONFIG_PLAIN_PW_DEFAULT "NULL"
49 #define CONFIG_ACCT_CTRL_DEFAULT "acct_ctrl"
50 #define CONFIG_UNKNOWN_3_DEFAULT "unknown_3"
51 #define CONFIG_LOGON_DIVS_DEFAULT "logon_divs"
52 #define CONFIG_HOURS_LEN_DEFAULT "hours_len"
53 #define CONFIG_UNKNOWN_5_DEFAULT "unknown_5"
54 #define CONFIG_UNKNOWN_6_DEFAULT "unknown_6"
55 #define CONFIG_HOST_DEFAULT "localhost"
56 #define CONFIG_USER_DEFAULT "samba"
57 #define CONFIG_PASS_DEFAULT ""
58 #define CONFIG_PORT_DEFAULT "3306"
59 #define CONFIG_DB_DEFAULT "samba"
61 static int mysqlsam_debug_level = DBGC_ALL;
64 #define DBGC_CLASS mysqlsam_debug_level
66 PDB_MODULE_VERSIONING_MAGIC
68 typedef struct pdb_mysql_data {
74 /* Used to construct insert and update queries */
76 typedef struct pdb_mysql_query {
82 #define SET_DATA(data,methods) { \
84 DEBUG(0, ("invalid methods!\n")); \
85 return NT_STATUS_INVALID_PARAMETER; \
87 data = (struct pdb_mysql_data *)methods->private_data; \
88 if(!data || !(data->handle)){ \
89 DEBUG(0, ("invalid handle!\n")); \
90 return NT_STATUS_INVALID_HANDLE; \
94 static void pdb_mysql_int_field(struct pdb_methods *m,
95 struct pdb_mysql_query *q, char *name, int value)
97 if (!name || strchr(name, '\''))
98 return; /* This field shouldn't be set by us */
102 talloc_asprintf_append(q->mem_ctx, q->part1,
103 "%s = %d,", name, value);
106 talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name);
108 talloc_asprintf_append(q->mem_ctx, q->part2, "%d,", value);
112 static NTSTATUS pdb_mysql_string_field(struct pdb_methods *methods,
113 struct pdb_mysql_query *q,
114 char *name, const char *value)
117 struct pdb_mysql_data *data;
120 SET_DATA(data, methods);
122 if (!name || !value || !strcmp(value, "") || strchr(name, '\''))
123 return NT_STATUS_INVALID_PARAMETER; /* This field shouldn't be set by module */
125 esc_value = malloc(strlen(value) * 2 + 1);
127 tmp_value = smb_xstrdup(value);
128 mysql_real_escape_string(data->handle, esc_value, tmp_value,
130 SAFE_FREE(tmp_value);
134 talloc_asprintf_append(q->mem_ctx, q->part1,
135 "%s = '%s',", name, esc_value);
138 talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name);
140 talloc_asprintf_append(q->mem_ctx, q->part2, "'%s',",
144 SAFE_FREE(esc_value);
149 static char * config_value(pdb_mysql_data * data, char *name, char *default_value)
151 if (lp_parm_string(NULL, data->location, name))
152 return lp_parm_string(NULL, data->location, name);
154 return default_value;
157 static char * config_value_write(pdb_mysql_data * data, char *name, char *default_value) {
158 char *v = config_value(data, name, NULL);
162 return default_value;
164 swrite = strchr(v, ':');
166 /* Default to the same field as read field */
172 /* If the field is 0 chars long, we shouldn't write to it */
173 if (!strlen(swrite) || !strcmp(swrite, "NULL"))
176 /* Otherwise, use the additionally specified */
180 static const char * config_value_read(pdb_mysql_data * data, char *name, char *default_value)
182 char *v = config_value(data, name, NULL);
186 return default_value;
188 swrite = strchr(v, ':');
190 /* If no write is specified, there are no problems */
197 /* Otherwise, we have to cut the ':write_part' */
205 /* Wrapper for atol that returns 0 if 'a' points to NULL */
206 static long xatol(char *a)
216 static NTSTATUS row_to_sam_account(MYSQL_RES * r, SAM_ACCOUNT * u)
220 unsigned int num_fields;
223 num_fields = mysql_num_fields(r);
224 row = mysql_fetch_row(r);
226 return NT_STATUS_INVALID_PARAMETER;
228 pdb_set_logon_time(u, xatol(row[0]), PDB_SET);
229 pdb_set_logoff_time(u, xatol(row[1]), PDB_SET);
230 pdb_set_kickoff_time(u, xatol(row[2]), PDB_SET);
231 pdb_set_pass_last_set_time(u, xatol(row[3]), PDB_SET);
232 pdb_set_pass_can_change_time(u, xatol(row[4]), PDB_SET);
233 pdb_set_pass_must_change_time(u, xatol(row[5]), PDB_SET);
234 pdb_set_username(u, row[6], PDB_SET);
235 pdb_set_domain(u, row[7], PDB_SET);
236 pdb_set_nt_username(u, row[8], PDB_SET);
237 pdb_set_fullname(u, row[9], PDB_SET);
238 pdb_set_homedir(u, row[10], PDB_SET);
239 pdb_set_dir_drive(u, row[11], PDB_SET);
240 pdb_set_logon_script(u, row[12], PDB_SET);
241 pdb_set_profile_path(u, row[13], PDB_SET);
242 pdb_set_acct_desc(u, row[14], PDB_SET);
243 pdb_set_workstations(u, row[15], PDB_SET);
244 pdb_set_unknown_str(u, row[16], PDB_SET);
245 pdb_set_munged_dial(u, row[17], PDB_SET);
248 pdb_set_uid(u, xatol(row[18]), PDB_SET);
250 pdb_set_gid(u, xatol(row[19]), PDB_SET);
252 string_to_sid(&sid, row[20]);
253 pdb_set_user_sid(u, &sid, PDB_SET);
254 string_to_sid(&sid, row[21]);
255 pdb_set_group_sid(u, &sid, PDB_SET);
257 if (pdb_gethexpwd(row[22], temp), PDB_SET)
258 pdb_set_lanman_passwd(u, temp, PDB_SET);
259 if (pdb_gethexpwd(row[23], temp), PDB_SET)
260 pdb_set_nt_passwd(u, temp, PDB_SET);
262 /* Only use plaintext password storage when lanman and nt are
264 if (!row[22] || !row[23])
265 pdb_set_plaintext_passwd(u, row[24]);
267 pdb_set_acct_ctrl(u, xatol(row[25]), PDB_SET);
268 pdb_set_unknown_3(u, xatol(row[26]), PDB_SET);
269 pdb_set_logon_divs(u, xatol(row[27]), PDB_SET);
270 pdb_set_hours_len(u, xatol(row[28]), PDB_SET);
271 pdb_set_unknown_5(u, xatol(row[29]), PDB_SET);
272 pdb_set_unknown_6(u, xatol(row[30]), PDB_SET);
277 static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update)
279 struct pdb_mysql_data *data =
280 (struct pdb_mysql_data *) methods->private_data;
284 if (!data || !(data->handle)) {
285 DEBUG(0, ("invalid handle!\n"));
286 return NT_STATUS_INVALID_HANDLE;
290 "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s",
291 config_value_read(data, "logon time column",
292 CONFIG_LOGON_TIME_DEFAULT),
293 config_value_read(data, "logoff time column",
294 CONFIG_LOGOFF_TIME_DEFAULT),
295 config_value_read(data, "kickoff time column",
296 CONFIG_KICKOFF_TIME_DEFAULT),
297 config_value_read(data, "pass last set time column",
298 CONFIG_PASS_LAST_SET_TIME_DEFAULT),
299 config_value_read(data, "pass can change time column",
300 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
301 config_value_read(data, "pass must change time column",
302 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
303 config_value_read(data, "username column",
304 CONFIG_USERNAME_DEFAULT),
305 config_value_read(data, "domain column",
306 CONFIG_DOMAIN_DEFAULT),
307 config_value_read(data, "nt username column",
308 CONFIG_NT_USERNAME_DEFAULT),
309 config_value_read(data, "fullname column",
310 CONFIG_FULLNAME_DEFAULT),
311 config_value_read(data, "home dir column",
312 CONFIG_HOME_DIR_DEFAULT),
313 config_value_read(data, "dir drive column",
314 CONFIG_DIR_DRIVE_DEFAULT),
315 config_value_read(data, "logon script column",
316 CONFIG_LOGON_SCRIPT_DEFAULT),
317 config_value_read(data, "profile path column",
318 CONFIG_PROFILE_PATH_DEFAULT),
319 config_value_read(data, "acct desc column",
320 CONFIG_ACCT_DESC_DEFAULT),
321 config_value_read(data, "workstations column",
322 CONFIG_WORKSTATIONS_DEFAULT),
323 config_value_read(data, "unknown string column",
324 CONFIG_UNKNOWN_STR_DEFAULT),
325 config_value_read(data, "munged dial column",
326 CONFIG_MUNGED_DIAL_DEFAULT),
327 config_value_read(data, "uid column", CONFIG_UID_DEFAULT),
328 config_value_read(data, "gid column", CONFIG_GID_DEFAULT),
329 config_value_read(data, "user sid column",
330 CONFIG_USER_SID_DEFAULT),
331 config_value_read(data, "group sid column",
332 CONFIG_GROUP_SID_DEFAULT),
333 config_value_read(data, "lanman pass column",
334 CONFIG_LM_PW_DEFAULT),
335 config_value_read(data, "nt pass column",
336 CONFIG_NT_PW_DEFAULT),
337 config_value_read(data, "plain pass column",
338 CONFIG_PLAIN_PW_DEFAULT),
339 config_value_read(data, "acct ctrl column",
340 CONFIG_ACCT_CTRL_DEFAULT),
341 config_value_read(data, "unknown 3 column",
342 CONFIG_UNKNOWN_3_DEFAULT),
343 config_value_read(data, "logon divs column",
344 CONFIG_LOGON_DIVS_DEFAULT),
345 config_value_read(data, "hours len column",
346 CONFIG_HOURS_LEN_DEFAULT),
347 config_value_read(data, "unknown 5 column",
348 CONFIG_UNKNOWN_5_DEFAULT),
349 config_value_read(data, "unknown 6 column",
350 CONFIG_UNKNOWN_6_DEFAULT),
351 config_value(data, "table", CONFIG_TABLE_DEFAULT)
353 DEBUG(5, ("Executing query %s\n", query));
355 ret = mysql_query(data->handle, query);
360 ("Error executing MySQL query %s\n", mysql_error(data->handle)));
361 return NT_STATUS_UNSUCCESSFUL;
364 data->pwent = mysql_store_result(data->handle);
366 if (data->pwent == NULL) {
368 ("Error storing results: %s\n", mysql_error(data->handle)));
369 return NT_STATUS_UNSUCCESSFUL;
373 ("mysqlsam_setsampwent succeeded(%lu results)!\n",
374 mysql_num_rows(data->pwent)));
379 /***************************************************************
380 End enumeration of the passwd list.
381 ****************************************************************/
383 static void mysqlsam_endsampwent(struct pdb_methods *methods)
385 struct pdb_mysql_data *data =
386 (struct pdb_mysql_data *) methods->private_data;
389 DEBUG(0, ("invalid handle!\n"));
393 if (data->pwent != NULL)
394 mysql_free_result(data->pwent);
398 DEBUG(5, ("mysql_endsampwent called\n"));
401 /*****************************************************************
402 Get one SAM_ACCOUNT from the list (next in line)
403 *****************************************************************/
405 static NTSTATUS mysqlsam_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT * user)
407 struct pdb_mysql_data *data;
409 SET_DATA(data, methods);
411 if (data->pwent == NULL) {
412 DEBUG(0, ("invalid pwent\n"));
413 return NT_STATUS_INVALID_PARAMETER;
416 return row_to_sam_account(data->pwent, user);
419 static NTSTATUS mysqlsam_select_by_field(struct pdb_methods * methods, SAM_ACCOUNT * user,
420 const char *field, const char *sname)
427 struct pdb_mysql_data *data;
430 SET_DATA(data, methods);
432 esc_sname = malloc(strlen(sname) * 2 + 1);
434 return NT_STATUS_NO_MEMORY;
438 ("mysqlsam_select_by_field: getting data where %s = %s(nonescaped)\n",
441 tmp_sname = smb_xstrdup(sname);
444 mysql_real_escape_string(data->handle, esc_sname, tmp_sname,
447 SAFE_FREE(tmp_sname);
450 DEBUG(0, ("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
451 SAFE_FREE(esc_sname);
452 return NT_STATUS_INVALID_PARAMETER;
456 "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s WHERE %s = '%s'",
457 config_value_read(data, "logon time column",
458 CONFIG_LOGON_TIME_DEFAULT),
459 config_value_read(data, "logoff time column",
460 CONFIG_LOGOFF_TIME_DEFAULT),
461 config_value_read(data, "kickoff time column",
462 CONFIG_KICKOFF_TIME_DEFAULT),
463 config_value_read(data, "pass last set time column",
464 CONFIG_PASS_LAST_SET_TIME_DEFAULT),
465 config_value_read(data, "pass can change time column",
466 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
467 config_value_read(data, "pass must change time column",
468 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
469 config_value_read(data, "username column",
470 CONFIG_USERNAME_DEFAULT),
471 config_value_read(data, "domain column",
472 CONFIG_DOMAIN_DEFAULT),
473 config_value_read(data, "nt username column",
474 CONFIG_NT_USERNAME_DEFAULT),
475 config_value_read(data, "fullname column",
476 CONFIG_FULLNAME_DEFAULT),
477 config_value_read(data, "home dir column",
478 CONFIG_HOME_DIR_DEFAULT),
479 config_value_read(data, "dir drive column",
480 CONFIG_DIR_DRIVE_DEFAULT),
481 config_value_read(data, "logon script column",
482 CONFIG_LOGON_SCRIPT_DEFAULT),
483 config_value_read(data, "profile path column",
484 CONFIG_PROFILE_PATH_DEFAULT),
485 config_value_read(data, "acct desc column",
486 CONFIG_ACCT_DESC_DEFAULT),
487 config_value_read(data, "workstations column",
488 CONFIG_WORKSTATIONS_DEFAULT),
489 config_value_read(data, "unknown string column",
490 CONFIG_UNKNOWN_STR_DEFAULT),
491 config_value_read(data, "munged dial column",
492 CONFIG_MUNGED_DIAL_DEFAULT),
493 config_value_read(data, "uid column", CONFIG_UID_DEFAULT),
494 config_value_read(data, "gid column", CONFIG_GID_DEFAULT),
495 config_value_read(data, "user sid column",
496 CONFIG_USER_SID_DEFAULT),
497 config_value_read(data, "group sid column",
498 CONFIG_GROUP_SID_DEFAULT),
499 config_value_read(data, "lanman pass column",
500 CONFIG_LM_PW_DEFAULT),
501 config_value_read(data, "nt pass column",
502 CONFIG_NT_PW_DEFAULT),
503 config_value_read(data, "plain pass column",
504 CONFIG_PLAIN_PW_DEFAULT),
505 config_value_read(data, "acct ctrl column",
506 CONFIG_ACCT_CTRL_DEFAULT),
507 config_value_read(data, "unknown 3 column",
508 CONFIG_UNKNOWN_3_DEFAULT),
509 config_value_read(data, "logon divs column",
510 CONFIG_LOGON_DIVS_DEFAULT),
511 config_value_read(data, "hours len column",
512 CONFIG_HOURS_LEN_DEFAULT),
513 config_value_read(data, "unknown 5 column",
514 CONFIG_UNKNOWN_5_DEFAULT),
515 config_value_read(data, "unknown 6 column",
516 CONFIG_UNKNOWN_6_DEFAULT),
517 config_value(data, "table", CONFIG_TABLE_DEFAULT), field,
520 SAFE_FREE(esc_sname);
522 DEBUG(5, ("Executing query %s\n", query));
524 mysql_ret = mysql_query(data->handle, query);
530 ("Error while executing MySQL query %s\n",
531 mysql_error(data->handle)));
532 return NT_STATUS_UNSUCCESSFUL;
535 res = mysql_store_result(data->handle);
538 ("Error storing results: %s\n", mysql_error(data->handle)));
539 return NT_STATUS_UNSUCCESSFUL;
542 ret = row_to_sam_account(res, user);
543 mysql_free_result(res);
548 /******************************************************************
549 Lookup a name in the SAM database
550 ******************************************************************/
552 static NTSTATUS mysqlsam_getsampwnam(struct pdb_methods *methods, SAM_ACCOUNT * user,
555 struct pdb_mysql_data *data;
557 SET_DATA(data, methods);
560 DEBUG(0, ("invalid name specified"));
561 return NT_STATUS_INVALID_PARAMETER;
564 return mysqlsam_select_by_field(methods, user,
565 config_value_read(data, "username column",
566 CONFIG_USERNAME_DEFAULT), sname);
570 /***************************************************************************
572 **************************************************************************/
574 static NTSTATUS mysqlsam_getsampwsid(struct pdb_methods *methods, SAM_ACCOUNT * user,
577 struct pdb_mysql_data *data;
580 SET_DATA(data, methods);
582 sid_to_string(sid_str, sid);
584 return mysqlsam_select_by_field(methods, user,
585 config_value_read(data, "user sid column",
586 CONFIG_USER_SID_DEFAULT), sid_str);
589 /***************************************************************************
591 ****************************************************************************/
593 static NTSTATUS mysqlsam_delete_sam_account(struct pdb_methods *methods,
594 SAM_ACCOUNT * sam_pass)
596 const char *sname = pdb_get_username(sam_pass);
600 struct pdb_mysql_data *data;
603 SET_DATA(data, methods);
606 DEBUG(0, ("invalid methods!\n"));
607 return NT_STATUS_INVALID_PARAMETER;
610 data = (struct pdb_mysql_data *) methods->private_data;
611 if (!data || !(data->handle)) {
612 DEBUG(0, ("invalid handle!\n"));
613 return NT_STATUS_INVALID_HANDLE;
617 DEBUG(0, ("invalid name specified\n"));
618 return NT_STATUS_INVALID_PARAMETER;
622 esc = malloc(strlen(sname) * 2 + 1);
624 DEBUG(0, ("Can't allocate memory to store escaped name\n"));
625 return NT_STATUS_NO_MEMORY;
628 tmp_sname = smb_xstrdup(sname);
630 mysql_real_escape_string(data->handle, esc, tmp_sname,
633 SAFE_FREE(tmp_sname);
635 asprintf(&query, "DELETE FROM %s WHERE %s = '%s'",
636 config_value(data, "table", CONFIG_TABLE_DEFAULT),
637 config_value_read(data, "username column",
638 CONFIG_USERNAME_DEFAULT), esc);
642 ret = mysql_query(data->handle, query);
648 ("Error while executing query: %s\n",
649 mysql_error(data->handle)));
650 return NT_STATUS_UNSUCCESSFUL;
653 DEBUG(5, ("User '%s' deleted\n", sname));
657 static NTSTATUS mysqlsam_replace_sam_account(struct pdb_methods *methods,
658 const SAM_ACCOUNT * newpwd, char isupdate)
661 struct pdb_mysql_data *data;
662 pdb_mysql_query query;
666 DEBUG(0, ("invalid methods!\n"));
667 return NT_STATUS_INVALID_PARAMETER;
670 data = (struct pdb_mysql_data *) methods->private_data;
671 if (data == NULL || data->handle == NULL) {
672 DEBUG(0, ("invalid handle!\n"));
673 return NT_STATUS_INVALID_HANDLE;
675 query.update = isupdate;
677 /* I know this is somewhat overkill but only the talloc
678 * functions have asprint_append and the 'normal' asprintf
679 * is a GNU extension */
680 query.mem_ctx = talloc_init("mysqlsam_replace_sam_account");
681 query.part2 = talloc_asprintf(query.mem_ctx, "%s", "");
684 talloc_asprintf(query.mem_ctx, "UPDATE %s SET ",
685 config_value(data, "table",
686 CONFIG_TABLE_DEFAULT));
689 talloc_asprintf(query.mem_ctx, "INSERT INTO %s (",
690 config_value(data, "table",
691 CONFIG_TABLE_DEFAULT));
694 pdb_mysql_int_field(methods, &query,
695 config_value_write(data, "acct ctrl column",
696 CONFIG_ACCT_CTRL_DEFAULT),
697 pdb_get_acct_ctrl(newpwd));
699 if (pdb_get_init_flags(newpwd, PDB_LOGONTIME) != PDB_DEFAULT) {
700 pdb_mysql_int_field(methods, &query,
701 config_value_write(data,
703 CONFIG_LOGON_TIME_DEFAULT),
704 pdb_get_logon_time(newpwd));
707 if (pdb_get_init_flags(newpwd, PDB_LOGOFFTIME) != PDB_DEFAULT) {
708 pdb_mysql_int_field(methods, &query,
709 config_value_write(data,
710 "logoff time column",
711 CONFIG_LOGOFF_TIME_DEFAULT),
712 pdb_get_logoff_time(newpwd));
715 if (pdb_get_init_flags(newpwd, PDB_KICKOFFTIME) != PDB_DEFAULT) {
716 pdb_mysql_int_field(methods, &query,
717 config_value_write(data,
718 "kickoff time column",
719 CONFIG_KICKOFF_TIME_DEFAULT),
720 pdb_get_kickoff_time(newpwd));
723 if (pdb_get_init_flags(newpwd, PDB_CANCHANGETIME) != PDB_DEFAULT) {
724 pdb_mysql_int_field(methods, &query,
725 config_value_write(data,
726 "pass can change time column",
727 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
728 pdb_get_pass_can_change_time(newpwd));
731 if (pdb_get_init_flags(newpwd, PDB_MUSTCHANGETIME) != PDB_DEFAULT) {
732 pdb_mysql_int_field(methods, &query,
733 config_value_write(data,
734 "pass must change time column",
735 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
736 pdb_get_pass_must_change_time(newpwd));
739 if (pdb_get_pass_last_set_time(newpwd)) {
740 pdb_mysql_int_field(methods, &query,
741 config_value_write(data,
742 "pass last set time column",
743 CONFIG_PASS_LAST_SET_TIME_DEFAULT),
744 pdb_get_pass_last_set_time(newpwd));
747 if (pdb_get_hours_len(newpwd)) {
748 pdb_mysql_int_field(methods, &query,
749 config_value_write(data,
751 CONFIG_HOURS_LEN_DEFAULT),
752 pdb_get_hours_len(newpwd));
755 if (pdb_get_logon_divs(newpwd)) {
756 pdb_mysql_int_field(methods, &query,
757 config_value_write(data,
759 CONFIG_LOGON_DIVS_DEFAULT),
760 pdb_get_logon_divs(newpwd));
763 if (pdb_get_init_flags(newpwd, PDB_UID) != PDB_DEFAULT) {
764 pdb_mysql_int_field(methods, &query,
765 config_value_write(data, "uid column",
767 pdb_get_uid(newpwd));
770 if (pdb_get_init_flags(newpwd, PDB_GID) != PDB_DEFAULT) {
771 pdb_mysql_int_field(methods, &query,
772 config_value_write(data, "gid column",
774 pdb_get_gid(newpwd));
777 pdb_mysql_string_field(methods, &query,
778 config_value_write(data, "user sid column",
779 CONFIG_USER_SID_DEFAULT),
780 sid_to_string(sid_str,
781 pdb_get_user_sid(newpwd)));
783 pdb_mysql_string_field(methods, &query,
784 config_value_write(data, "group sid column",
785 CONFIG_GROUP_SID_DEFAULT),
786 sid_to_string(sid_str,
787 pdb_get_group_sid(newpwd)));
789 pdb_mysql_string_field(methods, &query,
790 config_value_write(data, "username column",
791 CONFIG_USERNAME_DEFAULT),
792 pdb_get_username(newpwd));
794 pdb_mysql_string_field(methods, &query,
795 config_value_write(data, "domain column",
796 CONFIG_DOMAIN_DEFAULT),
797 pdb_get_domain(newpwd));
799 pdb_mysql_string_field(methods, &query,
800 config_value_write(data,
801 "nt username column",
802 CONFIG_NT_USERNAME_DEFAULT),
803 pdb_get_nt_username(newpwd));
805 pdb_mysql_string_field(methods, &query,
806 config_value_write(data, "fullname column",
807 CONFIG_FULLNAME_DEFAULT),
808 pdb_get_fullname(newpwd));
810 pdb_mysql_string_field(methods, &query,
811 config_value_write(data,
812 "logon script column",
813 CONFIG_LOGON_SCRIPT_DEFAULT),
814 pdb_get_logon_script(newpwd));
816 pdb_mysql_string_field(methods, &query,
817 config_value_write(data,
818 "profile path column",
819 CONFIG_PROFILE_PATH_DEFAULT),
820 pdb_get_profile_path(newpwd));
822 pdb_mysql_string_field(methods, &query,
823 config_value_write(data, "dir drive column",
824 CONFIG_DIR_DRIVE_DEFAULT),
825 pdb_get_dir_drive(newpwd));
827 pdb_mysql_string_field(methods, &query,
828 config_value_write(data, "home dir column",
829 CONFIG_HOME_DIR_DEFAULT),
830 pdb_get_homedir(newpwd));
832 pdb_mysql_string_field(methods, &query,
833 config_value_write(data,
834 "workstations column",
835 CONFIG_WORKSTATIONS_DEFAULT),
836 pdb_get_workstations(newpwd));
838 pdb_mysql_string_field(methods, &query,
839 config_value_write(data,
840 "unknown string column",
841 CONFIG_UNKNOWN_STR_DEFAULT),
842 pdb_get_workstations(newpwd));
844 pdb_sethexpwd(temp, pdb_get_lanman_passwd(newpwd),
845 pdb_get_acct_ctrl(newpwd));
846 pdb_mysql_string_field(methods, &query,
847 config_value_write(data,
848 "lanman pass column",
849 CONFIG_LM_PW_DEFAULT), temp);
851 pdb_sethexpwd(temp, pdb_get_nt_passwd(newpwd),
852 pdb_get_acct_ctrl(newpwd));
853 pdb_mysql_string_field(methods, &query,
854 config_value_write(data, "nt pass column",
855 CONFIG_NT_PW_DEFAULT), temp);
858 query.part1[strlen(query.part1) - 1] = '\0';
860 talloc_asprintf_append(query.mem_ctx, query.part1,
862 config_value_read(data,
864 CONFIG_USER_SID_DEFAULT),
865 sid_to_string(sid_str, pdb_get_user_sid (newpwd)));
867 query.part2[strlen(query.part2) - 1] = ')';
868 query.part1[strlen(query.part1) - 1] = ')';
870 talloc_asprintf_append(query.mem_ctx, query.part1,
871 " VALUES (%s", query.part2);
874 DEBUG(0, ("%s\n", query.part1));
875 /* Execute the query */
876 if (mysql_query(data->handle, query.part1)) {
878 ("Error executing %s, %s\n", query.part1,
879 mysql_error(data->handle)));
880 return NT_STATUS_INVALID_PARAMETER;
882 talloc_destroy(query.mem_ctx);
886 static NTSTATUS mysqlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT * newpwd)
888 return mysqlsam_replace_sam_account(methods, newpwd, 0);
891 static NTSTATUS mysqlsam_update_sam_account(struct pdb_methods *methods,
892 SAM_ACCOUNT * newpwd)
894 return mysqlsam_replace_sam_account(methods, newpwd, 1);
897 static NTSTATUS mysqlsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map,
898 DOM_SID sid, BOOL with_priv)
900 return get_group_map_from_sid(sid, map, with_priv) ?
901 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
904 static NTSTATUS mysqlsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
905 gid_t gid, BOOL with_priv)
907 return get_group_map_from_gid(gid, map, with_priv) ?
908 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
911 static NTSTATUS mysqlsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map,
912 char *name, BOOL with_priv)
914 return get_group_map_from_ntname(name, map, with_priv) ?
915 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
918 static NTSTATUS mysqlsam_add_group_mapping_entry(struct pdb_methods *methods,
921 return add_mapping_entry(map, TDB_INSERT) ?
922 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
925 static NTSTATUS mysqlsam_update_group_mapping_entry(struct pdb_methods *methods,
928 return add_mapping_entry(map, TDB_REPLACE) ?
929 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
932 static NTSTATUS mysqlsam_delete_group_mapping_entry(struct pdb_methods *methods,
935 return group_map_remove(sid) ?
936 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
939 static NTSTATUS mysqlsam_enum_group_mapping(struct pdb_methods *methods,
940 enum SID_NAME_USE sid_name_use,
941 GROUP_MAP **rmap, int *num_entries,
942 BOOL unix_only, BOOL with_priv)
944 return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only,
946 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
950 NTSTATUS pdb_init(PDB_CONTEXT * pdb_context, PDB_METHODS ** pdb_method,
954 struct pdb_mysql_data *data;
956 mysqlsam_debug_level = debug_add_class("mysqlsam");
957 if (mysqlsam_debug_level == -1) {
958 mysqlsam_debug_level = DBGC_ALL;
960 ("mysqlsam: Couldn't register custom debugging class!\n"));
964 DEBUG(0, ("invalid pdb_methods specified\n"));
965 return NT_STATUS_UNSUCCESSFUL;
969 (nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
973 (*pdb_method)->name = "mysqlsam";
975 (*pdb_method)->setsampwent = mysqlsam_setsampwent;
976 (*pdb_method)->endsampwent = mysqlsam_endsampwent;
977 (*pdb_method)->getsampwent = mysqlsam_getsampwent;
978 (*pdb_method)->getsampwnam = mysqlsam_getsampwnam;
979 (*pdb_method)->getsampwsid = mysqlsam_getsampwsid;
980 (*pdb_method)->add_sam_account = mysqlsam_add_sam_account;
981 (*pdb_method)->update_sam_account = mysqlsam_update_sam_account;
982 (*pdb_method)->delete_sam_account = mysqlsam_delete_sam_account;
983 (*pdb_method)->getgrsid = mysqlsam_getgrsid;
984 (*pdb_method)->getgrgid = mysqlsam_getgrgid;
985 (*pdb_method)->getgrnam = mysqlsam_getgrnam;
986 (*pdb_method)->add_group_mapping_entry = mysqlsam_add_group_mapping_entry;
987 (*pdb_method)->update_group_mapping_entry = mysqlsam_update_group_mapping_entry;
988 (*pdb_method)->delete_group_mapping_entry = mysqlsam_delete_group_mapping_entry;
989 (*pdb_method)->enum_group_mapping = mysqlsam_enum_group_mapping;
991 data = talloc(pdb_context->mem_ctx, sizeof(struct pdb_mysql_data));
992 (*pdb_method)->private_data = data;
997 DEBUG(0, ("No identifier specified. See README for details\n"));
998 return NT_STATUS_INVALID_PARAMETER;
1001 data->location = smb_xstrdup(location);
1004 ("Connecting to database server, host: %s, user: %s, password: %s, database: %s, port: %ld\n",
1005 config_value(data, "mysql host", CONFIG_HOST_DEFAULT),
1006 config_value(data, "mysql user", CONFIG_USER_DEFAULT),
1007 config_value(data, "mysql password", CONFIG_PASS_DEFAULT),
1008 config_value(data, "mysql database", CONFIG_DB_DEFAULT),
1009 xatol(config_value(data, "mysql port", CONFIG_PORT_DEFAULT))));
1011 /* Do the mysql initialization */
1012 data->handle = mysql_init(NULL);
1013 if (!data->handle) {
1014 DEBUG(0, ("Failed to connect to server\n"));
1015 return NT_STATUS_UNSUCCESSFUL;
1017 /* Process correct entry in $HOME/.my.conf */
1018 if (!mysql_real_connect(data->handle,
1019 config_value(data, "mysql host", CONFIG_HOST_DEFAULT),
1020 config_value(data, "mysql user", CONFIG_USER_DEFAULT),
1021 config_value(data, "mysql password", CONFIG_PASS_DEFAULT),
1022 config_value(data, "mysql database", CONFIG_DB_DEFAULT),
1023 xatol(config_value (data, "mysql port", CONFIG_PORT_DEFAULT)),
1026 ("Failed to connect to mysql database: error: %s\n",
1027 mysql_error(data->handle)));
1028 return NT_STATUS_UNSUCCESSFUL;
1031 DEBUG(5, ("Connected to mysql db\n"));
1033 return NT_STATUS_OK;