diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2004-01-04 21:09:42 +0000 |
---|---|---|
committer | Jelmer Vernooij <jelmer@samba.org> | 2004-01-04 21:09:42 +0000 |
commit | 430f9abd5f1d2537eab17c7c51a9e9b09f415989 (patch) | |
tree | b0feef1b65e19c6f85303ab390e77b93671fda68 /source3/passdb/pdb_sql.c | |
parent | fd35232584d34c3250094572393b3a64fc87cef9 (diff) | |
download | samba-430f9abd5f1d2537eab17c7c51a9e9b09f415989.tar.gz samba-430f9abd5f1d2537eab17c7c51a9e9b09f415989.tar.xz samba-430f9abd5f1d2537eab17c7c51a9e9b09f415989.zip |
- Put functions for generating SQL queries in pdb_sql.c
- Add pgSQL backend (based on patch by Hamish Friedlander)
- Use query generate functions from pdb_mysql and pdb_pgsql
- Only pdb_pgsql.c needs to be changed whenever the fields in SAM_ACCOUNT change
(This used to be commit 65ad2c02fd2bf36d535c279ad290ab81e39f6816)
Diffstat (limited to 'source3/passdb/pdb_sql.c')
-rw-r--r-- | source3/passdb/pdb_sql.c | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/source3/passdb/pdb_sql.c b/source3/passdb/pdb_sql.c new file mode 100644 index 00000000000..b87004e0193 --- /dev/null +++ b/source3/passdb/pdb_sql.c @@ -0,0 +1,496 @@ +/* + * Common PDB SQL backend functions + * Copyright (C) Jelmer Vernooij 2003-2004 + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 675 + * Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#define CONFIG_TABLE_DEFAULT "user" +#define CONFIG_LOGON_TIME_DEFAULT "logon_time" +#define CONFIG_LOGOFF_TIME_DEFAULT "logoff_time" +#define CONFIG_KICKOFF_TIME_DEFAULT "kickoff_time" +#define CONFIG_PASS_LAST_SET_TIME_DEFAULT "pass_last_set_time" +#define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT "pass_can_change_time" +#define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT "pass_must_change_time" +#define CONFIG_USERNAME_DEFAULT "username" +#define CONFIG_DOMAIN_DEFAULT "domain" +#define CONFIG_NT_USERNAME_DEFAULT "nt_username" +#define CONFIG_FULLNAME_DEFAULT "nt_fullname" +#define CONFIG_HOME_DIR_DEFAULT "home_dir" +#define CONFIG_DIR_DRIVE_DEFAULT "dir_drive" +#define CONFIG_LOGON_SCRIPT_DEFAULT "logon_script" +#define CONFIG_PROFILE_PATH_DEFAULT "profile_path" +#define CONFIG_ACCT_DESC_DEFAULT "acct_desc" +#define CONFIG_WORKSTATIONS_DEFAULT "workstations" +#define CONFIG_UNKNOWN_STR_DEFAULT "unknown_str" +#define CONFIG_MUNGED_DIAL_DEFAULT "munged_dial" +#define CONFIG_USER_SID_DEFAULT "user_sid" +#define CONFIG_GROUP_SID_DEFAULT "group_sid" +#define CONFIG_LM_PW_DEFAULT "lm_pw" +#define CONFIG_NT_PW_DEFAULT "nt_pw" +#define CONFIG_PLAIN_PW_DEFAULT "NULL" +#define CONFIG_ACCT_CTRL_DEFAULT "acct_ctrl" +#define CONFIG_UNKNOWN_3_DEFAULT "unknown_3" +#define CONFIG_LOGON_DIVS_DEFAULT "logon_divs" +#define CONFIG_HOURS_LEN_DEFAULT "hours_len" +#define CONFIG_BAD_PASSWORD_COUNT_DEFAULT "bad_password_count" +#define CONFIG_LOGON_COUNT_DEFAULT "logon_count" +#define CONFIG_UNKNOWN_6_DEFAULT "unknown_6" + +/* Used to construct insert and update queries */ + +typedef struct pdb_sql_query { + char update; + TALLOC_CTX *mem_ctx; + char *part1; + char *part2; +} pdb_sql_query; + +static void pdb_sql_int_field(struct pdb_sql_query *q, const char *name, int value) +{ + if (!name || strchr(name, '\'')) + return; /* This field shouldn't be set by us */ + + if (q->update) { + q->part1 = + talloc_asprintf_append(q->mem_ctx, q->part1, + "%s = %d,", name, value); + } else { + q->part1 = + talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name); + q->part2 = + talloc_asprintf_append(q->mem_ctx, q->part2, "%d,", value); + } +} + +char *sql_escape_string(const char *unesc) +{ + char *esc = malloc(strlen(unesc) * 2 + 3); + size_t pos_unesc = 0, pos_esc = 0; + + for(pos_unesc = 0; unesc[pos_unesc]; pos_unesc++) { + switch(unesc[pos_unesc]) { + case '\\': + case '\'': + case '"': + esc[pos_esc] = '\\'; pos_esc++; + default: + esc[pos_esc] = unesc[pos_unesc]; pos_esc++; + break; + } + } + + esc[pos_esc] = '\0'; + + return esc; +} + +static NTSTATUS pdb_sql_string_field(struct pdb_sql_query *q, + const char *name, const char *value) +{ + char *esc_value; + + if (!name || !value || !strcmp(value, "") || strchr(name, '\'')) + return NT_STATUS_INVALID_PARAMETER; /* This field shouldn't be set by module */ + + esc_value = sql_escape_string(value); + + if (q->update) { + q->part1 = + talloc_asprintf_append(q->mem_ctx, q->part1, + "%s = '%s',", name, esc_value); + } else { + q->part1 = + talloc_asprintf_append(q->mem_ctx, q->part1, "%s,", name); + q->part2 = + talloc_asprintf_append(q->mem_ctx, q->part2, "'%s',", + esc_value); + } + + SAFE_FREE(esc_value); + + return NT_STATUS_OK; +} + +#define config_value(data,name,default_value) \ + lp_parm_const_string(GLOBAL_SECTION_SNUM, data, name, default_value) + +static const char * config_value_write(const char *location, const char *name, const char *default_value) +{ + char const *v = NULL; + char const *swrite = NULL; + + v = lp_parm_const_string(GLOBAL_SECTION_SNUM, location, name, default_value); + + if (!v) + return NULL; + + swrite = strrchr(v, ':'); + + /* Default to the same field as read field */ + if (!swrite) + return v; + + swrite++; + + /* If the field is 0 chars long, we shouldn't write to it */ + if (!strlen(swrite) || !strcmp(swrite, "NULL")) + return NULL; + + /* Otherwise, use the additionally specified */ + return swrite; +} + +static const char * config_value_read(const char *location, const char *name, const char *default_value) +{ + char *v = NULL; + char *swrite; + + v = lp_parm_talloc_string(GLOBAL_SECTION_SNUM, location, name, default_value); + + if (!v) + return "NULL"; + + swrite = strrchr(v, ':'); + + /* If no write is specified, there are no problems */ + if (!swrite) { + if (strlen(v) == 0) + return "NULL"; + return (const char *)v; + } + + /* Otherwise, we have to cut the ':write_part' */ + *swrite = '\0'; + if (strlen(v) == 0) + return "NULL"; + + return (const char *)v; +} + +char *sql_account_query_select(const char *data, BOOL update, enum sql_search_field field, const char *value) +{ + const char *field_string; + char *query; + + switch(field) { + case SQL_SEARCH_NONE: + field_string = "'1'"; + value = "1"; + break; + + case SQL_SEARCH_USER_SID: + field_string = config_value_read(data, "user sid column", + CONFIG_USER_SID_DEFAULT); + break; + + case SQL_SEARCH_USER_NAME: + field_string = config_value_read(data, "username column", + CONFIG_USERNAME_DEFAULT); + break; + } + + asprintf(&query, + "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'", + config_value_read(data, "logon time column", + CONFIG_LOGON_TIME_DEFAULT), + config_value_read(data, "logoff time column", + CONFIG_LOGOFF_TIME_DEFAULT), + config_value_read(data, "kickoff time column", + CONFIG_KICKOFF_TIME_DEFAULT), + config_value_read(data, "pass last set time column", + CONFIG_PASS_LAST_SET_TIME_DEFAULT), + config_value_read(data, "pass can change time column", + CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT), + config_value_read(data, "pass must change time column", + CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT), + config_value_read(data, "username column", + CONFIG_USERNAME_DEFAULT), + config_value_read(data, "domain column", + CONFIG_DOMAIN_DEFAULT), + config_value_read(data, "nt username column", + CONFIG_NT_USERNAME_DEFAULT), + config_value_read(data, "fullname column", + CONFIG_FULLNAME_DEFAULT), + config_value_read(data, "home dir column", + CONFIG_HOME_DIR_DEFAULT), + config_value_read(data, "dir drive column", + CONFIG_DIR_DRIVE_DEFAULT), + config_value_read(data, "logon script column", + CONFIG_LOGON_SCRIPT_DEFAULT), + config_value_read(data, "profile path column", + CONFIG_PROFILE_PATH_DEFAULT), + config_value_read(data, "acct desc column", + CONFIG_ACCT_DESC_DEFAULT), + config_value_read(data, "workstations column", + CONFIG_WORKSTATIONS_DEFAULT), + config_value_read(data, "unknown string column", + CONFIG_UNKNOWN_STR_DEFAULT), + config_value_read(data, "munged dial column", + CONFIG_MUNGED_DIAL_DEFAULT), + config_value_read(data, "user sid column", + CONFIG_USER_SID_DEFAULT), + config_value_read(data, "group sid column", + CONFIG_GROUP_SID_DEFAULT), + config_value_read(data, "lanman pass column", + CONFIG_LM_PW_DEFAULT), + config_value_read(data, "nt pass column", + CONFIG_NT_PW_DEFAULT), + config_value_read(data, "plain pass column", + CONFIG_PLAIN_PW_DEFAULT), + config_value_read(data, "acct ctrl column", + CONFIG_ACCT_CTRL_DEFAULT), + config_value_read(data, "unknown 3 column", + CONFIG_UNKNOWN_3_DEFAULT), + config_value_read(data, "logon divs column", + CONFIG_LOGON_DIVS_DEFAULT), + config_value_read(data, "hours len column", + CONFIG_HOURS_LEN_DEFAULT), + config_value_read(data, "bad password count column", + CONFIG_BAD_PASSWORD_COUNT_DEFAULT), + config_value_read(data, "logon count column", + CONFIG_LOGON_COUNT_DEFAULT), + config_value_read(data, "unknown 6 column", + CONFIG_UNKNOWN_6_DEFAULT), + config_value(data, "table", CONFIG_TABLE_DEFAULT), + field_string, value + ); + return query; +} + +char *sql_account_query_delete(const char *data, const char *esc) +{ + char *query; + + asprintf(&query, "DELETE FROM %s WHERE %s = '%s'", + config_value(data, "table", CONFIG_TABLE_DEFAULT), + config_value_read(data, "username column", + CONFIG_USERNAME_DEFAULT), esc); + return query; +} + +char *sql_account_query_update(const char *location, const SAM_ACCOUNT *newpwd, char isupdate) +{ + char *ret; + pstring temp; + pdb_sql_query query; + fstring sid_str; + + query.update = isupdate; + + /* I know this is somewhat overkill but only the talloc + * functions have asprint_append and the 'normal' asprintf + * is a GNU extension */ + query.mem_ctx = talloc_init("sql_query_update"); + query.part2 = talloc_asprintf(query.mem_ctx, "%s", ""); + if (query.update) { + query.part1 = + talloc_asprintf(query.mem_ctx, "UPDATE %s SET ", + config_value(location, "table", + CONFIG_TABLE_DEFAULT)); + } else { + query.part1 = + talloc_asprintf(query.mem_ctx, "INSERT INTO %s (", + config_value(location, "table", + CONFIG_TABLE_DEFAULT)); + } + + pdb_sql_int_field(&query, + config_value_write(location, "acct ctrl column", + CONFIG_ACCT_CTRL_DEFAULT), + pdb_get_acct_ctrl(newpwd)); + + if (pdb_get_init_flags(newpwd, PDB_LOGONTIME) != PDB_DEFAULT) { + pdb_sql_int_field(&query, + config_value_write(location, + "logon time column", + CONFIG_LOGON_TIME_DEFAULT), + pdb_get_logon_time(newpwd)); + } + + if (pdb_get_init_flags(newpwd, PDB_LOGOFFTIME) != PDB_DEFAULT) { + pdb_sql_int_field(&query, + config_value_write(location, + "logoff time column", + CONFIG_LOGOFF_TIME_DEFAULT), + pdb_get_logoff_time(newpwd)); + } + + if (pdb_get_init_flags(newpwd, PDB_KICKOFFTIME) != PDB_DEFAULT) { + pdb_sql_int_field(&query, + config_value_write(location, + "kickoff time column", + CONFIG_KICKOFF_TIME_DEFAULT), + pdb_get_kickoff_time(newpwd)); + } + + if (pdb_get_init_flags(newpwd, PDB_CANCHANGETIME) != PDB_DEFAULT) { + pdb_sql_int_field(&query, + config_value_write(location, + "pass can change time column", + CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT), + pdb_get_pass_can_change_time(newpwd)); + } + + if (pdb_get_init_flags(newpwd, PDB_MUSTCHANGETIME) != PDB_DEFAULT) { + pdb_sql_int_field(&query, + config_value_write(location, + "pass must change time column", + CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT), + pdb_get_pass_must_change_time(newpwd)); + } + + if (pdb_get_pass_last_set_time(newpwd)) { + pdb_sql_int_field(&query, + config_value_write(location, + "pass last set time column", + CONFIG_PASS_LAST_SET_TIME_DEFAULT), + pdb_get_pass_last_set_time(newpwd)); + } + + if (pdb_get_hours_len(newpwd)) { + pdb_sql_int_field(&query, + config_value_write(location, + "hours len column", + CONFIG_HOURS_LEN_DEFAULT), + pdb_get_hours_len(newpwd)); + } + + if (pdb_get_logon_divs(newpwd)) { + pdb_sql_int_field(&query, + config_value_write(location, + "logon divs column", + CONFIG_LOGON_DIVS_DEFAULT), + pdb_get_logon_divs(newpwd)); + } + + pdb_sql_string_field(&query, + config_value_write(location, "user sid column", + CONFIG_USER_SID_DEFAULT), + sid_to_string(sid_str, + pdb_get_user_sid(newpwd))); + + pdb_sql_string_field(&query, + config_value_write(location, "group sid column", + CONFIG_GROUP_SID_DEFAULT), + sid_to_string(sid_str, + pdb_get_group_sid(newpwd))); + + pdb_sql_string_field(&query, + config_value_write(location, "username column", + CONFIG_USERNAME_DEFAULT), + pdb_get_username(newpwd)); + + pdb_sql_string_field(&query, + config_value_write(location, "domain column", + CONFIG_DOMAIN_DEFAULT), + pdb_get_domain(newpwd)); + + pdb_sql_string_field(&query, + config_value_write(location, + "nt username column", + CONFIG_NT_USERNAME_DEFAULT), + pdb_get_nt_username(newpwd)); + + pdb_sql_string_field(&query, + config_value_write(location, "fullname column", + CONFIG_FULLNAME_DEFAULT), + pdb_get_fullname(newpwd)); + + pdb_sql_string_field(&query, + config_value_write(location, + "logon script column", + CONFIG_LOGON_SCRIPT_DEFAULT), + pdb_get_logon_script(newpwd)); + + pdb_sql_string_field(&query, + config_value_write(location, + "profile path column", + CONFIG_PROFILE_PATH_DEFAULT), + pdb_get_profile_path(newpwd)); + + pdb_sql_string_field(&query, + config_value_write(location, "dir drive column", + CONFIG_DIR_DRIVE_DEFAULT), + pdb_get_dir_drive(newpwd)); + + pdb_sql_string_field(&query, + config_value_write(location, "home dir column", + CONFIG_HOME_DIR_DEFAULT), + pdb_get_homedir(newpwd)); + + pdb_sql_string_field(&query, + config_value_write(location, + "workstations column", + CONFIG_WORKSTATIONS_DEFAULT), + pdb_get_workstations(newpwd)); + + pdb_sql_string_field(&query, + config_value_write(location, + "unknown string column", + CONFIG_UNKNOWN_STR_DEFAULT), + pdb_get_workstations(newpwd)); + + pdb_sethexpwd(temp, pdb_get_lanman_passwd(newpwd), + pdb_get_acct_ctrl(newpwd)); + pdb_sql_string_field(&query, + config_value_write(location, + "lanman pass column", + CONFIG_LM_PW_DEFAULT), temp); + + pdb_sethexpwd(temp, pdb_get_nt_passwd(newpwd), + pdb_get_acct_ctrl(newpwd)); + pdb_sql_string_field(&query, + config_value_write(location, "nt pass column", + CONFIG_NT_PW_DEFAULT), temp); + + if (query.update) { + query.part1[strlen(query.part1) - 1] = '\0'; + query.part1 = + talloc_asprintf_append(query.mem_ctx, query.part1, + " WHERE %s = '%s'", + config_value_read(location, + "user sid column", + CONFIG_USER_SID_DEFAULT), + sid_to_string(sid_str, pdb_get_user_sid (newpwd))); + } else { + query.part2[strlen(query.part2) - 1] = ')'; + query.part1[strlen(query.part1) - 1] = ')'; + query.part1 = + talloc_asprintf_append(query.mem_ctx, query.part1, + " VALUES (%s", query.part2); + } + + ret = strdup(query.part1); + talloc_destroy(query.mem_ctx); + return ret; +} + +BOOL sql_account_config_valid(const char *data) +{ + const char *sid_column, *username_column; + + sid_column = config_value_read(data, "user sid column", CONFIG_USER_SID_DEFAULT); + username_column = config_value_read(data, "username column", CONFIG_USERNAME_DEFAULT); + + if(!strcmp(sid_column,"NULL") || !strcmp(username_column, "NULL")) { + DEBUG(0,("Please specify both a valid 'user sid column' and a valid 'username column' in smb.conf\n")); + return False; + } + + return True; +} |