summaryrefslogtreecommitdiff
path: root/source3/passdb/pdb_pgsql.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/passdb/pdb_pgsql.c')
-rw-r--r--source3/passdb/pdb_pgsql.c226
1 files changed, 169 insertions, 57 deletions
diff --git a/source3/passdb/pdb_pgsql.c b/source3/passdb/pdb_pgsql.c
index 4fb674d204..e603bd6a53 100644
--- a/source3/passdb/pdb_pgsql.c
+++ b/source3/passdb/pdb_pgsql.c
@@ -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 ;
@@ -75,6 +133,8 @@ static NTSTATUS row_to_sam_account ( PGresult *r, long row, SAM_ACCOUNT *u )
{
pstring temp ;
DOM_SID sid ;
+ unsigned char *hours ;
+ size_t hours_len = 0 ;
if ( row >= PQntuples( r ) ) return NT_STATUS_INVALID_PARAMETER ;
@@ -100,9 +160,16 @@ static NTSTATUS row_to_sam_account ( PGresult *r, long row, SAM_ACCOUNT *u )
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 ) ;
+ hours = PQgetvalue ( r, row, 29 );
+ if ( hours != NULL ) {
+ hours = PQunescapeBytea ( hours, &hours_len ) ;
+ if ( hours_len > 0 )
+ pdb_set_hours ( u, hours, PDB_SET ) ;
+ free ( hours );
+ }
if ( !PQgetisnull( r, row, 18 ) ) {
string_to_sid( &sid, PQgetvalue( r, row, 18 ) ) ;
@@ -126,22 +193,29 @@ static NTSTATUS row_to_sam_account ( PGresult *r, long row, SAM_ACCOUNT *u )
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(NULL, 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 +228,10 @@ static NTSTATUS pgsqlsam_setsampwent(struct pdb_methods *methods, BOOL update, u
DEBUG( 5, ("pgsqlsam_setsampwent succeeded(%d results)!\n", PQntuples(data->pwent)) ) ;
retval = NT_STATUS_OK ;
}
-
+
talloc_free(query);
+ if ( data->pwent != NULL )
+ PQclear( data->pwent ) ;
return retval ;
}
@@ -206,6 +282,7 @@ static NTSTATUS pgsqlsam_getsampwent( struct pdb_methods *methods, SAM_ACCOUNT *
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 +310,22 @@ static NTSTATUS pgsqlsam_select_by_field ( struct pdb_methods *methods, SAM_ACCO
//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(NULL, 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 +340,9 @@ static NTSTATUS pgsqlsam_select_by_field ( struct pdb_methods *methods, SAM_ACCO
talloc_free( esc ) ;
talloc_free( query ) ;
-
- PQclear( result ) ;
+
+ if ( result != NULL )
+ PQclear( result ) ;
return retval ;
}
@@ -271,6 +354,9 @@ static NTSTATUS pgsqlsam_select_by_field ( struct pdb_methods *methods, SAM_ACCO
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 +365,18 @@ static NTSTATUS pgsqlsam_getsampwnam ( struct pdb_methods *methods, SAM_ACCOUNT
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 +403,7 @@ static NTSTATUS pgsqlsam_getsampwsid ( struct pdb_methods *methods, SAM_ACCOUNT
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 +429,20 @@ static NTSTATUS pgsqlsam_delete_sam_account( struct pdb_methods *methods, SAM_AC
}
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(NULL, 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 +456,8 @@ static NTSTATUS pgsqlsam_delete_sam_account( struct pdb_methods *methods, SAM_AC
retval = NT_STATUS_OK ;
}
+ if ( result != NULL )
+ PQclear( result ) ;
talloc_free( esc ) ;
talloc_free( query ) ;
@@ -363,8 +467,10 @@ static NTSTATUS pgsqlsam_delete_sam_account( struct pdb_methods *methods, SAM_AC
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 +480,43 @@ static NTSTATUS pgsqlsam_replace_sam_account( struct pdb_methods *methods, const
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(NULL, 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 ) ;
talloc_free(query);
- return NT_STATUS_OK;
+ return retval;
}
static NTSTATUS pgsqlsam_add_sam_account ( struct pdb_methods *methods, SAM_ACCOUNT *newpwd )
@@ -422,6 +540,8 @@ static NTSTATUS pgsqlsam_init ( struct pdb_context *pdb_context, struct pdb_meth
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 +560,9 @@ static NTSTATUS pgsqlsam_init ( struct pdb_context *pdb_context, struct pdb_meth
data = talloc( pdb_context->mem_ctx, 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 +570,33 @@ static NTSTATUS pgsqlsam_init ( struct pdb_context *pdb_context, struct pdb_meth
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;
}