More code to store ACEs and SIDs. I have almost enough to start testing
[Samba/gebeck_regimport.git] / source3 / passdb / pdb_mysql.c
blob4e91994418c3916cafc4166b379223aab243746f
2 /*
3 * MySQL password backend for samba
4 * Copyright (C) Jelmer Vernooij 2002
5 *
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)
9 * any later version.
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
14 * more details.
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.
21 #include "includes.h"
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_USER_SID_DEFAULT "user_sid"
44 #define CONFIG_GROUP_SID_DEFAULT "group_sid"
45 #define CONFIG_LM_PW_DEFAULT "lm_pw"
46 #define CONFIG_NT_PW_DEFAULT "nt_pw"
47 #define CONFIG_PLAIN_PW_DEFAULT "NULL"
48 #define CONFIG_ACCT_CTRL_DEFAULT "acct_ctrl"
49 #define CONFIG_UNKNOWN_3_DEFAULT "unknown_3"
50 #define CONFIG_LOGON_DIVS_DEFAULT "logon_divs"
51 #define CONFIG_HOURS_LEN_DEFAULT "hours_len"
52 #define CONFIG_UNKNOWN_5_DEFAULT "unknown_5"
53 #define CONFIG_UNKNOWN_6_DEFAULT "unknown_6"
54 #define CONFIG_HOST_DEFAULT "localhost"
55 #define CONFIG_USER_DEFAULT "samba"
56 #define CONFIG_PASS_DEFAULT ""
57 #define CONFIG_PORT_DEFAULT "3306"
58 #define CONFIG_DB_DEFAULT "samba"
60 static int mysqlsam_debug_level = DBGC_ALL;
62 #undef DBGC_CLASS
63 #define DBGC_CLASS mysqlsam_debug_level
65 typedef struct pdb_mysql_data {
66 MYSQL *handle;
67 MYSQL_RES *pwent;
68 const char *location;
69 } pdb_mysql_data;
71 /* Used to construct insert and update queries */
73 typedef struct pdb_mysql_query {
74 char update;
75 TALLOC_CTX *mem_ctx;
76 char *part1;
77 char *part2;
78 } pdb_mysql_query;
79 #define SET_DATA(data,methods) { \
80 if(!methods){ \
81 DEBUG(0, ("invalid methods!\n")); \
82 return NT_STATUS_INVALID_PARAMETER; \
83 } \
84 data = (struct pdb_mysql_data *)methods->private_data; \
85 if(!data || !(data->handle)){ \
86 DEBUG(0, ("invalid handle!\n")); \
87 return NT_STATUS_INVALID_HANDLE; \
88 } \
91 static void pdb_mysql_int_field(struct pdb_methods *m,
92 struct pdb_mysql_query *q, const char *name, int value)
94 if (!name || strchr(name, '\''))
95 return; /* This field shouldn't be set by us */
97 if (q->update) {
98 q->part1 =
99 talloc_asprintf_append(q->mem_ctx, q->part1,
100 "%s = %d,", name, value);
101 } else {
102 q->part1 =
103 talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name);
104 q->part2 =
105 talloc_asprintf_append(q->mem_ctx, q->part2, "%d,", value);
109 static NTSTATUS pdb_mysql_string_field(struct pdb_methods *methods,
110 struct pdb_mysql_query *q,
111 const char *name, const char *value)
113 char *esc_value;
114 struct pdb_mysql_data *data;
115 char *tmp_value;
117 SET_DATA(data, methods);
119 if (!name || !value || !strcmp(value, "") || strchr(name, '\''))
120 return NT_STATUS_INVALID_PARAMETER; /* This field shouldn't be set by module */
122 esc_value = malloc(strlen(value) * 2 + 1);
124 tmp_value = smb_xstrdup(value);
125 mysql_real_escape_string(data->handle, esc_value, tmp_value,
126 strlen(tmp_value));
127 SAFE_FREE(tmp_value);
129 if (q->update) {
130 q->part1 =
131 talloc_asprintf_append(q->mem_ctx, q->part1,
132 "%s = '%s',", name, esc_value);
133 } else {
134 q->part1 =
135 talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name);
136 q->part2 =
137 talloc_asprintf_append(q->mem_ctx, q->part2, "'%s',",
138 esc_value);
141 SAFE_FREE(esc_value);
143 return NT_STATUS_OK;
146 #define config_value(data,name,default_value) \
147 lp_parm_const_string(GLOBAL_SECTION_SNUM, (data)->location, name, default_value)
149 static const char * config_value_write(pdb_mysql_data * data, const char *name, const char *default_value) {
150 char const *v = NULL;
151 char const *swrite = NULL;
153 v = lp_parm_const_string(GLOBAL_SECTION_SNUM, data->location, name, default_value);
155 if (!v)
156 return NULL;
158 swrite = strchr(v, ':');
160 /* Default to the same field as read field */
161 if (!swrite)
162 return v;
164 swrite++;
166 /* If the field is 0 chars long, we shouldn't write to it */
167 if (!strlen(swrite) || !strcmp(swrite, "NULL"))
168 return NULL;
170 /* Otherwise, use the additionally specified */
171 return swrite;
174 static const char * config_value_read(pdb_mysql_data * data, const char *name, const char *default_value)
176 char *v = NULL;
177 char *swrite;
179 v = lp_parm_talloc_string(GLOBAL_SECTION_SNUM, data->location, name, default_value);
181 if (!v)
182 return "NULL";
184 swrite = strchr(v, ':');
186 /* If no write is specified, there are no problems */
187 if (!swrite) {
188 if (strlen(v) == 0)
189 return "NULL";
190 return (const char *)v;
193 /* Otherwise, we have to cut the ':write_part' */
194 *swrite = '\0';
195 if (strlen(v) == 0)
196 return "NULL";
198 return (const char *)v;
201 /* Wrapper for atol that returns 0 if 'a' points to NULL */
202 static long xatol(const char *a)
204 long ret = 0;
206 if (a != NULL)
207 ret = atol(a);
209 return ret;
212 static NTSTATUS row_to_sam_account(MYSQL_RES * r, SAM_ACCOUNT * u)
214 MYSQL_ROW row;
215 pstring temp;
216 unsigned int num_fields;
217 DOM_SID sid;
219 num_fields = mysql_num_fields(r);
220 row = mysql_fetch_row(r);
221 if (!row)
222 return NT_STATUS_INVALID_PARAMETER;
224 pdb_set_logon_time(u, xatol(row[0]), PDB_SET);
225 pdb_set_logoff_time(u, xatol(row[1]), PDB_SET);
226 pdb_set_kickoff_time(u, xatol(row[2]), PDB_SET);
227 pdb_set_pass_last_set_time(u, xatol(row[3]), PDB_SET);
228 pdb_set_pass_can_change_time(u, xatol(row[4]), PDB_SET);
229 pdb_set_pass_must_change_time(u, xatol(row[5]), PDB_SET);
230 pdb_set_username(u, row[6], PDB_SET);
231 pdb_set_domain(u, row[7], PDB_SET);
232 pdb_set_nt_username(u, row[8], PDB_SET);
233 pdb_set_fullname(u, row[9], PDB_SET);
234 pdb_set_homedir(u, row[10], PDB_SET);
235 pdb_set_dir_drive(u, row[11], PDB_SET);
236 pdb_set_logon_script(u, row[12], PDB_SET);
237 pdb_set_profile_path(u, row[13], PDB_SET);
238 pdb_set_acct_desc(u, row[14], PDB_SET);
239 pdb_set_workstations(u, row[15], PDB_SET);
240 pdb_set_unknown_str(u, row[16], PDB_SET);
241 pdb_set_munged_dial(u, row[17], PDB_SET);
243 string_to_sid(&sid, row[18]);
244 pdb_set_user_sid(u, &sid, PDB_SET);
245 string_to_sid(&sid, row[19]);
246 pdb_set_group_sid(u, &sid, PDB_SET);
248 if (pdb_gethexpwd(row[20], temp), PDB_SET)
249 pdb_set_lanman_passwd(u, temp, PDB_SET);
250 if (pdb_gethexpwd(row[21], temp), PDB_SET)
251 pdb_set_nt_passwd(u, temp, PDB_SET);
253 /* Only use plaintext password storage when lanman and nt are
254 * NOT used */
255 if (!row[20] || !row[21])
256 pdb_set_plaintext_passwd(u, row[22]);
258 pdb_set_acct_ctrl(u, xatol(row[23]), PDB_SET);
259 pdb_set_unknown_3(u, xatol(row[24]), PDB_SET);
260 pdb_set_logon_divs(u, xatol(row[25]), PDB_SET);
261 pdb_set_hours_len(u, xatol(row[26]), PDB_SET);
262 pdb_set_unknown_5(u, xatol(row[27]), PDB_SET);
263 pdb_set_unknown_6(u, xatol(row[28]), PDB_SET);
265 return NT_STATUS_OK;
268 static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update)
270 struct pdb_mysql_data *data =
271 (struct pdb_mysql_data *) methods->private_data;
272 char *query;
273 int ret;
275 if (!data || !(data->handle)) {
276 DEBUG(0, ("invalid handle!\n"));
277 return NT_STATUS_INVALID_HANDLE;
280 asprintf(&query,
281 "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 FROM %s",
282 config_value_read(data, "logon time column",
283 CONFIG_LOGON_TIME_DEFAULT),
284 config_value_read(data, "logoff time column",
285 CONFIG_LOGOFF_TIME_DEFAULT),
286 config_value_read(data, "kickoff time column",
287 CONFIG_KICKOFF_TIME_DEFAULT),
288 config_value_read(data, "pass last set time column",
289 CONFIG_PASS_LAST_SET_TIME_DEFAULT),
290 config_value_read(data, "pass can change time column",
291 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
292 config_value_read(data, "pass must change time column",
293 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
294 config_value_read(data, "username column",
295 CONFIG_USERNAME_DEFAULT),
296 config_value_read(data, "domain column",
297 CONFIG_DOMAIN_DEFAULT),
298 config_value_read(data, "nt username column",
299 CONFIG_NT_USERNAME_DEFAULT),
300 config_value_read(data, "fullname column",
301 CONFIG_FULLNAME_DEFAULT),
302 config_value_read(data, "home dir column",
303 CONFIG_HOME_DIR_DEFAULT),
304 config_value_read(data, "dir drive column",
305 CONFIG_DIR_DRIVE_DEFAULT),
306 config_value_read(data, "logon script column",
307 CONFIG_LOGON_SCRIPT_DEFAULT),
308 config_value_read(data, "profile path column",
309 CONFIG_PROFILE_PATH_DEFAULT),
310 config_value_read(data, "acct desc column",
311 CONFIG_ACCT_DESC_DEFAULT),
312 config_value_read(data, "workstations column",
313 CONFIG_WORKSTATIONS_DEFAULT),
314 config_value_read(data, "unknown string column",
315 CONFIG_UNKNOWN_STR_DEFAULT),
316 config_value_read(data, "munged dial column",
317 CONFIG_MUNGED_DIAL_DEFAULT),
318 config_value_read(data, "user sid column",
319 CONFIG_USER_SID_DEFAULT),
320 config_value_read(data, "group sid column",
321 CONFIG_GROUP_SID_DEFAULT),
322 config_value_read(data, "lanman pass column",
323 CONFIG_LM_PW_DEFAULT),
324 config_value_read(data, "nt pass column",
325 CONFIG_NT_PW_DEFAULT),
326 config_value_read(data, "plain pass column",
327 CONFIG_PLAIN_PW_DEFAULT),
328 config_value_read(data, "acct ctrl column",
329 CONFIG_ACCT_CTRL_DEFAULT),
330 config_value_read(data, "unknown 3 column",
331 CONFIG_UNKNOWN_3_DEFAULT),
332 config_value_read(data, "logon divs column",
333 CONFIG_LOGON_DIVS_DEFAULT),
334 config_value_read(data, "hours len column",
335 CONFIG_HOURS_LEN_DEFAULT),
336 config_value_read(data, "unknown 5 column",
337 CONFIG_UNKNOWN_5_DEFAULT),
338 config_value_read(data, "unknown 6 column",
339 CONFIG_UNKNOWN_6_DEFAULT),
340 config_value(data, "table", CONFIG_TABLE_DEFAULT)
342 DEBUG(5, ("Executing query %s\n", query));
344 ret = mysql_query(data->handle, query);
345 SAFE_FREE(query);
347 if (ret) {
348 DEBUG(0,
349 ("Error executing MySQL query %s\n", mysql_error(data->handle)));
350 return NT_STATUS_UNSUCCESSFUL;
353 data->pwent = mysql_store_result(data->handle);
355 if (data->pwent == NULL) {
356 DEBUG(0,
357 ("Error storing results: %s\n", mysql_error(data->handle)));
358 return NT_STATUS_UNSUCCESSFUL;
361 DEBUG(5,
362 ("mysqlsam_setsampwent succeeded(%llu results)!\n",
363 mysql_num_rows(data->pwent)));
365 return NT_STATUS_OK;
368 /***************************************************************
369 End enumeration of the passwd list.
370 ****************************************************************/
372 static void mysqlsam_endsampwent(struct pdb_methods *methods)
374 struct pdb_mysql_data *data =
375 (struct pdb_mysql_data *) methods->private_data;
377 if (data == NULL) {
378 DEBUG(0, ("invalid handle!\n"));
379 return;
382 if (data->pwent != NULL)
383 mysql_free_result(data->pwent);
385 data->pwent = NULL;
387 DEBUG(5, ("mysql_endsampwent called\n"));
390 /*****************************************************************
391 Get one SAM_ACCOUNT from the list (next in line)
392 *****************************************************************/
394 static NTSTATUS mysqlsam_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT * user)
396 struct pdb_mysql_data *data;
398 SET_DATA(data, methods);
400 if (data->pwent == NULL) {
401 DEBUG(0, ("invalid pwent\n"));
402 return NT_STATUS_INVALID_PARAMETER;
405 return row_to_sam_account(data->pwent, user);
408 static NTSTATUS mysqlsam_select_by_field(struct pdb_methods * methods, SAM_ACCOUNT * user,
409 const char *field, const char *sname)
411 char *esc_sname;
412 char *query;
413 NTSTATUS ret;
414 MYSQL_RES *res;
415 int mysql_ret;
416 struct pdb_mysql_data *data;
417 char *tmp_sname;
419 SET_DATA(data, methods);
421 esc_sname = malloc(strlen(sname) * 2 + 1);
422 if (!esc_sname) {
423 return NT_STATUS_NO_MEMORY;
426 DEBUG(5,
427 ("mysqlsam_select_by_field: getting data where %s = %s(nonescaped)\n",
428 field, sname));
430 tmp_sname = smb_xstrdup(sname);
432 /* Escape sname */
433 mysql_real_escape_string(data->handle, esc_sname, tmp_sname,
434 strlen(tmp_sname));
436 SAFE_FREE(tmp_sname);
438 if (user == NULL) {
439 DEBUG(0, ("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
440 SAFE_FREE(esc_sname);
441 return NT_STATUS_INVALID_PARAMETER;
444 asprintf(&query,
445 "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'",
446 config_value_read(data, "logon time column",
447 CONFIG_LOGON_TIME_DEFAULT),
448 config_value_read(data, "logoff time column",
449 CONFIG_LOGOFF_TIME_DEFAULT),
450 config_value_read(data, "kickoff time column",
451 CONFIG_KICKOFF_TIME_DEFAULT),
452 config_value_read(data, "pass last set time column",
453 CONFIG_PASS_LAST_SET_TIME_DEFAULT),
454 config_value_read(data, "pass can change time column",
455 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
456 config_value_read(data, "pass must change time column",
457 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
458 config_value_read(data, "username column",
459 CONFIG_USERNAME_DEFAULT),
460 config_value_read(data, "domain column",
461 CONFIG_DOMAIN_DEFAULT),
462 config_value_read(data, "nt username column",
463 CONFIG_NT_USERNAME_DEFAULT),
464 config_value_read(data, "fullname column",
465 CONFIG_FULLNAME_DEFAULT),
466 config_value_read(data, "home dir column",
467 CONFIG_HOME_DIR_DEFAULT),
468 config_value_read(data, "dir drive column",
469 CONFIG_DIR_DRIVE_DEFAULT),
470 config_value_read(data, "logon script column",
471 CONFIG_LOGON_SCRIPT_DEFAULT),
472 config_value_read(data, "profile path column",
473 CONFIG_PROFILE_PATH_DEFAULT),
474 config_value_read(data, "acct desc column",
475 CONFIG_ACCT_DESC_DEFAULT),
476 config_value_read(data, "workstations column",
477 CONFIG_WORKSTATIONS_DEFAULT),
478 config_value_read(data, "unknown string column",
479 CONFIG_UNKNOWN_STR_DEFAULT),
480 config_value_read(data, "munged dial column",
481 CONFIG_MUNGED_DIAL_DEFAULT),
482 config_value_read(data, "user sid column",
483 CONFIG_USER_SID_DEFAULT),
484 config_value_read(data, "group sid column",
485 CONFIG_GROUP_SID_DEFAULT),
486 config_value_read(data, "lanman pass column",
487 CONFIG_LM_PW_DEFAULT),
488 config_value_read(data, "nt pass column",
489 CONFIG_NT_PW_DEFAULT),
490 config_value_read(data, "plain pass column",
491 CONFIG_PLAIN_PW_DEFAULT),
492 config_value_read(data, "acct ctrl column",
493 CONFIG_ACCT_CTRL_DEFAULT),
494 config_value_read(data, "unknown 3 column",
495 CONFIG_UNKNOWN_3_DEFAULT),
496 config_value_read(data, "logon divs column",
497 CONFIG_LOGON_DIVS_DEFAULT),
498 config_value_read(data, "hours len column",
499 CONFIG_HOURS_LEN_DEFAULT),
500 config_value_read(data, "unknown 5 column",
501 CONFIG_UNKNOWN_5_DEFAULT),
502 config_value_read(data, "unknown 6 column",
503 CONFIG_UNKNOWN_6_DEFAULT),
504 config_value(data, "table", CONFIG_TABLE_DEFAULT), field,
505 esc_sname);
507 SAFE_FREE(esc_sname);
509 DEBUG(5, ("Executing query %s\n", query));
511 mysql_ret = mysql_query(data->handle, query);
513 SAFE_FREE(query);
515 if (mysql_ret) {
516 DEBUG(0,
517 ("Error while executing MySQL query %s\n",
518 mysql_error(data->handle)));
519 return NT_STATUS_UNSUCCESSFUL;
522 res = mysql_store_result(data->handle);
523 if (res == NULL) {
524 DEBUG(0,
525 ("Error storing results: %s\n", mysql_error(data->handle)));
526 return NT_STATUS_UNSUCCESSFUL;
529 ret = row_to_sam_account(res, user);
530 mysql_free_result(res);
532 return ret;
535 /******************************************************************
536 Lookup a name in the SAM database
537 ******************************************************************/
539 static NTSTATUS mysqlsam_getsampwnam(struct pdb_methods *methods, SAM_ACCOUNT * user,
540 const char *sname)
542 struct pdb_mysql_data *data;
544 SET_DATA(data, methods);
546 if (!sname) {
547 DEBUG(0, ("invalid name specified"));
548 return NT_STATUS_INVALID_PARAMETER;
551 return mysqlsam_select_by_field(methods, user,
552 config_value_read(data, "username column",
553 CONFIG_USERNAME_DEFAULT), sname);
557 /***************************************************************************
558 Search by sid
559 **************************************************************************/
561 static NTSTATUS mysqlsam_getsampwsid(struct pdb_methods *methods, SAM_ACCOUNT * user,
562 const DOM_SID * sid)
564 struct pdb_mysql_data *data;
565 fstring sid_str;
567 SET_DATA(data, methods);
569 sid_to_string(sid_str, sid);
571 return mysqlsam_select_by_field(methods, user,
572 config_value_read(data, "user sid column",
573 CONFIG_USER_SID_DEFAULT), sid_str);
576 /***************************************************************************
577 Delete a SAM_ACCOUNT
578 ****************************************************************************/
580 static NTSTATUS mysqlsam_delete_sam_account(struct pdb_methods *methods,
581 SAM_ACCOUNT * sam_pass)
583 const char *sname = pdb_get_username(sam_pass);
584 char *esc;
585 char *query;
586 int ret;
587 struct pdb_mysql_data *data;
588 char *tmp_sname;
590 SET_DATA(data, methods);
592 if (!methods) {
593 DEBUG(0, ("invalid methods!\n"));
594 return NT_STATUS_INVALID_PARAMETER;
597 data = (struct pdb_mysql_data *) methods->private_data;
598 if (!data || !(data->handle)) {
599 DEBUG(0, ("invalid handle!\n"));
600 return NT_STATUS_INVALID_HANDLE;
603 if (!sname) {
604 DEBUG(0, ("invalid name specified\n"));
605 return NT_STATUS_INVALID_PARAMETER;
608 /* Escape sname */
609 esc = malloc(strlen(sname) * 2 + 1);
610 if (!esc) {
611 DEBUG(0, ("Can't allocate memory to store escaped name\n"));
612 return NT_STATUS_NO_MEMORY;
615 tmp_sname = smb_xstrdup(sname);
617 mysql_real_escape_string(data->handle, esc, tmp_sname,
618 strlen(tmp_sname));
620 SAFE_FREE(tmp_sname);
622 asprintf(&query, "DELETE FROM %s WHERE %s = '%s'",
623 config_value(data, "table", CONFIG_TABLE_DEFAULT),
624 config_value_read(data, "username column",
625 CONFIG_USERNAME_DEFAULT), esc);
627 SAFE_FREE(esc);
629 ret = mysql_query(data->handle, query);
631 SAFE_FREE(query);
633 if (ret) {
634 DEBUG(0,
635 ("Error while executing query: %s\n",
636 mysql_error(data->handle)));
637 return NT_STATUS_UNSUCCESSFUL;
640 DEBUG(5, ("User '%s' deleted\n", sname));
641 return NT_STATUS_OK;
644 static NTSTATUS mysqlsam_replace_sam_account(struct pdb_methods *methods,
645 const SAM_ACCOUNT * newpwd, char isupdate)
647 pstring temp;
648 struct pdb_mysql_data *data;
649 pdb_mysql_query query;
650 fstring sid_str;
652 if (!methods) {
653 DEBUG(0, ("invalid methods!\n"));
654 return NT_STATUS_INVALID_PARAMETER;
657 data = (struct pdb_mysql_data *) methods->private_data;
658 if (data == NULL || data->handle == NULL) {
659 DEBUG(0, ("invalid handle!\n"));
660 return NT_STATUS_INVALID_HANDLE;
662 query.update = isupdate;
664 /* I know this is somewhat overkill but only the talloc
665 * functions have asprint_append and the 'normal' asprintf
666 * is a GNU extension */
667 query.mem_ctx = talloc_init("mysqlsam_replace_sam_account");
668 query.part2 = talloc_asprintf(query.mem_ctx, "%s", "");
669 if (query.update) {
670 query.part1 =
671 talloc_asprintf(query.mem_ctx, "UPDATE %s SET ",
672 config_value(data, "table",
673 CONFIG_TABLE_DEFAULT));
674 } else {
675 query.part1 =
676 talloc_asprintf(query.mem_ctx, "INSERT INTO %s (",
677 config_value(data, "table",
678 CONFIG_TABLE_DEFAULT));
681 pdb_mysql_int_field(methods, &query,
682 config_value_write(data, "acct ctrl column",
683 CONFIG_ACCT_CTRL_DEFAULT),
684 pdb_get_acct_ctrl(newpwd));
686 if (pdb_get_init_flags(newpwd, PDB_LOGONTIME) != PDB_DEFAULT) {
687 pdb_mysql_int_field(methods, &query,
688 config_value_write(data,
689 "logon time column",
690 CONFIG_LOGON_TIME_DEFAULT),
691 pdb_get_logon_time(newpwd));
694 if (pdb_get_init_flags(newpwd, PDB_LOGOFFTIME) != PDB_DEFAULT) {
695 pdb_mysql_int_field(methods, &query,
696 config_value_write(data,
697 "logoff time column",
698 CONFIG_LOGOFF_TIME_DEFAULT),
699 pdb_get_logoff_time(newpwd));
702 if (pdb_get_init_flags(newpwd, PDB_KICKOFFTIME) != PDB_DEFAULT) {
703 pdb_mysql_int_field(methods, &query,
704 config_value_write(data,
705 "kickoff time column",
706 CONFIG_KICKOFF_TIME_DEFAULT),
707 pdb_get_kickoff_time(newpwd));
710 if (pdb_get_init_flags(newpwd, PDB_CANCHANGETIME) != PDB_DEFAULT) {
711 pdb_mysql_int_field(methods, &query,
712 config_value_write(data,
713 "pass can change time column",
714 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
715 pdb_get_pass_can_change_time(newpwd));
718 if (pdb_get_init_flags(newpwd, PDB_MUSTCHANGETIME) != PDB_DEFAULT) {
719 pdb_mysql_int_field(methods, &query,
720 config_value_write(data,
721 "pass must change time column",
722 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
723 pdb_get_pass_must_change_time(newpwd));
726 if (pdb_get_pass_last_set_time(newpwd)) {
727 pdb_mysql_int_field(methods, &query,
728 config_value_write(data,
729 "pass last set time column",
730 CONFIG_PASS_LAST_SET_TIME_DEFAULT),
731 pdb_get_pass_last_set_time(newpwd));
734 if (pdb_get_hours_len(newpwd)) {
735 pdb_mysql_int_field(methods, &query,
736 config_value_write(data,
737 "hours len column",
738 CONFIG_HOURS_LEN_DEFAULT),
739 pdb_get_hours_len(newpwd));
742 if (pdb_get_logon_divs(newpwd)) {
743 pdb_mysql_int_field(methods, &query,
744 config_value_write(data,
745 "logon divs column",
746 CONFIG_LOGON_DIVS_DEFAULT),
747 pdb_get_logon_divs(newpwd));
750 pdb_mysql_string_field(methods, &query,
751 config_value_write(data, "user sid column",
752 CONFIG_USER_SID_DEFAULT),
753 sid_to_string(sid_str,
754 pdb_get_user_sid(newpwd)));
756 pdb_mysql_string_field(methods, &query,
757 config_value_write(data, "group sid column",
758 CONFIG_GROUP_SID_DEFAULT),
759 sid_to_string(sid_str,
760 pdb_get_group_sid(newpwd)));
762 pdb_mysql_string_field(methods, &query,
763 config_value_write(data, "username column",
764 CONFIG_USERNAME_DEFAULT),
765 pdb_get_username(newpwd));
767 pdb_mysql_string_field(methods, &query,
768 config_value_write(data, "domain column",
769 CONFIG_DOMAIN_DEFAULT),
770 pdb_get_domain(newpwd));
772 pdb_mysql_string_field(methods, &query,
773 config_value_write(data,
774 "nt username column",
775 CONFIG_NT_USERNAME_DEFAULT),
776 pdb_get_nt_username(newpwd));
778 pdb_mysql_string_field(methods, &query,
779 config_value_write(data, "fullname column",
780 CONFIG_FULLNAME_DEFAULT),
781 pdb_get_fullname(newpwd));
783 pdb_mysql_string_field(methods, &query,
784 config_value_write(data,
785 "logon script column",
786 CONFIG_LOGON_SCRIPT_DEFAULT),
787 pdb_get_logon_script(newpwd));
789 pdb_mysql_string_field(methods, &query,
790 config_value_write(data,
791 "profile path column",
792 CONFIG_PROFILE_PATH_DEFAULT),
793 pdb_get_profile_path(newpwd));
795 pdb_mysql_string_field(methods, &query,
796 config_value_write(data, "dir drive column",
797 CONFIG_DIR_DRIVE_DEFAULT),
798 pdb_get_dir_drive(newpwd));
800 pdb_mysql_string_field(methods, &query,
801 config_value_write(data, "home dir column",
802 CONFIG_HOME_DIR_DEFAULT),
803 pdb_get_homedir(newpwd));
805 pdb_mysql_string_field(methods, &query,
806 config_value_write(data,
807 "workstations column",
808 CONFIG_WORKSTATIONS_DEFAULT),
809 pdb_get_workstations(newpwd));
811 pdb_mysql_string_field(methods, &query,
812 config_value_write(data,
813 "unknown string column",
814 CONFIG_UNKNOWN_STR_DEFAULT),
815 pdb_get_workstations(newpwd));
817 pdb_sethexpwd(temp, pdb_get_lanman_passwd(newpwd),
818 pdb_get_acct_ctrl(newpwd));
819 pdb_mysql_string_field(methods, &query,
820 config_value_write(data,
821 "lanman pass column",
822 CONFIG_LM_PW_DEFAULT), temp);
824 pdb_sethexpwd(temp, pdb_get_nt_passwd(newpwd),
825 pdb_get_acct_ctrl(newpwd));
826 pdb_mysql_string_field(methods, &query,
827 config_value_write(data, "nt pass column",
828 CONFIG_NT_PW_DEFAULT), temp);
830 if (query.update) {
831 query.part1[strlen(query.part1) - 1] = '\0';
832 query.part1 =
833 talloc_asprintf_append(query.mem_ctx, query.part1,
834 " WHERE %s = '%s'",
835 config_value_read(data,
836 "user sid column",
837 CONFIG_USER_SID_DEFAULT),
838 sid_to_string(sid_str, pdb_get_user_sid (newpwd)));
839 } else {
840 query.part2[strlen(query.part2) - 1] = ')';
841 query.part1[strlen(query.part1) - 1] = ')';
842 query.part1 =
843 talloc_asprintf_append(query.mem_ctx, query.part1,
844 " VALUES (%s", query.part2);
847 DEBUG(0, ("%s\n", query.part1));
848 /* Execute the query */
849 if (mysql_query(data->handle, query.part1)) {
850 DEBUG(0,
851 ("Error executing %s, %s\n", query.part1,
852 mysql_error(data->handle)));
853 return NT_STATUS_INVALID_PARAMETER;
855 talloc_destroy(query.mem_ctx);
856 return NT_STATUS_OK;
859 static NTSTATUS mysqlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT * newpwd)
861 return mysqlsam_replace_sam_account(methods, newpwd, 0);
864 static NTSTATUS mysqlsam_update_sam_account(struct pdb_methods *methods,
865 SAM_ACCOUNT * newpwd)
867 return mysqlsam_replace_sam_account(methods, newpwd, 1);
870 static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_methods ** pdb_method,
871 const char *location)
873 NTSTATUS nt_status;
874 struct pdb_mysql_data *data;
876 mysqlsam_debug_level = debug_add_class("mysqlsam");
877 if (mysqlsam_debug_level == -1) {
878 mysqlsam_debug_level = DBGC_ALL;
879 DEBUG(0,
880 ("mysqlsam: Couldn't register custom debugging class!\n"));
883 if (!pdb_context) {
884 DEBUG(0, ("invalid pdb_methods specified\n"));
885 return NT_STATUS_UNSUCCESSFUL;
888 if (!NT_STATUS_IS_OK
889 (nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
890 return nt_status;
893 (*pdb_method)->name = "mysqlsam";
895 (*pdb_method)->setsampwent = mysqlsam_setsampwent;
896 (*pdb_method)->endsampwent = mysqlsam_endsampwent;
897 (*pdb_method)->getsampwent = mysqlsam_getsampwent;
898 (*pdb_method)->getsampwnam = mysqlsam_getsampwnam;
899 (*pdb_method)->getsampwsid = mysqlsam_getsampwsid;
900 (*pdb_method)->add_sam_account = mysqlsam_add_sam_account;
901 (*pdb_method)->update_sam_account = mysqlsam_update_sam_account;
902 (*pdb_method)->delete_sam_account = mysqlsam_delete_sam_account;
904 data = talloc(pdb_context->mem_ctx, sizeof(struct pdb_mysql_data));
905 (*pdb_method)->private_data = data;
906 data->handle = NULL;
907 data->pwent = NULL;
909 if (!location) {
910 DEBUG(0, ("No identifier specified. Check the Samba HOWTO Collection for details\n"));
911 return NT_STATUS_INVALID_PARAMETER;
914 data->location = smb_xstrdup(location);
916 DEBUG(1,
917 ("Connecting to database server, host: %s, user: %s, password: %s, database: %s, port: %ld\n",
918 config_value(data, "mysql host", CONFIG_HOST_DEFAULT),
919 config_value(data, "mysql user", CONFIG_USER_DEFAULT),
920 config_value(data, "mysql password", CONFIG_PASS_DEFAULT),
921 config_value(data, "mysql database", CONFIG_DB_DEFAULT),
922 xatol(config_value(data, "mysql port", CONFIG_PORT_DEFAULT))));
924 /* Do the mysql initialization */
925 data->handle = mysql_init(NULL);
926 if (!data->handle) {
927 DEBUG(0, ("Failed to connect to server\n"));
928 return NT_STATUS_UNSUCCESSFUL;
930 /* Process correct entry in $HOME/.my.conf */
931 if (!mysql_real_connect(data->handle,
932 config_value(data, "mysql host", CONFIG_HOST_DEFAULT),
933 config_value(data, "mysql user", CONFIG_USER_DEFAULT),
934 config_value(data, "mysql password", CONFIG_PASS_DEFAULT),
935 config_value(data, "mysql database", CONFIG_DB_DEFAULT),
936 xatol(config_value (data, "mysql port", CONFIG_PORT_DEFAULT)),
937 NULL, 0)) {
938 DEBUG(0,
939 ("Failed to connect to mysql database: error: %s\n",
940 mysql_error(data->handle)));
941 return NT_STATUS_UNSUCCESSFUL;
944 DEBUG(5, ("Connected to mysql db\n"));
946 return NT_STATUS_OK;
949 int pdb_mysql_init(void)
951 return smb_register_passdb("mysql", mysqlsam_init, PASSDB_INTERFACE_VERSION);