3 * MySQL password backend for samba
4 * Copyright (C) Jelmer Vernooij 2002
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc., 675
18 * Mass Ave, Cambridge, MA 02139, USA.
22 #include <mysql/mysql.h>
24 #define CONFIG_TABLE_DEFAULT "user"
25 #define CONFIG_LOGON_TIME_DEFAULT "logon_time"
26 #define CONFIG_LOGOFF_TIME_DEFAULT "logoff_time"
27 #define CONFIG_KICKOFF_TIME_DEFAULT "kickoff_time"
28 #define CONFIG_PASS_LAST_SET_TIME_DEFAULT "pass_last_set_time"
29 #define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT "pass_can_change_time"
30 #define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT "pass_must_change_time"
31 #define CONFIG_USERNAME_DEFAULT "username"
32 #define CONFIG_DOMAIN_DEFAULT "domain"
33 #define CONFIG_NT_USERNAME_DEFAULT "nt_username"
34 #define CONFIG_FULLNAME_DEFAULT "nt_fullname"
35 #define CONFIG_HOME_DIR_DEFAULT "home_dir"
36 #define CONFIG_DIR_DRIVE_DEFAULT "dir_drive"
37 #define CONFIG_LOGON_SCRIPT_DEFAULT "logon_script"
38 #define CONFIG_PROFILE_PATH_DEFAULT "profile_path"
39 #define CONFIG_ACCT_DESC_DEFAULT "acct_desc"
40 #define CONFIG_WORKSTATIONS_DEFAULT "workstations"
41 #define CONFIG_UNKNOWN_STR_DEFAULT "unknown_str"
42 #define CONFIG_MUNGED_DIAL_DEFAULT "munged_dial"
43 #define CONFIG_UID_DEFAULT "uid"
44 #define CONFIG_GID_DEFAULT "gid"
45 #define CONFIG_USER_SID_DEFAULT "user_sid"
46 #define CONFIG_GROUP_SID_DEFAULT "group_sid"
47 #define CONFIG_LM_PW_DEFAULT "lm_pw"
48 #define CONFIG_NT_PW_DEFAULT "nt_pw"
49 #define CONFIG_PLAIN_PW_DEFAULT "NULL"
50 #define CONFIG_ACCT_CTRL_DEFAULT "acct_ctrl"
51 #define CONFIG_UNKNOWN_3_DEFAULT "unknown_3"
52 #define CONFIG_LOGON_DIVS_DEFAULT "logon_divs"
53 #define CONFIG_HOURS_LEN_DEFAULT "hours_len"
54 #define CONFIG_UNKNOWN_5_DEFAULT "unknown_5"
55 #define CONFIG_UNKNOWN_6_DEFAULT "unknown_6"
56 #define CONFIG_HOST_DEFAULT "localhost"
57 #define CONFIG_USER_DEFAULT "samba"
58 #define CONFIG_PASS_DEFAULT ""
59 #define CONFIG_PORT_DEFAULT "3306"
60 #define CONFIG_DB_DEFAULT "samba"
62 static int mysqlsam_debug_level
= DBGC_ALL
;
65 #define DBGC_CLASS mysqlsam_debug_level
67 typedef struct pdb_mysql_data
{
73 /* Used to construct insert and update queries */
75 typedef struct pdb_mysql_query
{
81 #define SET_DATA(data,methods) { \
83 DEBUG(0, ("invalid methods!\n")); \
84 return NT_STATUS_INVALID_PARAMETER; \
86 data = (struct pdb_mysql_data *)methods->private_data; \
87 if(!data || !(data->handle)){ \
88 DEBUG(0, ("invalid handle!\n")); \
89 return NT_STATUS_INVALID_HANDLE; \
93 static void pdb_mysql_int_field(struct pdb_methods
*m
,
94 struct pdb_mysql_query
*q
, char *name
, int value
)
96 if (!name
|| strchr(name
, '\''))
97 return; /* This field shouldn't be set by us */
101 talloc_asprintf_append(q
->mem_ctx
, q
->part1
,
102 "%s = %d,", name
, value
);
105 talloc_asprintf_append(q
->mem_ctx
, q
->part1
, "%s,", name
);
107 talloc_asprintf_append(q
->mem_ctx
, q
->part2
, "%d,", value
);
111 static NTSTATUS
pdb_mysql_string_field(struct pdb_methods
*methods
,
112 struct pdb_mysql_query
*q
,
113 char *name
, const char *value
)
116 struct pdb_mysql_data
*data
;
119 SET_DATA(data
, methods
);
121 if (!name
|| !value
|| !strcmp(value
, "") || strchr(name
, '\''))
122 return NT_STATUS_INVALID_PARAMETER
; /* This field shouldn't be set by module */
124 esc_value
= malloc(strlen(value
) * 2 + 1);
126 tmp_value
= smb_xstrdup(value
);
127 mysql_real_escape_string(data
->handle
, esc_value
, tmp_value
,
129 SAFE_FREE(tmp_value
);
133 talloc_asprintf_append(q
->mem_ctx
, q
->part1
,
134 "%s = '%s',", name
, esc_value
);
137 talloc_asprintf_append(q
->mem_ctx
, q
->part1
, "%s,", name
);
139 talloc_asprintf_append(q
->mem_ctx
, q
->part2
, "'%s',",
143 SAFE_FREE(esc_value
);
148 static char * config_value(pdb_mysql_data
* data
, char *name
, char *default_value
)
150 if (lp_parm_string(NULL
, data
->location
, name
))
151 return lp_parm_string(NULL
, data
->location
, name
);
153 return default_value
;
156 static char * config_value_write(pdb_mysql_data
* data
, char *name
, char *default_value
) {
157 char *v
= config_value(data
, name
, NULL
);
161 return default_value
;
163 swrite
= strchr(v
, ':');
165 /* Default to the same field as read field */
171 /* If the field is 0 chars long, we shouldn't write to it */
172 if (!strlen(swrite
) || !strcmp(swrite
, "NULL"))
175 /* Otherwise, use the additionally specified */
179 static const char * config_value_read(pdb_mysql_data
* data
, char *name
, char *default_value
)
181 char *v
= config_value(data
, name
, NULL
);
185 return default_value
;
187 swrite
= strchr(v
, ':');
189 /* If no write is specified, there are no problems */
196 /* Otherwise, we have to cut the ':write_part' */
204 /* Wrapper for atol that returns 0 if 'a' points to NULL */
205 static long xatol(char *a
)
215 static NTSTATUS
row_to_sam_account(MYSQL_RES
* r
, SAM_ACCOUNT
* u
)
219 unsigned int num_fields
;
222 num_fields
= mysql_num_fields(r
);
223 row
= mysql_fetch_row(r
);
225 return NT_STATUS_INVALID_PARAMETER
;
227 pdb_set_logon_time(u
, xatol(row
[0]), PDB_SET
);
228 pdb_set_logoff_time(u
, xatol(row
[1]), PDB_SET
);
229 pdb_set_kickoff_time(u
, xatol(row
[2]), PDB_SET
);
230 pdb_set_pass_last_set_time(u
, xatol(row
[3]), PDB_SET
);
231 pdb_set_pass_can_change_time(u
, xatol(row
[4]), PDB_SET
);
232 pdb_set_pass_must_change_time(u
, xatol(row
[5]), PDB_SET
);
233 pdb_set_username(u
, row
[6], PDB_SET
);
234 pdb_set_domain(u
, row
[7], PDB_SET
);
235 pdb_set_nt_username(u
, row
[8], PDB_SET
);
236 pdb_set_fullname(u
, row
[9], PDB_SET
);
237 pdb_set_homedir(u
, row
[10], PDB_SET
);
238 pdb_set_dir_drive(u
, row
[11], PDB_SET
);
239 pdb_set_logon_script(u
, row
[12], PDB_SET
);
240 pdb_set_profile_path(u
, row
[13], PDB_SET
);
241 pdb_set_acct_desc(u
, row
[14], PDB_SET
);
242 pdb_set_workstations(u
, row
[15], PDB_SET
);
243 pdb_set_unknown_str(u
, row
[16], PDB_SET
);
244 pdb_set_munged_dial(u
, row
[17], PDB_SET
);
247 pdb_set_uid(u
, xatol(row
[18]), PDB_SET
);
249 pdb_set_gid(u
, xatol(row
[19]), PDB_SET
);
251 string_to_sid(&sid
, row
[20]);
252 pdb_set_user_sid(u
, &sid
, PDB_SET
);
253 string_to_sid(&sid
, row
[21]);
254 pdb_set_group_sid(u
, &sid
, PDB_SET
);
256 if (pdb_gethexpwd(row
[22], temp
), PDB_SET
)
257 pdb_set_lanman_passwd(u
, temp
, PDB_SET
);
258 if (pdb_gethexpwd(row
[23], temp
), PDB_SET
)
259 pdb_set_nt_passwd(u
, temp
, PDB_SET
);
261 /* Only use plaintext password storage when lanman and nt are
263 if (!row
[22] || !row
[23])
264 pdb_set_plaintext_passwd(u
, row
[24]);
266 pdb_set_acct_ctrl(u
, xatol(row
[25]), PDB_SET
);
267 pdb_set_unknown_3(u
, xatol(row
[26]), PDB_SET
);
268 pdb_set_logon_divs(u
, xatol(row
[27]), PDB_SET
);
269 pdb_set_hours_len(u
, xatol(row
[28]), PDB_SET
);
270 pdb_set_unknown_5(u
, xatol(row
[29]), PDB_SET
);
271 pdb_set_unknown_6(u
, xatol(row
[30]), PDB_SET
);
276 static NTSTATUS
mysqlsam_setsampwent(struct pdb_methods
*methods
, BOOL update
)
278 struct pdb_mysql_data
*data
=
279 (struct pdb_mysql_data
*) methods
->private_data
;
283 if (!data
|| !(data
->handle
)) {
284 DEBUG(0, ("invalid handle!\n"));
285 return NT_STATUS_INVALID_HANDLE
;
289 "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",
290 config_value_read(data
, "logon time column",
291 CONFIG_LOGON_TIME_DEFAULT
),
292 config_value_read(data
, "logoff time column",
293 CONFIG_LOGOFF_TIME_DEFAULT
),
294 config_value_read(data
, "kickoff time column",
295 CONFIG_KICKOFF_TIME_DEFAULT
),
296 config_value_read(data
, "pass last set time column",
297 CONFIG_PASS_LAST_SET_TIME_DEFAULT
),
298 config_value_read(data
, "pass can change time column",
299 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT
),
300 config_value_read(data
, "pass must change time column",
301 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT
),
302 config_value_read(data
, "username column",
303 CONFIG_USERNAME_DEFAULT
),
304 config_value_read(data
, "domain column",
305 CONFIG_DOMAIN_DEFAULT
),
306 config_value_read(data
, "nt username column",
307 CONFIG_NT_USERNAME_DEFAULT
),
308 config_value_read(data
, "fullname column",
309 CONFIG_FULLNAME_DEFAULT
),
310 config_value_read(data
, "home dir column",
311 CONFIG_HOME_DIR_DEFAULT
),
312 config_value_read(data
, "dir drive column",
313 CONFIG_DIR_DRIVE_DEFAULT
),
314 config_value_read(data
, "logon script column",
315 CONFIG_LOGON_SCRIPT_DEFAULT
),
316 config_value_read(data
, "profile path column",
317 CONFIG_PROFILE_PATH_DEFAULT
),
318 config_value_read(data
, "acct desc column",
319 CONFIG_ACCT_DESC_DEFAULT
),
320 config_value_read(data
, "workstations column",
321 CONFIG_WORKSTATIONS_DEFAULT
),
322 config_value_read(data
, "unknown string column",
323 CONFIG_UNKNOWN_STR_DEFAULT
),
324 config_value_read(data
, "munged dial column",
325 CONFIG_MUNGED_DIAL_DEFAULT
),
326 config_value_read(data
, "uid column", CONFIG_UID_DEFAULT
),
327 config_value_read(data
, "gid column", CONFIG_GID_DEFAULT
),
328 config_value_read(data
, "user sid column",
329 CONFIG_USER_SID_DEFAULT
),
330 config_value_read(data
, "group sid column",
331 CONFIG_GROUP_SID_DEFAULT
),
332 config_value_read(data
, "lanman pass column",
333 CONFIG_LM_PW_DEFAULT
),
334 config_value_read(data
, "nt pass column",
335 CONFIG_NT_PW_DEFAULT
),
336 config_value_read(data
, "plain pass column",
337 CONFIG_PLAIN_PW_DEFAULT
),
338 config_value_read(data
, "acct ctrl column",
339 CONFIG_ACCT_CTRL_DEFAULT
),
340 config_value_read(data
, "unknown 3 column",
341 CONFIG_UNKNOWN_3_DEFAULT
),
342 config_value_read(data
, "logon divs column",
343 CONFIG_LOGON_DIVS_DEFAULT
),
344 config_value_read(data
, "hours len column",
345 CONFIG_HOURS_LEN_DEFAULT
),
346 config_value_read(data
, "unknown 5 column",
347 CONFIG_UNKNOWN_5_DEFAULT
),
348 config_value_read(data
, "unknown 6 column",
349 CONFIG_UNKNOWN_6_DEFAULT
),
350 config_value(data
, "table", CONFIG_TABLE_DEFAULT
)
352 DEBUG(5, ("Executing query %s\n", query
));
354 ret
= mysql_query(data
->handle
, query
);
359 ("Error executing MySQL query %s\n", mysql_error(data
->handle
)));
360 return NT_STATUS_UNSUCCESSFUL
;
363 data
->pwent
= mysql_store_result(data
->handle
);
365 if (data
->pwent
== NULL
) {
367 ("Error storing results: %s\n", mysql_error(data
->handle
)));
368 return NT_STATUS_UNSUCCESSFUL
;
372 ("mysqlsam_setsampwent succeeded(%lu results)!\n",
373 mysql_num_rows(data
->pwent
)));
378 /***************************************************************
379 End enumeration of the passwd list.
380 ****************************************************************/
382 static void mysqlsam_endsampwent(struct pdb_methods
*methods
)
384 struct pdb_mysql_data
*data
=
385 (struct pdb_mysql_data
*) methods
->private_data
;
388 DEBUG(0, ("invalid handle!\n"));
392 if (data
->pwent
!= NULL
)
393 mysql_free_result(data
->pwent
);
397 DEBUG(5, ("mysql_endsampwent called\n"));
400 /*****************************************************************
401 Get one SAM_ACCOUNT from the list (next in line)
402 *****************************************************************/
404 static NTSTATUS
mysqlsam_getsampwent(struct pdb_methods
*methods
, SAM_ACCOUNT
* user
)
406 struct pdb_mysql_data
*data
;
408 SET_DATA(data
, methods
);
410 if (data
->pwent
== NULL
) {
411 DEBUG(0, ("invalid pwent\n"));
412 return NT_STATUS_INVALID_PARAMETER
;
415 return row_to_sam_account(data
->pwent
, user
);
418 static NTSTATUS
mysqlsam_select_by_field(struct pdb_methods
* methods
, SAM_ACCOUNT
* user
,
419 const char *field
, const char *sname
)
426 struct pdb_mysql_data
*data
;
429 SET_DATA(data
, methods
);
431 esc_sname
= malloc(strlen(sname
) * 2 + 1);
433 return NT_STATUS_NO_MEMORY
;
437 ("mysqlsam_select_by_field: getting data where %s = %s(nonescaped)\n",
440 tmp_sname
= smb_xstrdup(sname
);
443 mysql_real_escape_string(data
->handle
, esc_sname
, tmp_sname
,
446 SAFE_FREE(tmp_sname
);
449 DEBUG(0, ("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
450 SAFE_FREE(esc_sname
);
451 return NT_STATUS_INVALID_PARAMETER
;
455 "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'",
456 config_value_read(data
, "logon time column",
457 CONFIG_LOGON_TIME_DEFAULT
),
458 config_value_read(data
, "logoff time column",
459 CONFIG_LOGOFF_TIME_DEFAULT
),
460 config_value_read(data
, "kickoff time column",
461 CONFIG_KICKOFF_TIME_DEFAULT
),
462 config_value_read(data
, "pass last set time column",
463 CONFIG_PASS_LAST_SET_TIME_DEFAULT
),
464 config_value_read(data
, "pass can change time column",
465 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT
),
466 config_value_read(data
, "pass must change time column",
467 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT
),
468 config_value_read(data
, "username column",
469 CONFIG_USERNAME_DEFAULT
),
470 config_value_read(data
, "domain column",
471 CONFIG_DOMAIN_DEFAULT
),
472 config_value_read(data
, "nt username column",
473 CONFIG_NT_USERNAME_DEFAULT
),
474 config_value_read(data
, "fullname column",
475 CONFIG_FULLNAME_DEFAULT
),
476 config_value_read(data
, "home dir column",
477 CONFIG_HOME_DIR_DEFAULT
),
478 config_value_read(data
, "dir drive column",
479 CONFIG_DIR_DRIVE_DEFAULT
),
480 config_value_read(data
, "logon script column",
481 CONFIG_LOGON_SCRIPT_DEFAULT
),
482 config_value_read(data
, "profile path column",
483 CONFIG_PROFILE_PATH_DEFAULT
),
484 config_value_read(data
, "acct desc column",
485 CONFIG_ACCT_DESC_DEFAULT
),
486 config_value_read(data
, "workstations column",
487 CONFIG_WORKSTATIONS_DEFAULT
),
488 config_value_read(data
, "unknown string column",
489 CONFIG_UNKNOWN_STR_DEFAULT
),
490 config_value_read(data
, "munged dial column",
491 CONFIG_MUNGED_DIAL_DEFAULT
),
492 config_value_read(data
, "uid column", CONFIG_UID_DEFAULT
),
493 config_value_read(data
, "gid column", CONFIG_GID_DEFAULT
),
494 config_value_read(data
, "user sid column",
495 CONFIG_USER_SID_DEFAULT
),
496 config_value_read(data
, "group sid column",
497 CONFIG_GROUP_SID_DEFAULT
),
498 config_value_read(data
, "lanman pass column",
499 CONFIG_LM_PW_DEFAULT
),
500 config_value_read(data
, "nt pass column",
501 CONFIG_NT_PW_DEFAULT
),
502 config_value_read(data
, "plain pass column",
503 CONFIG_PLAIN_PW_DEFAULT
),
504 config_value_read(data
, "acct ctrl column",
505 CONFIG_ACCT_CTRL_DEFAULT
),
506 config_value_read(data
, "unknown 3 column",
507 CONFIG_UNKNOWN_3_DEFAULT
),
508 config_value_read(data
, "logon divs column",
509 CONFIG_LOGON_DIVS_DEFAULT
),
510 config_value_read(data
, "hours len column",
511 CONFIG_HOURS_LEN_DEFAULT
),
512 config_value_read(data
, "unknown 5 column",
513 CONFIG_UNKNOWN_5_DEFAULT
),
514 config_value_read(data
, "unknown 6 column",
515 CONFIG_UNKNOWN_6_DEFAULT
),
516 config_value(data
, "table", CONFIG_TABLE_DEFAULT
), field
,
519 SAFE_FREE(esc_sname
);
521 DEBUG(5, ("Executing query %s\n", query
));
523 mysql_ret
= mysql_query(data
->handle
, query
);
529 ("Error while executing MySQL query %s\n",
530 mysql_error(data
->handle
)));
531 return NT_STATUS_UNSUCCESSFUL
;
534 res
= mysql_store_result(data
->handle
);
537 ("Error storing results: %s\n", mysql_error(data
->handle
)));
538 return NT_STATUS_UNSUCCESSFUL
;
541 ret
= row_to_sam_account(res
, user
);
542 mysql_free_result(res
);
547 /******************************************************************
548 Lookup a name in the SAM database
549 ******************************************************************/
551 static NTSTATUS
mysqlsam_getsampwnam(struct pdb_methods
*methods
, SAM_ACCOUNT
* user
,
554 struct pdb_mysql_data
*data
;
556 SET_DATA(data
, methods
);
559 DEBUG(0, ("invalid name specified"));
560 return NT_STATUS_INVALID_PARAMETER
;
563 return mysqlsam_select_by_field(methods
, user
,
564 config_value_read(data
, "username column",
565 CONFIG_USERNAME_DEFAULT
), sname
);
569 /***************************************************************************
571 **************************************************************************/
573 static NTSTATUS
mysqlsam_getsampwsid(struct pdb_methods
*methods
, SAM_ACCOUNT
* user
,
576 struct pdb_mysql_data
*data
;
579 SET_DATA(data
, methods
);
581 sid_to_string(sid_str
, sid
);
583 return mysqlsam_select_by_field(methods
, user
,
584 config_value_read(data
, "user sid column",
585 CONFIG_USER_SID_DEFAULT
), sid_str
);
588 /***************************************************************************
590 ****************************************************************************/
592 static NTSTATUS
mysqlsam_delete_sam_account(struct pdb_methods
*methods
,
593 SAM_ACCOUNT
* sam_pass
)
595 const char *sname
= pdb_get_username(sam_pass
);
599 struct pdb_mysql_data
*data
;
602 SET_DATA(data
, methods
);
605 DEBUG(0, ("invalid methods!\n"));
606 return NT_STATUS_INVALID_PARAMETER
;
609 data
= (struct pdb_mysql_data
*) methods
->private_data
;
610 if (!data
|| !(data
->handle
)) {
611 DEBUG(0, ("invalid handle!\n"));
612 return NT_STATUS_INVALID_HANDLE
;
616 DEBUG(0, ("invalid name specified\n"));
617 return NT_STATUS_INVALID_PARAMETER
;
621 esc
= malloc(strlen(sname
) * 2 + 1);
623 DEBUG(0, ("Can't allocate memory to store escaped name\n"));
624 return NT_STATUS_NO_MEMORY
;
627 tmp_sname
= smb_xstrdup(sname
);
629 mysql_real_escape_string(data
->handle
, esc
, tmp_sname
,
632 SAFE_FREE(tmp_sname
);
634 asprintf(&query
, "DELETE FROM %s WHERE %s = '%s'",
635 config_value(data
, "table", CONFIG_TABLE_DEFAULT
),
636 config_value_read(data
, "username column",
637 CONFIG_USERNAME_DEFAULT
), esc
);
641 ret
= mysql_query(data
->handle
, query
);
647 ("Error while executing query: %s\n",
648 mysql_error(data
->handle
)));
649 return NT_STATUS_UNSUCCESSFUL
;
652 DEBUG(5, ("User '%s' deleted\n", sname
));
656 static NTSTATUS
mysqlsam_replace_sam_account(struct pdb_methods
*methods
,
657 const SAM_ACCOUNT
* newpwd
, char isupdate
)
660 struct pdb_mysql_data
*data
;
661 pdb_mysql_query query
;
665 DEBUG(0, ("invalid methods!\n"));
666 return NT_STATUS_INVALID_PARAMETER
;
669 data
= (struct pdb_mysql_data
*) methods
->private_data
;
670 if (data
== NULL
|| data
->handle
== NULL
) {
671 DEBUG(0, ("invalid handle!\n"));
672 return NT_STATUS_INVALID_HANDLE
;
674 query
.update
= isupdate
;
676 /* I know this is somewhat overkill but only the talloc
677 * functions have asprint_append and the 'normal' asprintf
678 * is a GNU extension */
679 query
.mem_ctx
= talloc_init("mysqlsam_replace_sam_account");
680 query
.part2
= talloc_asprintf(query
.mem_ctx
, "%s", "");
683 talloc_asprintf(query
.mem_ctx
, "UPDATE %s SET ",
684 config_value(data
, "table",
685 CONFIG_TABLE_DEFAULT
));
688 talloc_asprintf(query
.mem_ctx
, "INSERT INTO %s (",
689 config_value(data
, "table",
690 CONFIG_TABLE_DEFAULT
));
693 pdb_mysql_int_field(methods
, &query
,
694 config_value_write(data
, "acct ctrl column",
695 CONFIG_ACCT_CTRL_DEFAULT
),
696 pdb_get_acct_ctrl(newpwd
));
698 if (pdb_get_init_flags(newpwd
, PDB_LOGONTIME
) != PDB_DEFAULT
) {
699 pdb_mysql_int_field(methods
, &query
,
700 config_value_write(data
,
702 CONFIG_LOGON_TIME_DEFAULT
),
703 pdb_get_logon_time(newpwd
));
706 if (pdb_get_init_flags(newpwd
, PDB_LOGOFFTIME
) != PDB_DEFAULT
) {
707 pdb_mysql_int_field(methods
, &query
,
708 config_value_write(data
,
709 "logoff time column",
710 CONFIG_LOGOFF_TIME_DEFAULT
),
711 pdb_get_logoff_time(newpwd
));
714 if (pdb_get_init_flags(newpwd
, PDB_KICKOFFTIME
) != PDB_DEFAULT
) {
715 pdb_mysql_int_field(methods
, &query
,
716 config_value_write(data
,
717 "kickoff time column",
718 CONFIG_KICKOFF_TIME_DEFAULT
),
719 pdb_get_kickoff_time(newpwd
));
722 if (pdb_get_init_flags(newpwd
, PDB_CANCHANGETIME
) != PDB_DEFAULT
) {
723 pdb_mysql_int_field(methods
, &query
,
724 config_value_write(data
,
725 "pass can change time column",
726 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT
),
727 pdb_get_pass_can_change_time(newpwd
));
730 if (pdb_get_init_flags(newpwd
, PDB_MUSTCHANGETIME
) != PDB_DEFAULT
) {
731 pdb_mysql_int_field(methods
, &query
,
732 config_value_write(data
,
733 "pass must change time column",
734 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT
),
735 pdb_get_pass_must_change_time(newpwd
));
738 if (pdb_get_pass_last_set_time(newpwd
)) {
739 pdb_mysql_int_field(methods
, &query
,
740 config_value_write(data
,
741 "pass last set time column",
742 CONFIG_PASS_LAST_SET_TIME_DEFAULT
),
743 pdb_get_pass_last_set_time(newpwd
));
746 if (pdb_get_hours_len(newpwd
)) {
747 pdb_mysql_int_field(methods
, &query
,
748 config_value_write(data
,
750 CONFIG_HOURS_LEN_DEFAULT
),
751 pdb_get_hours_len(newpwd
));
754 if (pdb_get_logon_divs(newpwd
)) {
755 pdb_mysql_int_field(methods
, &query
,
756 config_value_write(data
,
758 CONFIG_LOGON_DIVS_DEFAULT
),
759 pdb_get_logon_divs(newpwd
));
762 if (pdb_get_init_flags(newpwd
, PDB_UID
) != PDB_DEFAULT
) {
763 pdb_mysql_int_field(methods
, &query
,
764 config_value_write(data
, "uid column",
766 pdb_get_uid(newpwd
));
769 if (pdb_get_init_flags(newpwd
, PDB_GID
) != PDB_DEFAULT
) {
770 pdb_mysql_int_field(methods
, &query
,
771 config_value_write(data
, "gid column",
773 pdb_get_gid(newpwd
));
776 pdb_mysql_string_field(methods
, &query
,
777 config_value_write(data
, "user sid column",
778 CONFIG_USER_SID_DEFAULT
),
779 sid_to_string(sid_str
,
780 pdb_get_user_sid(newpwd
)));
782 pdb_mysql_string_field(methods
, &query
,
783 config_value_write(data
, "group sid column",
784 CONFIG_GROUP_SID_DEFAULT
),
785 sid_to_string(sid_str
,
786 pdb_get_group_sid(newpwd
)));
788 pdb_mysql_string_field(methods
, &query
,
789 config_value_write(data
, "username column",
790 CONFIG_USERNAME_DEFAULT
),
791 pdb_get_username(newpwd
));
793 pdb_mysql_string_field(methods
, &query
,
794 config_value_write(data
, "domain column",
795 CONFIG_DOMAIN_DEFAULT
),
796 pdb_get_domain(newpwd
));
798 pdb_mysql_string_field(methods
, &query
,
799 config_value_write(data
,
800 "nt username column",
801 CONFIG_NT_USERNAME_DEFAULT
),
802 pdb_get_nt_username(newpwd
));
804 pdb_mysql_string_field(methods
, &query
,
805 config_value_write(data
, "fullname column",
806 CONFIG_FULLNAME_DEFAULT
),
807 pdb_get_fullname(newpwd
));
809 pdb_mysql_string_field(methods
, &query
,
810 config_value_write(data
,
811 "logon script column",
812 CONFIG_LOGON_SCRIPT_DEFAULT
),
813 pdb_get_logon_script(newpwd
));
815 pdb_mysql_string_field(methods
, &query
,
816 config_value_write(data
,
817 "profile path column",
818 CONFIG_PROFILE_PATH_DEFAULT
),
819 pdb_get_profile_path(newpwd
));
821 pdb_mysql_string_field(methods
, &query
,
822 config_value_write(data
, "dir drive column",
823 CONFIG_DIR_DRIVE_DEFAULT
),
824 pdb_get_dir_drive(newpwd
));
826 pdb_mysql_string_field(methods
, &query
,
827 config_value_write(data
, "home dir column",
828 CONFIG_HOME_DIR_DEFAULT
),
829 pdb_get_homedir(newpwd
));
831 pdb_mysql_string_field(methods
, &query
,
832 config_value_write(data
,
833 "workstations column",
834 CONFIG_WORKSTATIONS_DEFAULT
),
835 pdb_get_workstations(newpwd
));
837 pdb_mysql_string_field(methods
, &query
,
838 config_value_write(data
,
839 "unknown string column",
840 CONFIG_UNKNOWN_STR_DEFAULT
),
841 pdb_get_workstations(newpwd
));
843 pdb_sethexpwd(temp
, pdb_get_lanman_passwd(newpwd
),
844 pdb_get_acct_ctrl(newpwd
));
845 pdb_mysql_string_field(methods
, &query
,
846 config_value_write(data
,
847 "lanman pass column",
848 CONFIG_LM_PW_DEFAULT
), temp
);
850 pdb_sethexpwd(temp
, pdb_get_nt_passwd(newpwd
),
851 pdb_get_acct_ctrl(newpwd
));
852 pdb_mysql_string_field(methods
, &query
,
853 config_value_write(data
, "nt pass column",
854 CONFIG_NT_PW_DEFAULT
), temp
);
857 query
.part1
[strlen(query
.part1
) - 1] = '\0';
859 talloc_asprintf_append(query
.mem_ctx
, query
.part1
,
861 config_value_read(data
,
863 CONFIG_USER_SID_DEFAULT
),
864 sid_to_string(sid_str
, pdb_get_user_sid (newpwd
)));
866 query
.part2
[strlen(query
.part2
) - 1] = ')';
867 query
.part1
[strlen(query
.part1
) - 1] = ')';
869 talloc_asprintf_append(query
.mem_ctx
, query
.part1
,
870 " VALUES (%s", query
.part2
);
873 DEBUG(0, ("%s\n", query
.part1
));
874 /* Execute the query */
875 if (mysql_query(data
->handle
, query
.part1
)) {
877 ("Error executing %s, %s\n", query
.part1
,
878 mysql_error(data
->handle
)));
879 return NT_STATUS_INVALID_PARAMETER
;
881 talloc_destroy(query
.mem_ctx
);
885 static NTSTATUS
mysqlsam_add_sam_account(struct pdb_methods
*methods
, SAM_ACCOUNT
* newpwd
)
887 return mysqlsam_replace_sam_account(methods
, newpwd
, 0);
890 static NTSTATUS
mysqlsam_update_sam_account(struct pdb_methods
*methods
,
891 SAM_ACCOUNT
* newpwd
)
893 return mysqlsam_replace_sam_account(methods
, newpwd
, 1);
896 static NTSTATUS
mysqlsam_getgrsid(struct pdb_methods
*methods
, GROUP_MAP
*map
,
897 DOM_SID sid
, BOOL with_priv
)
899 return get_group_map_from_sid(sid
, map
, with_priv
) ?
900 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
903 static NTSTATUS
mysqlsam_getgrgid(struct pdb_methods
*methods
, GROUP_MAP
*map
,
904 gid_t gid
, BOOL with_priv
)
906 return get_group_map_from_gid(gid
, map
, with_priv
) ?
907 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
910 static NTSTATUS
mysqlsam_getgrnam(struct pdb_methods
*methods
, GROUP_MAP
*map
,
911 char *name
, BOOL with_priv
)
913 return get_group_map_from_ntname(name
, map
, with_priv
) ?
914 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
917 static NTSTATUS
mysqlsam_add_group_mapping_entry(struct pdb_methods
*methods
,
920 return add_mapping_entry(map
, TDB_INSERT
) ?
921 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
924 static NTSTATUS
mysqlsam_update_group_mapping_entry(struct pdb_methods
*methods
,
927 return add_mapping_entry(map
, TDB_REPLACE
) ?
928 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
931 static NTSTATUS
mysqlsam_delete_group_mapping_entry(struct pdb_methods
*methods
,
934 return group_map_remove(sid
) ?
935 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
938 static NTSTATUS
mysqlsam_enum_group_mapping(struct pdb_methods
*methods
,
939 enum SID_NAME_USE sid_name_use
,
940 GROUP_MAP
**rmap
, int *num_entries
,
941 BOOL unix_only
, BOOL with_priv
)
943 return enum_group_mapping(sid_name_use
, rmap
, num_entries
, unix_only
,
945 NT_STATUS_OK
: NT_STATUS_UNSUCCESSFUL
;
949 static NTSTATUS
mysqlsam_init(struct pdb_context
* pdb_context
, struct pdb_methods
** pdb_method
,
950 const char *location
)
953 struct pdb_mysql_data
*data
;
955 mysqlsam_debug_level
= debug_add_class("mysqlsam");
956 if (mysqlsam_debug_level
== -1) {
957 mysqlsam_debug_level
= DBGC_ALL
;
959 ("mysqlsam: Couldn't register custom debugging class!\n"));
963 DEBUG(0, ("invalid pdb_methods specified\n"));
964 return NT_STATUS_UNSUCCESSFUL
;
968 (nt_status
= make_pdb_methods(pdb_context
->mem_ctx
, pdb_method
))) {
972 (*pdb_method
)->name
= "mysqlsam";
974 (*pdb_method
)->setsampwent
= mysqlsam_setsampwent
;
975 (*pdb_method
)->endsampwent
= mysqlsam_endsampwent
;
976 (*pdb_method
)->getsampwent
= mysqlsam_getsampwent
;
977 (*pdb_method
)->getsampwnam
= mysqlsam_getsampwnam
;
978 (*pdb_method
)->getsampwsid
= mysqlsam_getsampwsid
;
979 (*pdb_method
)->add_sam_account
= mysqlsam_add_sam_account
;
980 (*pdb_method
)->update_sam_account
= mysqlsam_update_sam_account
;
981 (*pdb_method
)->delete_sam_account
= mysqlsam_delete_sam_account
;
982 (*pdb_method
)->getgrsid
= mysqlsam_getgrsid
;
983 (*pdb_method
)->getgrgid
= mysqlsam_getgrgid
;
984 (*pdb_method
)->getgrnam
= mysqlsam_getgrnam
;
985 (*pdb_method
)->add_group_mapping_entry
= mysqlsam_add_group_mapping_entry
;
986 (*pdb_method
)->update_group_mapping_entry
= mysqlsam_update_group_mapping_entry
;
987 (*pdb_method
)->delete_group_mapping_entry
= mysqlsam_delete_group_mapping_entry
;
988 (*pdb_method
)->enum_group_mapping
= mysqlsam_enum_group_mapping
;
990 data
= talloc(pdb_context
->mem_ctx
, sizeof(struct pdb_mysql_data
));
991 (*pdb_method
)->private_data
= data
;
996 DEBUG(0, ("No identifier specified. See README for details\n"));
997 return NT_STATUS_INVALID_PARAMETER
;
1000 data
->location
= smb_xstrdup(location
);
1003 ("Connecting to database server, host: %s, user: %s, password: %s, database: %s, port: %ld\n",
1004 config_value(data
, "mysql host", CONFIG_HOST_DEFAULT
),
1005 config_value(data
, "mysql user", CONFIG_USER_DEFAULT
),
1006 config_value(data
, "mysql password", CONFIG_PASS_DEFAULT
),
1007 config_value(data
, "mysql database", CONFIG_DB_DEFAULT
),
1008 xatol(config_value(data
, "mysql port", CONFIG_PORT_DEFAULT
))));
1010 /* Do the mysql initialization */
1011 data
->handle
= mysql_init(NULL
);
1012 if (!data
->handle
) {
1013 DEBUG(0, ("Failed to connect to server\n"));
1014 return NT_STATUS_UNSUCCESSFUL
;
1016 /* Process correct entry in $HOME/.my.conf */
1017 if (!mysql_real_connect(data
->handle
,
1018 config_value(data
, "mysql host", CONFIG_HOST_DEFAULT
),
1019 config_value(data
, "mysql user", CONFIG_USER_DEFAULT
),
1020 config_value(data
, "mysql password", CONFIG_PASS_DEFAULT
),
1021 config_value(data
, "mysql database", CONFIG_DB_DEFAULT
),
1022 xatol(config_value (data
, "mysql port", CONFIG_PORT_DEFAULT
)),
1025 ("Failed to connect to mysql database: error: %s\n",
1026 mysql_error(data
->handle
)));
1027 return NT_STATUS_UNSUCCESSFUL
;
1030 DEBUG(5, ("Connected to mysql db\n"));
1032 return NT_STATUS_OK
;
1035 int init_module(void);
1039 if(smb_register_passdb("mysql", mysqlsam_init
, PASSDB_INTERFACE_VERSION
))