2 * Common PDB SQL backend functions
3 * Copyright (C) Jelmer Vernooij 2003-2004
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 675
17 * Mass Ave, Cambridge, MA 02139, USA.
22 #define CONFIG_TABLE_DEFAULT "user"
23 #define CONFIG_LOGON_TIME_DEFAULT "logon_time"
24 #define CONFIG_LOGOFF_TIME_DEFAULT "logoff_time"
25 #define CONFIG_KICKOFF_TIME_DEFAULT "kickoff_time"
26 #define CONFIG_PASS_LAST_SET_TIME_DEFAULT "pass_last_set_time"
27 #define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT "pass_can_change_time"
28 #define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT "pass_must_change_time"
29 #define CONFIG_USERNAME_DEFAULT "username"
30 #define CONFIG_DOMAIN_DEFAULT "domain"
31 #define CONFIG_NT_USERNAME_DEFAULT "nt_username"
32 #define CONFIG_FULLNAME_DEFAULT "nt_fullname"
33 #define CONFIG_HOME_DIR_DEFAULT "home_dir"
34 #define CONFIG_DIR_DRIVE_DEFAULT "dir_drive"
35 #define CONFIG_LOGON_SCRIPT_DEFAULT "logon_script"
36 #define CONFIG_PROFILE_PATH_DEFAULT "profile_path"
37 #define CONFIG_ACCT_DESC_DEFAULT "acct_desc"
38 #define CONFIG_WORKSTATIONS_DEFAULT "workstations"
39 #define CONFIG_UNKNOWN_STR_DEFAULT "unknown_str"
40 #define CONFIG_MUNGED_DIAL_DEFAULT "munged_dial"
41 #define CONFIG_USER_SID_DEFAULT "user_sid"
42 #define CONFIG_GROUP_SID_DEFAULT "group_sid"
43 #define CONFIG_LM_PW_DEFAULT "lm_pw"
44 #define CONFIG_NT_PW_DEFAULT "nt_pw"
45 #define CONFIG_PLAIN_PW_DEFAULT "NULL"
46 #define CONFIG_ACCT_CTRL_DEFAULT "acct_ctrl"
47 #define CONFIG_LOGON_DIVS_DEFAULT "logon_divs"
48 #define CONFIG_HOURS_LEN_DEFAULT "hours_len"
49 #define CONFIG_BAD_PASSWORD_COUNT_DEFAULT "bad_password_count"
50 #define CONFIG_LOGON_COUNT_DEFAULT "logon_count"
51 #define CONFIG_UNKNOWN_6_DEFAULT "unknown_6"
52 #define CONFIG_LOGON_HOURS "logon_hours"
54 /* Used to construct insert and update queries */
56 typedef struct pdb_sql_query
{
62 static void pdb_sql_int_field(struct pdb_sql_query
*q
, const char *name
, int value
)
64 if (!name
|| strchr(name
, '\''))
65 return; /* This field shouldn't be set by us */
69 talloc_asprintf_append(q
->part1
,
70 "%s = %d,", name
, value
);
73 talloc_asprintf_append(q
->part1
, "%s,", name
);
75 talloc_asprintf_append(q
->part2
, "%d,", value
);
79 char *sql_escape_string(TALLOC_CTX
*mem_ctx
, const char *unesc
)
81 char *esc
= talloc_array(mem_ctx
, char, strlen(unesc
) * 2 + 3);
82 size_t pos_unesc
= 0, pos_esc
= 0;
84 for(pos_unesc
= 0; unesc
[pos_unesc
]; pos_unesc
++) {
85 switch(unesc
[pos_unesc
]) {
89 esc
[pos_esc
] = '\\'; pos_esc
++;
91 esc
[pos_esc
] = unesc
[pos_unesc
]; pos_esc
++;
101 static NTSTATUS
pdb_sql_string_field(struct pdb_sql_query
*q
,
102 const char *name
, const char *value
)
106 if (!name
|| !value
|| !strcmp(value
, "") || strchr(name
, '\''))
107 return NT_STATUS_INVALID_PARAMETER
; /* This field shouldn't be set by module */
109 esc_value
= sql_escape_string(q
, value
);
113 talloc_asprintf_append(q
->part1
,
114 "%s = '%s',", name
, esc_value
);
117 talloc_asprintf_append(q
->part1
, "%s,", name
);
119 talloc_asprintf_append(q
->part2
, "'%s',",
123 talloc_free(esc_value
);
128 #define config_value(data,name,default_value) \
129 lp_parm_const_string(GLOBAL_SECTION_SNUM, data, name, default_value)
131 static const char * config_value_write(const char *location
, const char *name
, const char *default_value
)
133 char const *v
= NULL
;
134 char const *swrite
= NULL
;
136 v
= lp_parm_const_string(GLOBAL_SECTION_SNUM
, location
, name
, default_value
);
141 swrite
= strrchr(v
, ':');
143 /* Default to the same field as read field */
146 /* Updating NULL does not make much sense */
147 if (!strcmp(v
, "NULL"))
155 /* If the field is 0 chars long, we shouldn't write to it */
156 if (!strlen(swrite
) || !strcmp(swrite
, "NULL"))
159 /* Otherwise, use the additionally specified */
163 static const char * config_value_read(const char *location
, const char *name
, const char *default_value
)
168 v
= lp_parm_talloc_string(GLOBAL_SECTION_SNUM
, location
, name
, default_value
);
173 swrite
= strrchr(v
, ':');
175 /* If no write is specified, there are no problems */
179 return (const char *)v
;
182 /* Otherwise, we have to cut the ':write_part' */
187 return (const char *)v
;
190 char *sql_account_query_select(TALLOC_CTX
*mem_ctx
, const char *data
, BOOL update
, enum sql_search_field field
, const char *value
)
192 const char *field_string
;
196 case SQL_SEARCH_NONE
:
197 field_string
= "'1'";
201 case SQL_SEARCH_USER_SID
:
202 field_string
= config_value_read(data
, "user sid column",
203 CONFIG_USER_SID_DEFAULT
);
206 case SQL_SEARCH_USER_NAME
:
207 field_string
= config_value_read(data
, "username column",
208 CONFIG_USERNAME_DEFAULT
);
211 field_string
= "unknown";
215 query
= talloc_asprintf(mem_ctx
,
216 "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'",
217 config_value_read(data
, "logon time column",
218 CONFIG_LOGON_TIME_DEFAULT
),
219 config_value_read(data
, "logoff time column",
220 CONFIG_LOGOFF_TIME_DEFAULT
),
221 config_value_read(data
, "kickoff time column",
222 CONFIG_KICKOFF_TIME_DEFAULT
),
223 config_value_read(data
, "pass last set time column",
224 CONFIG_PASS_LAST_SET_TIME_DEFAULT
),
225 config_value_read(data
, "pass can change time column",
226 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT
),
227 config_value_read(data
, "pass must change time column",
228 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT
),
229 config_value_read(data
, "username column",
230 CONFIG_USERNAME_DEFAULT
),
231 config_value_read(data
, "domain column",
232 CONFIG_DOMAIN_DEFAULT
),
233 config_value_read(data
, "nt username column",
234 CONFIG_NT_USERNAME_DEFAULT
),
235 config_value_read(data
, "fullname column",
236 CONFIG_FULLNAME_DEFAULT
),
237 config_value_read(data
, "home dir column",
238 CONFIG_HOME_DIR_DEFAULT
),
239 config_value_read(data
, "dir drive column",
240 CONFIG_DIR_DRIVE_DEFAULT
),
241 config_value_read(data
, "logon script column",
242 CONFIG_LOGON_SCRIPT_DEFAULT
),
243 config_value_read(data
, "profile path column",
244 CONFIG_PROFILE_PATH_DEFAULT
),
245 config_value_read(data
, "acct desc column",
246 CONFIG_ACCT_DESC_DEFAULT
),
247 config_value_read(data
, "workstations column",
248 CONFIG_WORKSTATIONS_DEFAULT
),
249 config_value_read(data
, "unknown string column",
250 CONFIG_UNKNOWN_STR_DEFAULT
),
251 config_value_read(data
, "munged dial column",
252 CONFIG_MUNGED_DIAL_DEFAULT
),
253 config_value_read(data
, "user sid column",
254 CONFIG_USER_SID_DEFAULT
),
255 config_value_read(data
, "group sid column",
256 CONFIG_GROUP_SID_DEFAULT
),
257 config_value_read(data
, "lanman pass column",
258 CONFIG_LM_PW_DEFAULT
),
259 config_value_read(data
, "nt pass column",
260 CONFIG_NT_PW_DEFAULT
),
261 config_value_read(data
, "plain pass column",
262 CONFIG_PLAIN_PW_DEFAULT
),
263 config_value_read(data
, "acct ctrl column",
264 CONFIG_ACCT_CTRL_DEFAULT
),
265 config_value_read(data
, "logon divs column",
266 CONFIG_LOGON_DIVS_DEFAULT
),
267 config_value_read(data
, "hours len column",
268 CONFIG_HOURS_LEN_DEFAULT
),
269 config_value_read(data
, "bad password count column",
270 CONFIG_BAD_PASSWORD_COUNT_DEFAULT
),
271 config_value_read(data
, "logon count column",
272 CONFIG_LOGON_COUNT_DEFAULT
),
273 config_value_read(data
, "unknown 6 column",
274 CONFIG_UNKNOWN_6_DEFAULT
),
275 config_value_read(data
, "logon hours column",
277 config_value(data
, "table", CONFIG_TABLE_DEFAULT
),
283 char *sql_account_query_delete(TALLOC_CTX
*mem_ctx
, const char *data
, const char *esc
)
287 query
= talloc_asprintf(mem_ctx
, "DELETE FROM %s WHERE %s = '%s'",
288 config_value(data
, "table", CONFIG_TABLE_DEFAULT
),
289 config_value_read(data
, "username column",
290 CONFIG_USERNAME_DEFAULT
), esc
);
294 char *sql_account_query_update(TALLOC_CTX
*mem_ctx
, const char *location
, const SAM_ACCOUNT
*newpwd
, char isupdate
)
299 pdb_sql_query
*query
;
300 int some_field_affected
= 0;
302 query
= talloc(mem_ctx
, pdb_sql_query
);
303 query
->update
= isupdate
;
305 /* I know this is somewhat overkill but only the talloc
306 * functions have asprint_append and the 'normal' asprintf
307 * is a GNU extension */
308 query
->part2
= talloc_asprintf(query
, "%s", "");
311 talloc_asprintf(query
, "UPDATE %s SET ",
312 config_value(location
, "table",
313 CONFIG_TABLE_DEFAULT
));
316 talloc_asprintf(query
, "INSERT INTO %s (",
317 config_value(location
, "table",
318 CONFIG_TABLE_DEFAULT
));
321 if (IS_SAM_CHANGED(newpwd
, PDB_ACCTCTRL
)) {
322 some_field_affected
= 1;
323 pdb_sql_int_field(query
,
324 config_value_write(location
, "acct ctrl column",
325 CONFIG_ACCT_CTRL_DEFAULT
),
326 pdb_get_acct_ctrl(newpwd
));
329 if (IS_SAM_CHANGED(newpwd
, PDB_LOGONTIME
)) {
330 some_field_affected
= 1;
331 pdb_sql_int_field(query
,
332 config_value_write(location
,
334 CONFIG_LOGON_TIME_DEFAULT
),
335 pdb_get_logon_time(newpwd
));
338 if (IS_SAM_CHANGED(newpwd
, PDB_LOGOFFTIME
)) {
339 some_field_affected
= 1;
340 pdb_sql_int_field(query
,
341 config_value_write(location
,
342 "logoff time column",
343 CONFIG_LOGOFF_TIME_DEFAULT
),
344 pdb_get_logoff_time(newpwd
));
347 if (IS_SAM_CHANGED(newpwd
, PDB_KICKOFFTIME
)) {
348 some_field_affected
= 1;
349 pdb_sql_int_field(query
,
350 config_value_write(location
,
351 "kickoff time column",
352 CONFIG_KICKOFF_TIME_DEFAULT
),
353 pdb_get_kickoff_time(newpwd
));
356 if (IS_SAM_CHANGED(newpwd
, PDB_CANCHANGETIME
)) {
357 some_field_affected
= 1;
358 pdb_sql_int_field(query
,
359 config_value_write(location
,
360 "pass can change time column",
361 CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT
),
362 pdb_get_pass_can_change_time(newpwd
));
365 if (IS_SAM_CHANGED(newpwd
, PDB_MUSTCHANGETIME
)) {
366 some_field_affected
= 1;
367 pdb_sql_int_field(query
,
368 config_value_write(location
,
369 "pass must change time column",
370 CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT
),
371 pdb_get_pass_must_change_time(newpwd
));
374 if (IS_SAM_CHANGED(newpwd
, PDB_PASSLASTSET
)) {
375 some_field_affected
= 1;
376 pdb_sql_int_field(query
,
377 config_value_write(location
,
378 "pass last set time column",
379 CONFIG_PASS_LAST_SET_TIME_DEFAULT
),
380 pdb_get_pass_last_set_time(newpwd
));
383 if (IS_SAM_CHANGED(newpwd
, PDB_HOURSLEN
)) {
384 some_field_affected
= 1;
385 pdb_sql_int_field(query
,
386 config_value_write(location
,
388 CONFIG_HOURS_LEN_DEFAULT
),
389 pdb_get_hours_len(newpwd
));
392 if (IS_SAM_CHANGED(newpwd
, PDB_LOGONDIVS
)) {
393 some_field_affected
= 1;
394 pdb_sql_int_field(query
,
395 config_value_write(location
,
397 CONFIG_LOGON_DIVS_DEFAULT
),
398 pdb_get_logon_divs(newpwd
));
401 if (IS_SAM_CHANGED(newpwd
, PDB_USERSID
)) {
402 some_field_affected
= 1;
403 pdb_sql_string_field(query
,
404 config_value_write(location
, "user sid column",
405 CONFIG_USER_SID_DEFAULT
),
406 sid_to_string(sid_str
,
407 pdb_get_user_sid(newpwd
)));
410 if (IS_SAM_CHANGED(newpwd
, PDB_GROUPSID
)) {
411 some_field_affected
= 1;
412 pdb_sql_string_field(query
,
413 config_value_write(location
, "group sid column",
414 CONFIG_GROUP_SID_DEFAULT
),
415 sid_to_string(sid_str
,
416 pdb_get_group_sid(newpwd
)));
419 if (IS_SAM_CHANGED(newpwd
, PDB_USERNAME
)) {
420 some_field_affected
= 1;
421 pdb_sql_string_field(query
,
422 config_value_write(location
, "username column",
423 CONFIG_USERNAME_DEFAULT
),
424 pdb_get_username(newpwd
));
427 if (IS_SAM_CHANGED(newpwd
, PDB_DOMAIN
)) {
428 some_field_affected
= 1;
429 pdb_sql_string_field(query
,
430 config_value_write(location
, "domain column",
431 CONFIG_DOMAIN_DEFAULT
),
432 pdb_get_domain(newpwd
));
435 if (IS_SAM_CHANGED(newpwd
, PDB_USERNAME
)) {
436 some_field_affected
= 1;
437 pdb_sql_string_field(query
,
438 config_value_write(location
,
439 "nt username column",
440 CONFIG_NT_USERNAME_DEFAULT
),
441 pdb_get_nt_username(newpwd
));
444 if (IS_SAM_CHANGED(newpwd
, PDB_FULLNAME
)) {
445 some_field_affected
= 1;
446 pdb_sql_string_field(query
,
447 config_value_write(location
, "fullname column",
448 CONFIG_FULLNAME_DEFAULT
),
449 pdb_get_fullname(newpwd
));
452 if (IS_SAM_CHANGED(newpwd
, PDB_LOGONSCRIPT
)) {
453 some_field_affected
= 1;
454 pdb_sql_string_field(query
,
455 config_value_write(location
,
456 "logon script column",
457 CONFIG_LOGON_SCRIPT_DEFAULT
),
458 pdb_get_logon_script(newpwd
));
461 if (IS_SAM_CHANGED(newpwd
, PDB_PROFILE
)) {
462 some_field_affected
= 1;
463 pdb_sql_string_field(query
,
464 config_value_write(location
,
465 "profile path column",
466 CONFIG_PROFILE_PATH_DEFAULT
),
467 pdb_get_profile_path(newpwd
));
470 if (IS_SAM_CHANGED(newpwd
, PDB_DRIVE
)) {
471 some_field_affected
= 1;
472 pdb_sql_string_field(query
,
473 config_value_write(location
, "dir drive column",
474 CONFIG_DIR_DRIVE_DEFAULT
),
475 pdb_get_dir_drive(newpwd
));
478 if (IS_SAM_CHANGED(newpwd
, PDB_SMBHOME
)) {
479 some_field_affected
= 1;
480 pdb_sql_string_field(query
,
481 config_value_write(location
, "home dir column",
482 CONFIG_HOME_DIR_DEFAULT
),
483 pdb_get_homedir(newpwd
));
486 if (IS_SAM_CHANGED(newpwd
, PDB_WORKSTATIONS
)) {
487 some_field_affected
= 1;
488 pdb_sql_string_field(query
,
489 config_value_write(location
,
490 "workstations column",
491 CONFIG_WORKSTATIONS_DEFAULT
),
492 pdb_get_workstations(newpwd
));
495 if (IS_SAM_CHANGED(newpwd
, PDB_UNKNOWNSTR
)) {
496 some_field_affected
= 1;
497 pdb_sql_string_field(query
,
498 config_value_write(location
,
499 "unknown string column",
500 CONFIG_UNKNOWN_STR_DEFAULT
),
501 pdb_get_workstations(newpwd
));
504 if (IS_SAM_CHANGED(newpwd
, PDB_LMPASSWD
)) {
505 some_field_affected
= 1;
506 pdb_sethexpwd(temp
, pdb_get_lanman_passwd(newpwd
),
507 pdb_get_acct_ctrl(newpwd
));
508 pdb_sql_string_field(query
,
509 config_value_write(location
,
510 "lanman pass column",
511 CONFIG_LM_PW_DEFAULT
), temp
);
514 if (IS_SAM_CHANGED(newpwd
, PDB_NTPASSWD
)) {
515 some_field_affected
= 1;
516 pdb_sethexpwd(temp
, pdb_get_nt_passwd(newpwd
),
517 pdb_get_acct_ctrl(newpwd
));
518 pdb_sql_string_field(query
,
519 config_value_write(location
, "nt pass column",
520 CONFIG_NT_PW_DEFAULT
), temp
);
523 if (IS_SAM_CHANGED(newpwd
, PDB_HOURS
)) {
524 some_field_affected
= 1;
525 pdb_sql_string_field(query
,
526 config_value_write(location
,
527 "logon hours column",
529 pdb_get_hours(newpwd
));
532 if (!some_field_affected
) {
538 query
->part1
[strlen(query
->part1
) - 1] = '\0';
540 talloc_asprintf_append(query
->part1
,
542 config_value_read(location
,
544 CONFIG_USER_SID_DEFAULT
),
545 sid_to_string(sid_str
, pdb_get_user_sid (newpwd
)));
547 query
->part2
[strlen(query
->part2
) - 1] = ')';
548 query
->part1
[strlen(query
->part1
) - 1] = ')';
550 talloc_asprintf_append(query
->part1
,
551 " VALUES (%s", query
->part2
);
554 ret
= talloc_strdup(mem_ctx
, query
->part1
);
559 BOOL
sql_account_config_valid(const char *data
)
561 const char *sid_column
, *username_column
;
563 sid_column
= config_value_read(data
, "user sid column", CONFIG_USER_SID_DEFAULT
);
564 username_column
= config_value_read(data
, "username column", CONFIG_USERNAME_DEFAULT
);
566 if(!strcmp(sid_column
,"NULL") || !strcmp(username_column
, "NULL")) {
567 DEBUG(0,("Please specify both a valid 'user sid column' and a valid 'username column' in smb.conf\n"));