don't dereference null pointer
[Samba/gebeck_regimport.git] / source4 / modules / mysql.c
blob1d5819295b034ce737b3d27a0a0fd8e59d9c5f2e
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_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;
64 #undef DBGC_CLASS
65 #define DBGC_CLASS mysqlsam_debug_level
67 typedef struct pdb_mysql_data {
68 MYSQL *handle;
69 MYSQL_RES *pwent;
70 const char *location;
71 } pdb_mysql_data;
73 /* Used to construct insert and update queries */
75 typedef struct pdb_mysql_query {
76 char update;
77 TALLOC_CTX *mem_ctx;
78 char *part1;
79 char *part2;
80 } pdb_mysql_query;
81 #define SET_DATA(data,methods) { \
82 if(!methods){ \
83 DEBUG(0, ("invalid methods!\n")); \
84 return NT_STATUS_INVALID_PARAMETER; \
85 } \
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; \
90 } \
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 */
99 if (q->update) {
100 q->part1 =
101 talloc_asprintf_append(q->mem_ctx, q->part1,
102 "%s = %d,", name, value);
103 } else {
104 q->part1 =
105 talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name);
106 q->part2 =
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)
115 char *esc_value;
116 struct pdb_mysql_data *data;
117 char *tmp_value;
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,
128 strlen(tmp_value));
129 SAFE_FREE(tmp_value);
131 if (q->update) {
132 q->part1 =
133 talloc_asprintf_append(q->mem_ctx, q->part1,
134 "%s = '%s',", name, esc_value);
135 } else {
136 q->part1 =
137 talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name);
138 q->part2 =
139 talloc_asprintf_append(q->mem_ctx, q->part2, "'%s',",
140 esc_value);
143 SAFE_FREE(esc_value);
145 return NT_STATUS_OK;
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);
158 char *swrite;
160 if (!v)
161 return default_value;
163 swrite = strchr(v, ':');
165 /* Default to the same field as read field */
166 if (!swrite)
167 return v;
169 swrite++;
171 /* If the field is 0 chars long, we shouldn't write to it */
172 if (!strlen(swrite) || !strcmp(swrite, "NULL"))
173 return NULL;
175 /* Otherwise, use the additionally specified */
176 return swrite;
179 static const char * config_value_read(pdb_mysql_data * data, char *name, char *default_value)
181 char *v = config_value(data, name, NULL);
182 char *swrite;
184 if (!v)
185 return default_value;
187 swrite = strchr(v, ':');
189 /* If no write is specified, there are no problems */
190 if (!swrite) {
191 if (strlen(v) == 0)
192 return "NULL";
193 return v;
196 /* Otherwise, we have to cut the ':write_part' */
197 *swrite = '\0';
198 if (strlen(v) == 0)
199 return "NULL";
201 return v;
204 /* Wrapper for atol that returns 0 if 'a' points to NULL */
205 static long xatol(char *a)
207 long ret = 0;
209 if (a != NULL)
210 ret = atol(a);
212 return ret;
215 static NTSTATUS row_to_sam_account(MYSQL_RES * r, SAM_ACCOUNT * u)
217 MYSQL_ROW row;
218 pstring temp;
219 unsigned int num_fields;
220 DOM_SID sid;
222 num_fields = mysql_num_fields(r);
223 row = mysql_fetch_row(r);
224 if (!row)
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);
246 if (row[18])
247 pdb_set_uid(u, xatol(row[18]), PDB_SET);
248 if (row[19])
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
262 * NOT used */
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);
273 return NT_STATUS_OK;
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;
280 char *query;
281 int ret;
283 if (!data || !(data->handle)) {
284 DEBUG(0, ("invalid handle!\n"));
285 return NT_STATUS_INVALID_HANDLE;
288 asprintf(&query,
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);
355 SAFE_FREE(query);
357 if (ret) {
358 DEBUG(0,
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) {
366 DEBUG(0,
367 ("Error storing results: %s\n", mysql_error(data->handle)));
368 return NT_STATUS_UNSUCCESSFUL;
371 DEBUG(5,
372 ("mysqlsam_setsampwent succeeded(%lu results)!\n",
373 mysql_num_rows(data->pwent)));
375 return NT_STATUS_OK;
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;
387 if (data == NULL) {
388 DEBUG(0, ("invalid handle!\n"));
389 return;
392 if (data->pwent != NULL)
393 mysql_free_result(data->pwent);
395 data->pwent = NULL;
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)
421 char *esc_sname;
422 char *query;
423 NTSTATUS ret;
424 MYSQL_RES *res;
425 int mysql_ret;
426 struct pdb_mysql_data *data;
427 char *tmp_sname;
429 SET_DATA(data, methods);
431 esc_sname = malloc(strlen(sname) * 2 + 1);
432 if (!esc_sname) {
433 return NT_STATUS_NO_MEMORY;
436 DEBUG(5,
437 ("mysqlsam_select_by_field: getting data where %s = %s(nonescaped)\n",
438 field, sname));
440 tmp_sname = smb_xstrdup(sname);
442 /* Escape sname */
443 mysql_real_escape_string(data->handle, esc_sname, tmp_sname,
444 strlen(tmp_sname));
446 SAFE_FREE(tmp_sname);
448 if (user == NULL) {
449 DEBUG(0, ("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
450 SAFE_FREE(esc_sname);
451 return NT_STATUS_INVALID_PARAMETER;
454 asprintf(&query,
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,
517 esc_sname);
519 SAFE_FREE(esc_sname);
521 DEBUG(5, ("Executing query %s\n", query));
523 mysql_ret = mysql_query(data->handle, query);
525 SAFE_FREE(query);
527 if (mysql_ret) {
528 DEBUG(0,
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);
535 if (res == NULL) {
536 DEBUG(0,
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);
544 return ret;
547 /******************************************************************
548 Lookup a name in the SAM database
549 ******************************************************************/
551 static NTSTATUS mysqlsam_getsampwnam(struct pdb_methods *methods, SAM_ACCOUNT * user,
552 const char *sname)
554 struct pdb_mysql_data *data;
556 SET_DATA(data, methods);
558 if (!sname) {
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 /***************************************************************************
570 Search by sid
571 **************************************************************************/
573 static NTSTATUS mysqlsam_getsampwsid(struct pdb_methods *methods, SAM_ACCOUNT * user,
574 const DOM_SID * sid)
576 struct pdb_mysql_data *data;
577 fstring sid_str;
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 /***************************************************************************
589 Delete a SAM_ACCOUNT
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);
596 char *esc;
597 char *query;
598 int ret;
599 struct pdb_mysql_data *data;
600 char *tmp_sname;
602 SET_DATA(data, methods);
604 if (!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;
615 if (!sname) {
616 DEBUG(0, ("invalid name specified\n"));
617 return NT_STATUS_INVALID_PARAMETER;
620 /* Escape sname */
621 esc = malloc(strlen(sname) * 2 + 1);
622 if (!esc) {
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,
630 strlen(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);
639 SAFE_FREE(esc);
641 ret = mysql_query(data->handle, query);
643 SAFE_FREE(query);
645 if (ret) {
646 DEBUG(0,
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));
653 return NT_STATUS_OK;
656 static NTSTATUS mysqlsam_replace_sam_account(struct pdb_methods *methods,
657 const SAM_ACCOUNT * newpwd, char isupdate)
659 pstring temp;
660 struct pdb_mysql_data *data;
661 pdb_mysql_query query;
662 fstring sid_str;
664 if (!methods) {
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", "");
681 if (query.update) {
682 query.part1 =
683 talloc_asprintf(query.mem_ctx, "UPDATE %s SET ",
684 config_value(data, "table",
685 CONFIG_TABLE_DEFAULT));
686 } else {
687 query.part1 =
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,
701 "logon time column",
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,
749 "hours len column",
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,
757 "logon divs column",
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",
765 CONFIG_UID_DEFAULT),
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",
772 CONFIG_GID_DEFAULT),
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);
856 if (query.update) {
857 query.part1[strlen(query.part1) - 1] = '\0';
858 query.part1 =
859 talloc_asprintf_append(query.mem_ctx, query.part1,
860 " WHERE %s = '%s'",
861 config_value_read(data,
862 "user sid column",
863 CONFIG_USER_SID_DEFAULT),
864 sid_to_string(sid_str, pdb_get_user_sid (newpwd)));
865 } else {
866 query.part2[strlen(query.part2) - 1] = ')';
867 query.part1[strlen(query.part1) - 1] = ')';
868 query.part1 =
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)) {
876 DEBUG(0,
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);
882 return NT_STATUS_OK;
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,
918 GROUP_MAP *map)
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,
925 GROUP_MAP *map)
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,
932 DOM_SID sid)
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,
944 with_priv) ?
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)
952 NTSTATUS nt_status;
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;
958 DEBUG(0,
959 ("mysqlsam: Couldn't register custom debugging class!\n"));
962 if (!pdb_context) {
963 DEBUG(0, ("invalid pdb_methods specified\n"));
964 return NT_STATUS_UNSUCCESSFUL;
967 if (!NT_STATUS_IS_OK
968 (nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
969 return nt_status;
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;
992 data->handle = NULL;
993 data->pwent = NULL;
995 if (!location) {
996 DEBUG(0, ("No identifier specified. See README for details\n"));
997 return NT_STATUS_INVALID_PARAMETER;
1000 data->location = smb_xstrdup(location);
1002 DEBUG(1,
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)),
1023 NULL, 0)) {
1024 DEBUG(0,
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);
1037 int init_module()
1039 if(smb_register_passdb("mysql", mysqlsam_init, PASSDB_INTERFACE_VERSION))
1040 return 0;
1042 return 1;