Fix pdb_mysql. Jelmer will look into details tonight.
[Samba/gebeck_regimport.git] / source3 / passdb / pdb_mysql.c
blob9004c97716ff47482a1c2ba9c4f1dd5adfcba192
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_BAD_PASSWORD_COUNT_DEFAULT "bad_password_count"
53 #define CONFIG_LOGON_COUNT_DEFAULT "logon_count"
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;
63 #undef DBGC_CLASS
64 #define DBGC_CLASS mysqlsam_debug_level
66 typedef struct pdb_mysql_data {
67 MYSQL *handle;
68 MYSQL_RES *pwent;
69 const char *location;
70 } pdb_mysql_data;
72 /* Used to construct insert and update queries */
74 typedef struct pdb_mysql_query {
75 char update;
76 TALLOC_CTX *mem_ctx;
77 char *part1;
78 char *part2;
79 } pdb_mysql_query;
80 #define SET_DATA(data,methods) { \
81 if(!methods){ \
82 DEBUG(0, ("invalid methods!\n")); \
83 return NT_STATUS_INVALID_PARAMETER; \
84 } \
85 data = (struct pdb_mysql_data *)methods->private_data; \
86 if(!data || !(data->handle)){ \
87 DEBUG(0, ("invalid handle!\n")); \
88 return NT_STATUS_INVALID_HANDLE; \
89 } \
92 static void pdb_mysql_int_field(struct pdb_methods *m,
93 struct pdb_mysql_query *q, const char *name, int value)
95 if (!name || strchr(name, '\''))
96 return; /* This field shouldn't be set by us */
98 if (q->update) {
99 q->part1 =
100 talloc_asprintf_append(q->mem_ctx, q->part1,
101 "%s = %d,", name, value);
102 } else {
103 q->part1 =
104 talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name);
105 q->part2 =
106 talloc_asprintf_append(q->mem_ctx, q->part2, "%d,", value);
110 static NTSTATUS pdb_mysql_string_field(struct pdb_methods *methods,
111 struct pdb_mysql_query *q,
112 const char *name, const char *value)
114 char *esc_value;
115 struct pdb_mysql_data *data;
116 char *tmp_value;
118 SET_DATA(data, methods);
120 if (!name || !value || !strcmp(value, "") || strchr(name, '\''))
121 return NT_STATUS_INVALID_PARAMETER; /* This field shouldn't be set by module */
123 esc_value = malloc(strlen(value) * 2 + 1);
125 tmp_value = smb_xstrdup(value);
126 mysql_real_escape_string(data->handle, esc_value, tmp_value,
127 strlen(tmp_value));
128 SAFE_FREE(tmp_value);
130 if (q->update) {
131 q->part1 =
132 talloc_asprintf_append(q->mem_ctx, q->part1,
133 "%s = '%s',", name, esc_value);
134 } else {
135 q->part1 =
136 talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name);
137 q->part2 =
138 talloc_asprintf_append(q->mem_ctx, q->part2, "'%s',",
139 esc_value);
142 SAFE_FREE(esc_value);
144 return NT_STATUS_OK;
147 #define config_value(data,name,default_value) \
148 lp_parm_const_string(GLOBAL_SECTION_SNUM, (data)->location, name, default_value)
150 static const char * config_value_write(pdb_mysql_data * data, const char *name, const char *default_value) {
151 char const *v = NULL;
152 char const *swrite = NULL;
154 v = lp_parm_const_string(GLOBAL_SECTION_SNUM, data->location, name, default_value);
156 if (!v)
157 return NULL;
159 swrite = strchr(v, ':');
161 /* Default to the same field as read field */
162 if (!swrite)
163 return v;
165 swrite++;
167 /* If the field is 0 chars long, we shouldn't write to it */
168 if (!strlen(swrite) || !strcmp(swrite, "NULL"))
169 return NULL;
171 /* Otherwise, use the additionally specified */
172 return swrite;
175 static const char * config_value_read(pdb_mysql_data * data, const char *name, const char *default_value)
177 char *v = NULL;
178 char *swrite;
180 v = lp_parm_talloc_string(GLOBAL_SECTION_SNUM, data->location, name, default_value);
182 if (!v)
183 return "NULL";
185 swrite = strchr(v, ':');
187 /* If no write is specified, there are no problems */
188 if (!swrite) {
189 if (strlen(v) == 0)
190 return "NULL";
191 return (const char *)v;
194 /* Otherwise, we have to cut the ':write_part' */
195 *swrite = '\0';
196 if (strlen(v) == 0)
197 return "NULL";
199 return (const char *)v;
202 /* Wrapper for atol that returns 0 if 'a' points to NULL */
203 static long xatol(const char *a)
205 long ret = 0;
207 if (a != NULL)
208 ret = atol(a);
210 return ret;
213 static NTSTATUS row_to_sam_account(MYSQL_RES * r, SAM_ACCOUNT * u)
215 MYSQL_ROW row;
216 pstring temp;
217 unsigned int num_fields;
218 DOM_SID sid;
220 num_fields = mysql_num_fields(r);
221 row = mysql_fetch_row(r);
222 if (!row)
223 return NT_STATUS_INVALID_PARAMETER;
225 pdb_set_logon_time(u, xatol(row[0]), PDB_SET);
226 pdb_set_logoff_time(u, xatol(row[1]), PDB_SET);
227 pdb_set_kickoff_time(u, xatol(row[2]), PDB_SET);
228 pdb_set_pass_last_set_time(u, xatol(row[3]), PDB_SET);
229 pdb_set_pass_can_change_time(u, xatol(row[4]), PDB_SET);
230 pdb_set_pass_must_change_time(u, xatol(row[5]), PDB_SET);
231 pdb_set_username(u, row[6], PDB_SET);
232 pdb_set_domain(u, row[7], PDB_SET);
233 pdb_set_nt_username(u, row[8], PDB_SET);
234 pdb_set_fullname(u, row[9], PDB_SET);
235 pdb_set_homedir(u, row[10], PDB_SET);
236 pdb_set_dir_drive(u, row[11], PDB_SET);
237 pdb_set_logon_script(u, row[12], PDB_SET);
238 pdb_set_profile_path(u, row[13], PDB_SET);
239 pdb_set_acct_desc(u, row[14], PDB_SET);
240 pdb_set_workstations(u, row[15], PDB_SET);
241 pdb_set_unknown_str(u, row[16], PDB_SET);
242 pdb_set_munged_dial(u, row[17], PDB_SET);
244 if(row[18])string_to_sid(&sid, row[18]);
245 pdb_set_user_sid(u, &sid, PDB_SET);
246 if(row[19])string_to_sid(&sid, row[19]);
247 pdb_set_group_sid(u, &sid, PDB_SET);
249 if (pdb_gethexpwd(row[20], temp), PDB_SET)
250 pdb_set_lanman_passwd(u, temp, PDB_SET);
251 if (pdb_gethexpwd(row[21], temp), PDB_SET)
252 pdb_set_nt_passwd(u, temp, PDB_SET);
254 /* Only use plaintext password storage when lanman and nt are
255 * NOT used */
256 if (!row[20] || !row[21])
257 pdb_set_plaintext_passwd(u, row[22]);
259 pdb_set_acct_ctrl(u, xatol(row[23]), PDB_SET);
260 pdb_set_unknown_3(u, xatol(row[24]), PDB_SET);
261 pdb_set_logon_divs(u, xatol(row[25]), PDB_SET);
262 pdb_set_hours_len(u, xatol(row[26]), PDB_SET);
263 pdb_set_bad_password_count(u, xatol(row[27]), PDB_SET);
264 pdb_set_logon_count(u, xatol(row[28]), PDB_SET);
265 pdb_set_unknown_6(u, xatol(row[29]), PDB_SET);
267 return NT_STATUS_OK;
270 static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update)
272 struct pdb_mysql_data *data =
273 (struct pdb_mysql_data *) methods->private_data;
274 char *query;
275 int ret;
277 if (!data || !(data->handle)) {
278 DEBUG(0, ("invalid handle!\n"));
279 return NT_STATUS_INVALID_HANDLE;
282 asprintf(&query,
283 "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 FROM %s",
284 config_value_read(data, "logon time column",
285 CONFIG_LOGON_TIME_DEFAULT),
286 config_value_read(data, "logoff time column",
287 CONFIG_LOGOFF_TIME_DEFAULT),
288 config_value_read(data, "kickoff time column",
289 CONFIG_KICKOFF_TIME_DEFAULT),
290 config_value_read(data, "pass last set time column",
291 CONFIG_PASS_LAST_SET_TIME_DEFAULT),
292 config_value_read(data, "pass can change time column",
293 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
294 config_value_read(data, "pass must change time column",
295 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
296 config_value_read(data, "username column",
297 CONFIG_USERNAME_DEFAULT),
298 config_value_read(data, "domain column",
299 CONFIG_DOMAIN_DEFAULT),
300 config_value_read(data, "nt username column",
301 CONFIG_NT_USERNAME_DEFAULT),
302 config_value_read(data, "fullname column",
303 CONFIG_FULLNAME_DEFAULT),
304 config_value_read(data, "home dir column",
305 CONFIG_HOME_DIR_DEFAULT),
306 config_value_read(data, "dir drive column",
307 CONFIG_DIR_DRIVE_DEFAULT),
308 config_value_read(data, "logon script column",
309 CONFIG_LOGON_SCRIPT_DEFAULT),
310 config_value_read(data, "profile path column",
311 CONFIG_PROFILE_PATH_DEFAULT),
312 config_value_read(data, "acct desc column",
313 CONFIG_ACCT_DESC_DEFAULT),
314 config_value_read(data, "workstations column",
315 CONFIG_WORKSTATIONS_DEFAULT),
316 config_value_read(data, "unknown string column",
317 CONFIG_UNKNOWN_STR_DEFAULT),
318 config_value_read(data, "munged dial column",
319 CONFIG_MUNGED_DIAL_DEFAULT),
320 config_value_read(data, "user sid column",
321 CONFIG_USER_SID_DEFAULT),
322 config_value_read(data, "group sid column",
323 CONFIG_GROUP_SID_DEFAULT),
324 config_value_read(data, "lanman pass column",
325 CONFIG_LM_PW_DEFAULT),
326 config_value_read(data, "nt pass column",
327 CONFIG_NT_PW_DEFAULT),
328 config_value_read(data, "plain pass column",
329 CONFIG_PLAIN_PW_DEFAULT),
330 config_value_read(data, "acct ctrl column",
331 CONFIG_ACCT_CTRL_DEFAULT),
332 config_value_read(data, "unknown 3 column",
333 CONFIG_UNKNOWN_3_DEFAULT),
334 config_value_read(data, "logon divs column",
335 CONFIG_LOGON_DIVS_DEFAULT),
336 config_value_read(data, "hours len column",
337 CONFIG_HOURS_LEN_DEFAULT),
338 config_value_read(data, "bad_password_count column",
339 CONFIG_BAD_PASSWORD_COUNT_DEFAULT),
340 config_value_read(data, "logon_count column",
341 CONFIG_LOGON_COUNT_DEFAULT),
342 config_value_read(data, "unknown 6 column",
343 CONFIG_UNKNOWN_6_DEFAULT),
344 config_value(data, "table", CONFIG_TABLE_DEFAULT)
346 DEBUG(5, ("Executing query %s\n", query));
348 ret = mysql_query(data->handle, query);
349 SAFE_FREE(query);
351 if (ret) {
352 DEBUG(0,
353 ("Error executing MySQL query %s\n", mysql_error(data->handle)));
354 return NT_STATUS_UNSUCCESSFUL;
357 data->pwent = mysql_store_result(data->handle);
359 if (data->pwent == NULL) {
360 DEBUG(0,
361 ("Error storing results: %s\n", mysql_error(data->handle)));
362 return NT_STATUS_UNSUCCESSFUL;
365 DEBUG(5,
366 ("mysqlsam_setsampwent succeeded(%llu results)!\n",
367 mysql_num_rows(data->pwent)));
369 return NT_STATUS_OK;
372 /***************************************************************
373 End enumeration of the passwd list.
374 ****************************************************************/
376 static void mysqlsam_endsampwent(struct pdb_methods *methods)
378 struct pdb_mysql_data *data =
379 (struct pdb_mysql_data *) methods->private_data;
381 if (data == NULL) {
382 DEBUG(0, ("invalid handle!\n"));
383 return;
386 if (data->pwent != NULL)
387 mysql_free_result(data->pwent);
389 data->pwent = NULL;
391 DEBUG(5, ("mysql_endsampwent called\n"));
394 /*****************************************************************
395 Get one SAM_ACCOUNT from the list (next in line)
396 *****************************************************************/
398 static NTSTATUS mysqlsam_getsampwent(struct pdb_methods *methods, SAM_ACCOUNT * user)
400 struct pdb_mysql_data *data;
402 SET_DATA(data, methods);
404 if (data->pwent == NULL) {
405 DEBUG(0, ("invalid pwent\n"));
406 return NT_STATUS_INVALID_PARAMETER;
409 return row_to_sam_account(data->pwent, user);
412 static NTSTATUS mysqlsam_select_by_field(struct pdb_methods * methods, SAM_ACCOUNT * user,
413 const char *field, const char *sname)
415 char *esc_sname;
416 char *query;
417 NTSTATUS ret;
418 MYSQL_RES *res;
419 int mysql_ret;
420 struct pdb_mysql_data *data;
421 char *tmp_sname;
423 SET_DATA(data, methods);
425 esc_sname = malloc(strlen(sname) * 2 + 1);
426 if (!esc_sname) {
427 return NT_STATUS_NO_MEMORY;
430 DEBUG(5,
431 ("mysqlsam_select_by_field: getting data where %s = %s(nonescaped)\n",
432 field, sname));
434 tmp_sname = smb_xstrdup(sname);
436 /* Escape sname */
437 mysql_real_escape_string(data->handle, esc_sname, tmp_sname,
438 strlen(tmp_sname));
440 SAFE_FREE(tmp_sname);
442 if (user == NULL) {
443 DEBUG(0, ("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
444 SAFE_FREE(esc_sname);
445 return NT_STATUS_INVALID_PARAMETER;
448 asprintf(&query,
449 "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 FROM %s WHERE %s = '%s'",
450 config_value_read(data, "logon time column",
451 CONFIG_LOGON_TIME_DEFAULT),
452 config_value_read(data, "logoff time column",
453 CONFIG_LOGOFF_TIME_DEFAULT),
454 config_value_read(data, "kickoff time column",
455 CONFIG_KICKOFF_TIME_DEFAULT),
456 config_value_read(data, "pass last set time column",
457 CONFIG_PASS_LAST_SET_TIME_DEFAULT),
458 config_value_read(data, "pass can change time column",
459 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
460 config_value_read(data, "pass must change time column",
461 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
462 config_value_read(data, "username column",
463 CONFIG_USERNAME_DEFAULT),
464 config_value_read(data, "domain column",
465 CONFIG_DOMAIN_DEFAULT),
466 config_value_read(data, "nt username column",
467 CONFIG_NT_USERNAME_DEFAULT),
468 config_value_read(data, "fullname column",
469 CONFIG_FULLNAME_DEFAULT),
470 config_value_read(data, "home dir column",
471 CONFIG_HOME_DIR_DEFAULT),
472 config_value_read(data, "dir drive column",
473 CONFIG_DIR_DRIVE_DEFAULT),
474 config_value_read(data, "logon script column",
475 CONFIG_LOGON_SCRIPT_DEFAULT),
476 config_value_read(data, "profile path column",
477 CONFIG_PROFILE_PATH_DEFAULT),
478 config_value_read(data, "acct desc column",
479 CONFIG_ACCT_DESC_DEFAULT),
480 config_value_read(data, "workstations column",
481 CONFIG_WORKSTATIONS_DEFAULT),
482 config_value_read(data, "unknown string column",
483 CONFIG_UNKNOWN_STR_DEFAULT),
484 config_value_read(data, "munged dial column",
485 CONFIG_MUNGED_DIAL_DEFAULT),
486 config_value_read(data, "user sid column",
487 CONFIG_USER_SID_DEFAULT),
488 config_value_read(data, "group sid column",
489 CONFIG_GROUP_SID_DEFAULT),
490 config_value_read(data, "lanman pass column",
491 CONFIG_LM_PW_DEFAULT),
492 config_value_read(data, "nt pass column",
493 CONFIG_NT_PW_DEFAULT),
494 config_value_read(data, "plain pass column",
495 CONFIG_PLAIN_PW_DEFAULT),
496 config_value_read(data, "acct ctrl column",
497 CONFIG_ACCT_CTRL_DEFAULT),
498 config_value_read(data, "unknown 3 column",
499 CONFIG_UNKNOWN_3_DEFAULT),
500 config_value_read(data, "logon divs column",
501 CONFIG_LOGON_DIVS_DEFAULT),
502 config_value_read(data, "hours len column",
503 CONFIG_HOURS_LEN_DEFAULT),
504 config_value_read(data, "bad password count column",
505 CONFIG_BAD_PASSWORD_COUNT_DEFAULT),
506 config_value_read(data, "logon count column",
507 CONFIG_LOGON_COUNT_DEFAULT),
508 config_value_read(data, "unknown 6 column",
509 CONFIG_UNKNOWN_6_DEFAULT),
510 config_value(data, "table", CONFIG_TABLE_DEFAULT), field,
511 esc_sname);
513 SAFE_FREE(esc_sname);
515 DEBUG(5, ("Executing query %s\n", query));
517 mysql_ret = mysql_query(data->handle, query);
519 SAFE_FREE(query);
521 if (mysql_ret) {
522 DEBUG(0,
523 ("Error while executing MySQL query %s\n",
524 mysql_error(data->handle)));
525 return NT_STATUS_UNSUCCESSFUL;
528 res = mysql_store_result(data->handle);
529 if (res == NULL) {
530 DEBUG(0,
531 ("Error storing results: %s\n", mysql_error(data->handle)));
532 return NT_STATUS_UNSUCCESSFUL;
535 ret = row_to_sam_account(res, user);
536 mysql_free_result(res);
538 return ret;
541 /******************************************************************
542 Lookup a name in the SAM database
543 ******************************************************************/
545 static NTSTATUS mysqlsam_getsampwnam(struct pdb_methods *methods, SAM_ACCOUNT * user,
546 const char *sname)
548 struct pdb_mysql_data *data;
550 SET_DATA(data, methods);
552 if (!sname) {
553 DEBUG(0, ("invalid name specified"));
554 return NT_STATUS_INVALID_PARAMETER;
557 return mysqlsam_select_by_field(methods, user,
558 config_value_read(data, "username column",
559 CONFIG_USERNAME_DEFAULT), sname);
563 /***************************************************************************
564 Search by sid
565 **************************************************************************/
567 static NTSTATUS mysqlsam_getsampwsid(struct pdb_methods *methods, SAM_ACCOUNT * user,
568 const DOM_SID * sid)
570 struct pdb_mysql_data *data;
571 fstring sid_str;
573 SET_DATA(data, methods);
575 sid_to_string(sid_str, sid);
577 return mysqlsam_select_by_field(methods, user,
578 config_value_read(data, "user sid column",
579 CONFIG_USER_SID_DEFAULT), sid_str);
582 /***************************************************************************
583 Delete a SAM_ACCOUNT
584 ****************************************************************************/
586 static NTSTATUS mysqlsam_delete_sam_account(struct pdb_methods *methods,
587 SAM_ACCOUNT * sam_pass)
589 const char *sname = pdb_get_username(sam_pass);
590 char *esc;
591 char *query;
592 int ret;
593 struct pdb_mysql_data *data;
594 char *tmp_sname;
596 SET_DATA(data, methods);
598 if (!methods) {
599 DEBUG(0, ("invalid methods!\n"));
600 return NT_STATUS_INVALID_PARAMETER;
603 data = (struct pdb_mysql_data *) methods->private_data;
604 if (!data || !(data->handle)) {
605 DEBUG(0, ("invalid handle!\n"));
606 return NT_STATUS_INVALID_HANDLE;
609 if (!sname) {
610 DEBUG(0, ("invalid name specified\n"));
611 return NT_STATUS_INVALID_PARAMETER;
614 /* Escape sname */
615 esc = malloc(strlen(sname) * 2 + 1);
616 if (!esc) {
617 DEBUG(0, ("Can't allocate memory to store escaped name\n"));
618 return NT_STATUS_NO_MEMORY;
621 tmp_sname = smb_xstrdup(sname);
623 mysql_real_escape_string(data->handle, esc, tmp_sname,
624 strlen(tmp_sname));
626 SAFE_FREE(tmp_sname);
628 asprintf(&query, "DELETE FROM %s WHERE %s = '%s'",
629 config_value(data, "table", CONFIG_TABLE_DEFAULT),
630 config_value_read(data, "username column",
631 CONFIG_USERNAME_DEFAULT), esc);
633 SAFE_FREE(esc);
635 ret = mysql_query(data->handle, query);
637 SAFE_FREE(query);
639 if (ret) {
640 DEBUG(0,
641 ("Error while executing query: %s\n",
642 mysql_error(data->handle)));
643 return NT_STATUS_UNSUCCESSFUL;
646 DEBUG(5, ("User '%s' deleted\n", sname));
647 return NT_STATUS_OK;
650 static NTSTATUS mysqlsam_replace_sam_account(struct pdb_methods *methods,
651 const SAM_ACCOUNT * newpwd, char isupdate)
653 pstring temp;
654 struct pdb_mysql_data *data;
655 pdb_mysql_query query;
656 fstring sid_str;
658 if (!methods) {
659 DEBUG(0, ("invalid methods!\n"));
660 return NT_STATUS_INVALID_PARAMETER;
663 data = (struct pdb_mysql_data *) methods->private_data;
664 if (data == NULL || data->handle == NULL) {
665 DEBUG(0, ("invalid handle!\n"));
666 return NT_STATUS_INVALID_HANDLE;
668 query.update = isupdate;
670 /* I know this is somewhat overkill but only the talloc
671 * functions have asprint_append and the 'normal' asprintf
672 * is a GNU extension */
673 query.mem_ctx = talloc_init("mysqlsam_replace_sam_account");
674 query.part2 = talloc_asprintf(query.mem_ctx, "%s", "");
675 if (query.update) {
676 query.part1 =
677 talloc_asprintf(query.mem_ctx, "UPDATE %s SET ",
678 config_value(data, "table",
679 CONFIG_TABLE_DEFAULT));
680 } else {
681 query.part1 =
682 talloc_asprintf(query.mem_ctx, "INSERT INTO %s (",
683 config_value(data, "table",
684 CONFIG_TABLE_DEFAULT));
687 pdb_mysql_int_field(methods, &query,
688 config_value_write(data, "acct ctrl column",
689 CONFIG_ACCT_CTRL_DEFAULT),
690 pdb_get_acct_ctrl(newpwd));
692 if (pdb_get_init_flags(newpwd, PDB_LOGONTIME) != PDB_DEFAULT) {
693 pdb_mysql_int_field(methods, &query,
694 config_value_write(data,
695 "logon time column",
696 CONFIG_LOGON_TIME_DEFAULT),
697 pdb_get_logon_time(newpwd));
700 if (pdb_get_init_flags(newpwd, PDB_LOGOFFTIME) != PDB_DEFAULT) {
701 pdb_mysql_int_field(methods, &query,
702 config_value_write(data,
703 "logoff time column",
704 CONFIG_LOGOFF_TIME_DEFAULT),
705 pdb_get_logoff_time(newpwd));
708 if (pdb_get_init_flags(newpwd, PDB_KICKOFFTIME) != PDB_DEFAULT) {
709 pdb_mysql_int_field(methods, &query,
710 config_value_write(data,
711 "kickoff time column",
712 CONFIG_KICKOFF_TIME_DEFAULT),
713 pdb_get_kickoff_time(newpwd));
716 if (pdb_get_init_flags(newpwd, PDB_CANCHANGETIME) != PDB_DEFAULT) {
717 pdb_mysql_int_field(methods, &query,
718 config_value_write(data,
719 "pass can change time column",
720 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT),
721 pdb_get_pass_can_change_time(newpwd));
724 if (pdb_get_init_flags(newpwd, PDB_MUSTCHANGETIME) != PDB_DEFAULT) {
725 pdb_mysql_int_field(methods, &query,
726 config_value_write(data,
727 "pass must change time column",
728 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT),
729 pdb_get_pass_must_change_time(newpwd));
732 if (pdb_get_pass_last_set_time(newpwd)) {
733 pdb_mysql_int_field(methods, &query,
734 config_value_write(data,
735 "pass last set time column",
736 CONFIG_PASS_LAST_SET_TIME_DEFAULT),
737 pdb_get_pass_last_set_time(newpwd));
740 if (pdb_get_hours_len(newpwd)) {
741 pdb_mysql_int_field(methods, &query,
742 config_value_write(data,
743 "hours len column",
744 CONFIG_HOURS_LEN_DEFAULT),
745 pdb_get_hours_len(newpwd));
748 if (pdb_get_logon_divs(newpwd)) {
749 pdb_mysql_int_field(methods, &query,
750 config_value_write(data,
751 "logon divs column",
752 CONFIG_LOGON_DIVS_DEFAULT),
753 pdb_get_logon_divs(newpwd));
756 pdb_mysql_string_field(methods, &query,
757 config_value_write(data, "user sid column",
758 CONFIG_USER_SID_DEFAULT),
759 sid_to_string(sid_str,
760 pdb_get_user_sid(newpwd)));
762 pdb_mysql_string_field(methods, &query,
763 config_value_write(data, "group sid column",
764 CONFIG_GROUP_SID_DEFAULT),
765 sid_to_string(sid_str,
766 pdb_get_group_sid(newpwd)));
768 pdb_mysql_string_field(methods, &query,
769 config_value_write(data, "username column",
770 CONFIG_USERNAME_DEFAULT),
771 pdb_get_username(newpwd));
773 pdb_mysql_string_field(methods, &query,
774 config_value_write(data, "domain column",
775 CONFIG_DOMAIN_DEFAULT),
776 pdb_get_domain(newpwd));
778 pdb_mysql_string_field(methods, &query,
779 config_value_write(data,
780 "nt username column",
781 CONFIG_NT_USERNAME_DEFAULT),
782 pdb_get_nt_username(newpwd));
784 pdb_mysql_string_field(methods, &query,
785 config_value_write(data, "fullname column",
786 CONFIG_FULLNAME_DEFAULT),
787 pdb_get_fullname(newpwd));
789 pdb_mysql_string_field(methods, &query,
790 config_value_write(data,
791 "logon script column",
792 CONFIG_LOGON_SCRIPT_DEFAULT),
793 pdb_get_logon_script(newpwd));
795 pdb_mysql_string_field(methods, &query,
796 config_value_write(data,
797 "profile path column",
798 CONFIG_PROFILE_PATH_DEFAULT),
799 pdb_get_profile_path(newpwd));
801 pdb_mysql_string_field(methods, &query,
802 config_value_write(data, "dir drive column",
803 CONFIG_DIR_DRIVE_DEFAULT),
804 pdb_get_dir_drive(newpwd));
806 pdb_mysql_string_field(methods, &query,
807 config_value_write(data, "home dir column",
808 CONFIG_HOME_DIR_DEFAULT),
809 pdb_get_homedir(newpwd));
811 pdb_mysql_string_field(methods, &query,
812 config_value_write(data,
813 "workstations column",
814 CONFIG_WORKSTATIONS_DEFAULT),
815 pdb_get_workstations(newpwd));
817 pdb_mysql_string_field(methods, &query,
818 config_value_write(data,
819 "unknown string column",
820 CONFIG_UNKNOWN_STR_DEFAULT),
821 pdb_get_workstations(newpwd));
823 pdb_sethexpwd(temp, pdb_get_lanman_passwd(newpwd),
824 pdb_get_acct_ctrl(newpwd));
825 pdb_mysql_string_field(methods, &query,
826 config_value_write(data,
827 "lanman pass column",
828 CONFIG_LM_PW_DEFAULT), temp);
830 pdb_sethexpwd(temp, pdb_get_nt_passwd(newpwd),
831 pdb_get_acct_ctrl(newpwd));
832 pdb_mysql_string_field(methods, &query,
833 config_value_write(data, "nt pass column",
834 CONFIG_NT_PW_DEFAULT), temp);
836 if (query.update) {
837 query.part1[strlen(query.part1) - 1] = '\0';
838 query.part1 =
839 talloc_asprintf_append(query.mem_ctx, query.part1,
840 " WHERE %s = '%s'",
841 config_value_read(data,
842 "user sid column",
843 CONFIG_USER_SID_DEFAULT),
844 sid_to_string(sid_str, pdb_get_user_sid (newpwd)));
845 } else {
846 query.part2[strlen(query.part2) - 1] = ')';
847 query.part1[strlen(query.part1) - 1] = ')';
848 query.part1 =
849 talloc_asprintf_append(query.mem_ctx, query.part1,
850 " VALUES (%s", query.part2);
853 DEBUG(0, ("%s\n", query.part1));
854 /* Execute the query */
855 if (mysql_query(data->handle, query.part1)) {
856 DEBUG(0,
857 ("Error executing %s, %s\n", query.part1,
858 mysql_error(data->handle)));
859 return NT_STATUS_INVALID_PARAMETER;
861 talloc_destroy(query.mem_ctx);
862 return NT_STATUS_OK;
865 static NTSTATUS mysqlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT * newpwd)
867 return mysqlsam_replace_sam_account(methods, newpwd, 0);
870 static NTSTATUS mysqlsam_update_sam_account(struct pdb_methods *methods,
871 SAM_ACCOUNT * newpwd)
873 return mysqlsam_replace_sam_account(methods, newpwd, 1);
876 static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_methods ** pdb_method,
877 const char *location)
879 NTSTATUS nt_status;
880 struct pdb_mysql_data *data;
882 mysqlsam_debug_level = debug_add_class("mysqlsam");
883 if (mysqlsam_debug_level == -1) {
884 mysqlsam_debug_level = DBGC_ALL;
885 DEBUG(0,
886 ("mysqlsam: Couldn't register custom debugging class!\n"));
889 if (!pdb_context) {
890 DEBUG(0, ("invalid pdb_methods specified\n"));
891 return NT_STATUS_UNSUCCESSFUL;
894 if (!NT_STATUS_IS_OK
895 (nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
896 return nt_status;
899 (*pdb_method)->name = "mysqlsam";
901 (*pdb_method)->setsampwent = mysqlsam_setsampwent;
902 (*pdb_method)->endsampwent = mysqlsam_endsampwent;
903 (*pdb_method)->getsampwent = mysqlsam_getsampwent;
904 (*pdb_method)->getsampwnam = mysqlsam_getsampwnam;
905 (*pdb_method)->getsampwsid = mysqlsam_getsampwsid;
906 (*pdb_method)->add_sam_account = mysqlsam_add_sam_account;
907 (*pdb_method)->update_sam_account = mysqlsam_update_sam_account;
908 (*pdb_method)->delete_sam_account = mysqlsam_delete_sam_account;
910 data = talloc(pdb_context->mem_ctx, sizeof(struct pdb_mysql_data));
911 (*pdb_method)->private_data = data;
912 data->handle = NULL;
913 data->pwent = NULL;
915 if (!location) {
916 DEBUG(0, ("No identifier specified. Check the Samba HOWTO Collection for details\n"));
917 return NT_STATUS_INVALID_PARAMETER;
920 data->location = smb_xstrdup(location);
922 DEBUG(1,
923 ("Connecting to database server, host: %s, user: %s, password: %s, database: %s, port: %ld\n",
924 config_value(data, "mysql host", CONFIG_HOST_DEFAULT),
925 config_value(data, "mysql user", CONFIG_USER_DEFAULT),
926 config_value(data, "mysql password", CONFIG_PASS_DEFAULT),
927 config_value(data, "mysql database", CONFIG_DB_DEFAULT),
928 xatol(config_value(data, "mysql port", CONFIG_PORT_DEFAULT))));
930 /* Do the mysql initialization */
931 data->handle = mysql_init(NULL);
932 if (!data->handle) {
933 DEBUG(0, ("Failed to connect to server\n"));
934 return NT_STATUS_UNSUCCESSFUL;
936 /* Process correct entry in $HOME/.my.conf */
937 if (!mysql_real_connect(data->handle,
938 config_value(data, "mysql host", CONFIG_HOST_DEFAULT),
939 config_value(data, "mysql user", CONFIG_USER_DEFAULT),
940 config_value(data, "mysql password", CONFIG_PASS_DEFAULT),
941 config_value(data, "mysql database", CONFIG_DB_DEFAULT),
942 xatol(config_value (data, "mysql port", CONFIG_PORT_DEFAULT)),
943 NULL, 0)) {
944 DEBUG(0,
945 ("Failed to connect to mysql database: error: %s\n",
946 mysql_error(data->handle)));
947 return NT_STATUS_UNSUCCESSFUL;
950 DEBUG(5, ("Connected to mysql db\n"));
952 return NT_STATUS_OK;
955 NTSTATUS pdb_mysql_init(void)
957 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "mysql", mysqlsam_init);