--- passdb/pdb_pgsql.c.orig Fri Mar 11 10:47:04 2005 +++ passdb/pdb_pgsql.c Wed Apr 13 11:02:42 2005 @@ -29,41 +29,99 @@ /* handles for doing db transactions */ typedef struct pdb_pgsql_data { + PGconn *master_handle ; PGconn *handle ; + PGresult *pwent ; long currow ; + const char *db ; + const char *host ; + const char *port ; + const char *user ; + const char *pass ; const char *location ; } pdb_pgsql_data ; +struct pdb_context *the_pdb_context; + #define SET_DATA(data,methods) { \ if(!methods){ \ DEBUG(0, ("invalid methods!\n")); \ return NT_STATUS_INVALID_PARAMETER; \ } \ data = (struct pdb_pgsql_data *)methods->private_data; \ - if(!data || !(data->handle)){ \ - DEBUG(0, ("invalid handle!\n")); \ - return NT_STATUS_INVALID_HANDLE; \ - } \ } + #define SET_DATA_QUIET(data,methods) { \ if(!methods){ \ DEBUG(0, ("invalid methods!\n")); \ return ; \ } \ - data = (struct pdb_pgsql_data *)methods->private_data; \ - if(!data || !(data->handle)){ \ - DEBUG(0, ("invalid handle!\n")); \ - return ; \ - } \ + data = (struct pdb_pgsql_data *)methods->private_data;\ } - #define config_value( data, name, default_value ) \ lp_parm_const_string( GLOBAL_SECTION_SNUM, (data)->location, name, default_value ) +static PGconn *pgsqlsam_connect( struct pdb_pgsql_data *data ) +{ + PGconn *handle; + + DEBUG + ( + 1, + ( + "Connecting to database server, host: %s, user: %s, password: XXXXXX, database: %s, port: %s\n", + data->host, data->user, data->db, data->port + ) + ) ; + + /* Do the pgsql initialization */ + handle = PQsetdbLogin( + data->host, + data->port, + NULL, + NULL, + data->db, + data->user, + data->pass + ) ; + + if ( handle != NULL && PQstatus( handle ) != CONNECTION_OK ) + { + DEBUG( 0, ("Failed to connect to pgsql database: error: %s\n", + (handle != NULL ? PQerrorMessage( handle ) : "")) ) ; + return NULL; + } + + DEBUG( 5, ("Connected to pgsql database\n") ) ; + return handle; +} + +/* The assumption here is that the master process will get connection 0, + * and all the renaining ones just one connection for their etire life span. + */ +static PGconn *choose_connection( struct pdb_pgsql_data *data ) +{ + if ( data->master_handle == NULL ) + { + data->master_handle = pgsqlsam_connect( data ); + return data->master_handle ; + } + + /* Master connection != NULL, so we are just another process. */ + + /* If we didn't connect yet, do it now. */ + if ( data->handle == NULL ) + { + data->handle = pgsqlsam_connect( data ); + } + + return data->handle ; +} + static long PQgetlong( PGresult *r, long row, long col ) { if ( PQgetisnull( r, row, col ) ) return 0 ; @@ -100,8 +158,8 @@ pdb_set_acct_ctrl ( u, PQgetlong ( r, row, 23 ), PDB_SET ) ; pdb_set_logon_divs ( u, PQgetlong ( r, row, 24 ), PDB_SET ) ; pdb_set_hours_len ( u, PQgetlong ( r, row, 25 ), PDB_SET ) ; - pdb_set_bad_password_count ( u, PQgetlong (r, row, 26 ), PDB_SET ) ; - pdb_set_logon_count ( u, PQgetlong ( r, row, 27 ), PDB_SET ) ; + pdb_set_bad_password_count ( u, PQgetlong ( r, row, 26 ), PDB_SET ) ; + pdb_set_logon_count ( u, PQgetlong ( r, row, 27 ), PDB_SET ) ; pdb_set_unknown_6 ( u, PQgetlong ( r, row, 28 ), PDB_SET ) ; if ( !PQgetisnull( r, row, 18 ) ) { @@ -126,22 +184,29 @@ static NTSTATUS pgsqlsam_setsampwent(struct pdb_methods *methods, BOOL update, uint16 acb_mask) { struct pdb_pgsql_data *data ; + PGconn *handle ; char *query ; NTSTATUS retval ; SET_DATA( data, methods ) ; + + /* Connect to the DB. */ + handle = choose_connection( data ); + if ( handle == NULL ) + return NT_STATUS_UNSUCCESSFUL ; + DEBUG( 5, ("CONNECTING pgsqlsam_setsampwent\n") ) ; query = sql_account_query_select(data->location, update, SQL_SEARCH_NONE, NULL); /* Do it */ DEBUG( 5, ("Executing query %s\n", query) ) ; - data->pwent = PQexec( data->handle, query ) ; + data->pwent = PQexec( handle, query ) ; data->currow = 0 ; /* Result? */ if ( data->pwent == NULL ) { - DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( data->handle ) ) ) ; + DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( handle ) ) ) ; retval = NT_STATUS_UNSUCCESSFUL ; } else if ( PQresultStatus( data->pwent ) != PGRES_TUPLES_OK ) @@ -154,8 +219,10 @@ DEBUG( 5, ("pgsqlsam_setsampwent succeeded(%d results)!\n", PQntuples(data->pwent)) ) ; retval = NT_STATUS_OK ; } - + SAFE_FREE(query); + if ( data->pwent != NULL ) + PQclear( data->pwent ) ; return retval ; } @@ -206,6 +273,7 @@ static NTSTATUS pgsqlsam_select_by_field ( struct pdb_methods *methods, SAM_ACCOUNT *user, enum sql_search_field field, const char *sname ) { struct pdb_pgsql_data *data ; + PGconn *handle ; char *esc ; char *query ; @@ -233,17 +301,22 @@ //tmp_sname = smb_xstrdup(sname); PQescapeString( esc, sname, strlen(sname) ) ; + + /* Connect to the DB. */ + handle = choose_connection( data ); + if ( handle == NULL ) + return NT_STATUS_UNSUCCESSFUL ; query = sql_account_query_select(data->location, True, field, esc); /* Do it */ DEBUG( 5, ("Executing query %s\n", query) ) ; - result = PQexec( data->handle, query ) ; + result = PQexec( handle, query ) ; /* Result? */ if ( result == NULL ) { - DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( data->handle ) ) ) ; + DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( handle ) ) ) ; retval = NT_STATUS_UNSUCCESSFUL ; } else if ( PQresultStatus( result ) != PGRES_TUPLES_OK ) @@ -258,8 +331,9 @@ SAFE_FREE( esc ) ; SAFE_FREE( query ) ; - - PQclear( result ) ; + + if ( result != NULL ) + PQclear( result ) ; return retval ; } @@ -271,6 +345,9 @@ static NTSTATUS pgsqlsam_getsampwnam ( struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname ) { struct pdb_pgsql_data *data; + size_t i, l; + char *lowercasename; + NTSTATUS result; SET_DATA(data, methods); @@ -279,8 +356,18 @@ DEBUG( 0, ("invalid name specified") ) ; return NT_STATUS_INVALID_PARAMETER; } + + lowercasename = smb_xstrdup(sname); + l = strlen(lowercasename); + for(i = 0; i < l; i++) { + lowercasename[i] = tolower(lowercasename[i]); + } - return pgsqlsam_select_by_field( methods, user, SQL_SEARCH_USER_NAME, sname ) ; + result = pgsqlsam_select_by_field( methods, user, SQL_SEARCH_USER_NAME, lowercasename ) ; + + SAFE_FREE( lowercasename ) ; + + return result; } @@ -307,6 +394,7 @@ static NTSTATUS pgsqlsam_delete_sam_account( struct pdb_methods *methods, SAM_ACCOUNT *sam_pass ) { struct pdb_pgsql_data *data ; + PGconn *handle ; const char *sname = pdb_get_username( sam_pass ) ; char *esc ; @@ -332,15 +420,20 @@ } PQescapeString( esc, sname, strlen(sname) ) ; + + /* Connect to the DB. */ + handle = choose_connection( data ); + if ( handle == NULL ) + return NT_STATUS_UNSUCCESSFUL ; query = sql_account_query_delete(data->location, esc); /* Do it */ - result = PQexec( data->handle, query ) ; + result = PQexec( handle, query ) ; if ( result == NULL ) { - DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( data->handle ) ) ) ; + DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( handle ) ) ) ; retval = NT_STATUS_UNSUCCESSFUL ; } else if ( PQresultStatus( result ) != PGRES_COMMAND_OK ) @@ -354,6 +447,8 @@ retval = NT_STATUS_OK ; } + if ( result != NULL ) + PQclear( result ) ; SAFE_FREE( esc ) ; SAFE_FREE( query ) ; @@ -363,8 +458,10 @@ static NTSTATUS pgsqlsam_replace_sam_account( struct pdb_methods *methods, const SAM_ACCOUNT *newpwd, char isupdate ) { struct pdb_pgsql_data *data ; + PGconn *handle ; char *query; PGresult *result ; + NTSTATUS retval ; if ( !methods ) { @@ -374,31 +471,43 @@ data = (struct pdb_pgsql_data *) methods->private_data ; - if ( data == NULL || data->handle == NULL ) + if ( data == NULL || handle == NULL ) { DEBUG( 0, ("invalid handle!\n") ) ; return NT_STATUS_INVALID_HANDLE ; } query = sql_account_query_update(data->location, newpwd, isupdate); + if ( query == NULL ) /* Nothing to update. */ + return NT_STATUS_OK; - result = PQexec( data->handle, query ) ; + /* Connect to the DB. */ + handle = choose_connection( data ); + if ( handle == NULL ) + return NT_STATUS_UNSUCCESSFUL ; + result = PQexec( handle, query ) ; /* Execute the query */ if ( result == NULL ) { - DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( data->handle ) ) ) ; - return NT_STATUS_INVALID_PARAMETER; + DEBUG( 0, ("Error executing %s, %s\n", query, PQerrorMessage( handle ) ) ) ; + retval = NT_STATUS_INVALID_PARAMETER; } else if ( PQresultStatus( result ) != PGRES_COMMAND_OK ) { DEBUG( 0, ("Error executing %s, %s\n", query, PQresultErrorMessage( result ) ) ) ; - return NT_STATUS_INVALID_PARAMETER; + retval = NT_STATUS_INVALID_PARAMETER; + } + else + { + retval = NT_STATUS_OK; } + if ( result != NULL ) + PQclear( result ) ; SAFE_FREE(query); - return NT_STATUS_OK; + return retval; } static NTSTATUS pgsqlsam_add_sam_account ( struct pdb_methods *methods, SAM_ACCOUNT *newpwd ) @@ -422,6 +531,8 @@ return NT_STATUS_UNSUCCESSFUL; } + the_pdb_context = pdb_context; + if (!NT_STATUS_IS_OK (nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { return nt_status; @@ -440,7 +551,9 @@ data = talloc( pdb_context->mem_ctx, sizeof( struct pdb_pgsql_data ) ) ; (*pdb_method)->private_data = data ; - data->handle = NULL ; + + data->master_handle = NULL; + data->handle = NULL; data->pwent = NULL ; if ( !location ) @@ -448,43 +561,33 @@ DEBUG( 0, ("No identifier specified. Check the Samba HOWTO Collection for details\n") ) ; return NT_STATUS_INVALID_PARAMETER; } - + data->location = smb_xstrdup( location ) ; if(!sql_account_config_valid(data->location)) { - return NT_STATUS_INVALID_PARAMETER; + return NT_STATUS_INVALID_PARAMETER; } - + DEBUG ( - 1, + 1, ( - "Connecting to database server, host: %s, user: %s, password: XXXXXX, database: %s, port: %s\n", - config_value( data, "pgsql host" , CONFIG_HOST_DEFAULT ), - config_value( data, "pgsql user" , CONFIG_USER_DEFAULT ), - config_value( data, "pgsql database", CONFIG_DB_DEFAULT ), - config_value( data, "pgsql port" , CONFIG_PORT_DEFAULT ) + "Database server parameters: host: %s, user: %s, password: XXXX, database: %s, port: %s\n", + config_value( data, "pgsql host" , CONFIG_HOST_DEFAULT ), + config_value( data, "pgsql user" , CONFIG_USER_DEFAULT ), + config_value( data, "pgsql database", CONFIG_DB_DEFAULT ), + config_value( data, "pgsql port" , CONFIG_PORT_DEFAULT ) ) ) ; - - /* Do the pgsql initialization */ - data->handle = PQsetdbLogin( - config_value( data, "pgsql host" , CONFIG_HOST_DEFAULT ), - config_value( data, "pgsql port" , CONFIG_PORT_DEFAULT ), - NULL, - NULL, - config_value( data, "pgsql database", CONFIG_DB_DEFAULT ), - config_value( data, "pgsql user" , CONFIG_USER_DEFAULT ), - config_value( data, "pgsql password", CONFIG_PASS_DEFAULT ) - ) ; - - if ( PQstatus( data->handle ) != CONNECTION_OK ) - { - DEBUG( 0, ("Failed to connect to pgsql database: error: %s\n", PQerrorMessage( data->handle )) ) ; - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG( 5, ("Connected to pgsql database\n") ) ; + + /* Save the parameters. */ + data->db = config_value( data, "pgsql database", CONFIG_DB_DEFAULT ); + data->host = config_value( data, "pgsql host" , CONFIG_HOST_DEFAULT ); + data->port = config_value( data, "pgsql port" , CONFIG_PORT_DEFAULT ); + data->user = config_value( data, "pgsql user" , CONFIG_USER_DEFAULT ); + data->pass = config_value( data, "pgsql password", CONFIG_PASS_DEFAULT ); + + DEBUG( 5, ("Pgsql module intialized\n") ) ; return NT_STATUS_OK; } --- passdb/pdb_mysql.c.orig Fri Feb 25 14:59:36 2005 +++ passdb/pdb_mysql.c Mon Apr 11 11:49:35 2005 @@ -382,6 +382,8 @@ } query = sql_account_query_update(data->location, newpwd, isupdate); + if ( query == NULL ) /* Nothing to update. */ + return NT_STATUS_OK; /* Execute the query */ if (mysql_query(data->handle, query)) { --- passdb/pdb_sql.c.orig Fri Mar 11 10:47:04 2005 +++ passdb/pdb_sql.c Mon Apr 11 11:49:35 2005 @@ -295,6 +295,7 @@ pstring temp; pdb_sql_query query; fstring sid_str; + int some_field_affected = 0; query.update = isupdate; @@ -316,6 +317,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_ACCTCTRL)) { + some_field_affected = 1; pdb_sql_int_field(&query, config_value_write(location, "acct ctrl column", CONFIG_ACCT_CTRL_DEFAULT), @@ -323,6 +325,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_LOGONTIME)) { + some_field_affected = 1; pdb_sql_int_field(&query, config_value_write(location, "logon time column", @@ -331,6 +334,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_LOGOFFTIME)) { + some_field_affected = 1; pdb_sql_int_field(&query, config_value_write(location, "logoff time column", @@ -339,6 +343,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_KICKOFFTIME)) { + some_field_affected = 1; pdb_sql_int_field(&query, config_value_write(location, "kickoff time column", @@ -347,6 +352,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_CANCHANGETIME)) { + some_field_affected = 1; pdb_sql_int_field(&query, config_value_write(location, "pass can change time column", @@ -355,6 +361,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_MUSTCHANGETIME)) { + some_field_affected = 1; pdb_sql_int_field(&query, config_value_write(location, "pass must change time column", @@ -363,6 +370,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_PASSLASTSET)) { + some_field_affected = 1; pdb_sql_int_field(&query, config_value_write(location, "pass last set time column", @@ -371,6 +379,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_HOURSLEN)) { + some_field_affected = 1; pdb_sql_int_field(&query, config_value_write(location, "hours len column", @@ -379,6 +388,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_LOGONDIVS)) { + some_field_affected = 1; pdb_sql_int_field(&query, config_value_write(location, "logon divs column", @@ -387,6 +397,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_USERSID)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "user sid column", CONFIG_USER_SID_DEFAULT), @@ -395,6 +406,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_GROUPSID)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "group sid column", CONFIG_GROUP_SID_DEFAULT), @@ -403,6 +415,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_USERNAME)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "username column", CONFIG_USERNAME_DEFAULT), @@ -410,6 +423,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_DOMAIN)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "domain column", CONFIG_DOMAIN_DEFAULT), @@ -417,6 +431,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_USERNAME)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "nt username column", @@ -425,6 +440,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_FULLNAME)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "fullname column", CONFIG_FULLNAME_DEFAULT), @@ -432,6 +448,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_LOGONSCRIPT)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "logon script column", @@ -440,6 +457,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_PROFILE)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "profile path column", @@ -448,6 +466,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_DRIVE)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "dir drive column", CONFIG_DIR_DRIVE_DEFAULT), @@ -455,6 +474,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_SMBHOME)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "home dir column", CONFIG_HOME_DIR_DEFAULT), @@ -462,6 +482,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_WORKSTATIONS)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "workstations column", @@ -470,6 +491,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_UNKNOWNSTR)) { + some_field_affected = 1; pdb_sql_string_field(&query, config_value_write(location, "unknown string column", @@ -478,6 +500,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_LMPASSWD)) { + some_field_affected = 1; pdb_sethexpwd(temp, pdb_get_lanman_passwd(newpwd), pdb_get_acct_ctrl(newpwd)); pdb_sql_string_field(&query, @@ -487,6 +510,7 @@ } if (IS_SAM_CHANGED(newpwd, PDB_NTPASSWD)) { + some_field_affected = 1; pdb_sethexpwd(temp, pdb_get_nt_passwd(newpwd), pdb_get_acct_ctrl(newpwd)); pdb_sql_string_field(&query, @@ -494,6 +518,11 @@ CONFIG_NT_PW_DEFAULT), temp); } + if (!some_field_affected) { + talloc_destroy(query.mem_ctx); + return NULL; + } + if (query.update) { query.part1[strlen(query.part1) - 1] = '\0'; query.part1 = @@ -503,7 +532,7 @@ "user sid column", CONFIG_USER_SID_DEFAULT), sid_to_string(sid_str, pdb_get_user_sid (newpwd))); - } else { + } else { query.part2[strlen(query.part2) - 1] = ')'; query.part1[strlen(query.part1) - 1] = ')'; query.part1 =