You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
284 lines
9.2 KiB
284 lines
9.2 KiB
From: Marco Nenciarini <mnencia@debian.org>
|
|
Date: Sat, 10 Aug 2013 16:26:41 +0200
|
|
Subject: encoding
|
|
|
|
---
|
|
mod_auth_pgsql.c | 144 +++++++++++++++++++++++++++++++---------------------
|
|
mod_auth_pgsql.html | 9 ++++
|
|
2 files changed, 94 insertions(+), 59 deletions(-)
|
|
|
|
diff --git a/mod_auth_pgsql.c b/mod_auth_pgsql.c
|
|
index f13c166..639537d 100644
|
|
--- a/mod_auth_pgsql.c
|
|
+++ b/mod_auth_pgsql.c
|
|
@@ -151,6 +151,7 @@ typedef struct {
|
|
const char *auth_pg_port;
|
|
const char *auth_pg_options;
|
|
const char *auth_pg_user;
|
|
+ const char *auth_pg_charset;
|
|
const char *auth_pg_pwd;
|
|
const char *auth_pg_pwd_table;
|
|
const char *auth_pg_uname_field;
|
|
@@ -181,6 +182,8 @@ typedef struct {
|
|
|
|
} pg_auth_config_rec;
|
|
|
|
+static PGconn *pg_conn;
|
|
+
|
|
static apr_pool_t *auth_pgsql_pool = NULL;
|
|
static apr_pool_t *auth_pgsql_pool_base64 = NULL;
|
|
|
|
@@ -220,6 +223,7 @@ static void *create_pg_auth_dir_config(apr_pool_t * p, char *d)
|
|
new_rec->auth_pg_port = NULL;
|
|
new_rec->auth_pg_options = NULL;
|
|
new_rec->auth_pg_user = NULL;
|
|
+ new_rec->auth_pg_charset = NULL;
|
|
new_rec->auth_pg_pwd = NULL;
|
|
new_rec->auth_pg_pwd_table = NULL;
|
|
new_rec->auth_pg_uname_field = NULL;
|
|
@@ -324,6 +328,10 @@ static const command_rec pg_auth_cmds[] = {
|
|
(void *) APR_OFFSETOF(pg_auth_config_rec, auth_pg_user),
|
|
OR_AUTHCFG,
|
|
"user name connect as"),
|
|
+ AP_INIT_TAKE1("Auth_PG_charset", ap_set_string_slot,
|
|
+ (void *) APR_OFFSETOF(pg_auth_config_rec, auth_pg_charset),
|
|
+ OR_AUTHCFG,
|
|
+ "charset to use for connection"),
|
|
AP_INIT_TAKE1("Auth_PG_pwd", ap_set_string_slot,
|
|
(void *) APR_OFFSETOF(pg_auth_config_rec, auth_pg_pwd),
|
|
OR_AUTHCFG,
|
|
@@ -462,53 +470,51 @@ static char *auth_pg_base64(char *pw)
|
|
}
|
|
|
|
|
|
+PGconn *pg_connect(pg_auth_config_rec *sec)
|
|
+{
|
|
+ PGconn *conn;
|
|
|
|
-/* Got from POstgreSQL 7.2 */
|
|
-/* ---------------
|
|
- * Escaping arbitrary strings to get valid SQL strings/identifiers.
|
|
- *
|
|
- * Replaces "\\" with "\\\\" and "'" with "''".
|
|
- * length is the length of the buffer pointed to by
|
|
- * from. The buffer at to must be at least 2*length + 1 characters
|
|
- * long. A terminating NUL character is written.
|
|
- * ---------------
|
|
- */
|
|
+ conn = PQsetdbLogin(sec->auth_pg_host, sec->auth_pg_port,
|
|
+ sec->auth_pg_options, NULL, sec->auth_pg_database,
|
|
+ sec->auth_pg_user, sec->auth_pg_pwd);
|
|
+ if (PQstatus(conn) != CONNECTION_OK) {
|
|
+ PQreset(conn);
|
|
+ apr_snprintf(pg_errstr, MAX_STRING_LEN,
|
|
+ "mod_auth_pgsql database connection error resetting %s",
|
|
+ PQerrorMessage(conn));
|
|
+ if (PQstatus(conn) != CONNECTION_OK) {
|
|
+ apr_snprintf(pg_errstr, MAX_STRING_LEN,
|
|
+ "mod_auth_pgsql database connection error reset failed %s",
|
|
+ PQerrorMessage(conn));
|
|
+ PQfinish(conn);
|
|
+ return NULL;
|
|
+ }
|
|
+ }
|
|
+ return conn;
|
|
+}
|
|
|
|
-static size_t pg_check_string(char *to, const char *from, size_t length)
|
|
-{
|
|
- const char *source = from;
|
|
- char *target = to;
|
|
- unsigned int remaining = length;
|
|
-
|
|
- while (remaining > 0) {
|
|
- switch (*source) {
|
|
- case '\\':
|
|
- *target = '\\';
|
|
- target++;
|
|
- *target = '\\';
|
|
- /* target and remaining are updated below. */
|
|
- break;
|
|
|
|
- case '\'':
|
|
- *target = '\'';
|
|
- target++;
|
|
- *target = '\'';
|
|
- /* target and remaining are updated below. */
|
|
- break;
|
|
+static size_t pg_check_string(char *to, const char *from, size_t length, request_rec * r, pg_auth_config_rec *sec)
|
|
+{
|
|
+ int error;
|
|
|
|
- default:
|
|
- *target = *source;
|
|
- /* target and remaining are updated below. */
|
|
+ if (!pg_conn) {
|
|
+ if (!(pg_conn = pg_connect(sec))) {
|
|
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - cannot connect to database");
|
|
+ ap_note_basic_auth_failure(r);
|
|
+ return -1;
|
|
}
|
|
- source++;
|
|
- target++;
|
|
- remaining--;
|
|
}
|
|
|
|
- /* Write the terminating NUL character. */
|
|
- *target = '\0';
|
|
+ PQescapeStringConn(pg_conn, to, from, length, &error);
|
|
+
|
|
+ if (error) {
|
|
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - cannot escape string");
|
|
+ ap_note_basic_auth_failure(r);
|
|
+ return -1;
|
|
+ }
|
|
|
|
- return target - to;
|
|
+ return 0;
|
|
}
|
|
|
|
|
|
@@ -518,7 +524,6 @@ static size_t pg_check_string(char *to, const char *from, size_t length)
|
|
char *do_pg_query(request_rec * r, char *query, pg_auth_config_rec * sec)
|
|
{
|
|
PGresult *pg_result;
|
|
- PGconn *pg_conn;
|
|
char *val;
|
|
char *result = NULL;
|
|
|
|
@@ -530,19 +535,10 @@ char *do_pg_query(request_rec * r, char *query, pg_auth_config_rec * sec)
|
|
sec->auth_pg_database);
|
|
#endif /* DEBUG_AUTH_PGSQL */
|
|
|
|
- pg_conn = PQsetdbLogin(sec->auth_pg_host, sec->auth_pg_port,
|
|
- sec->auth_pg_options, NULL, sec->auth_pg_database,
|
|
- sec->auth_pg_user, sec->auth_pg_pwd);
|
|
- if (PQstatus(pg_conn) != CONNECTION_OK) {
|
|
- PQreset(pg_conn);
|
|
- apr_snprintf(pg_errstr, MAX_STRING_LEN,
|
|
- "mod_auth_pgsql database connection error resetting %s",
|
|
- PQerrorMessage(pg_conn));
|
|
- if (PQstatus(pg_conn) != CONNECTION_OK) {
|
|
- apr_snprintf(pg_errstr, MAX_STRING_LEN,
|
|
- "mod_auth_pgsql database connection error reset failed %s",
|
|
- PQerrorMessage(pg_conn));
|
|
- PQfinish(pg_conn);
|
|
+ if (!pg_conn) {
|
|
+ if (!(pg_conn = pg_connect(sec))) {
|
|
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - cannot connect to database");
|
|
+ ap_note_basic_auth_failure(r);
|
|
return NULL;
|
|
}
|
|
}
|
|
@@ -552,6 +548,21 @@ char *do_pg_query(request_rec * r, char *query, pg_auth_config_rec * sec)
|
|
query);
|
|
#endif /* DEBUG_AUTH_PGSQL */
|
|
|
|
+ if (sec->auth_pg_charset) {
|
|
+ const char *check;
|
|
+
|
|
+ PQsetClientEncoding(pg_conn, sec->auth_pg_charset);
|
|
+
|
|
+ check = pg_encoding_to_char(PQclientEncoding(pg_conn));
|
|
+
|
|
+ if (!check || strcmp(sec->auth_pg_charset, check)) {
|
|
+ apr_snprintf(pg_errstr, MAX_STRING_LEN,
|
|
+ "mod_auth_pgsql database character set encoding %s");
|
|
+ PQfinish(pg_conn);
|
|
+ return NULL;
|
|
+ }
|
|
+ }
|
|
+
|
|
pg_result = PQexec(pg_conn, query);
|
|
|
|
if (pg_result == NULL) {
|
|
@@ -610,7 +621,7 @@ char *get_pg_pw(request_rec * r, char *user, pg_auth_config_rec * sec)
|
|
int n;
|
|
|
|
safe_user = apr_palloc(r->pool, 1 + 2 * strlen(user));
|
|
- pg_check_string(safe_user, user, strlen(user));
|
|
+ pg_check_string(safe_user, user, strlen(user), r, sec);
|
|
|
|
#ifdef DEBUG_AUTH_PGSQL
|
|
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r,
|
|
@@ -685,8 +696,8 @@ static char *get_pg_grp(request_rec * r, char *group, char *user,
|
|
#endif /* DEBUG_AUTH_PGSQL */
|
|
|
|
query[0] = '\0';
|
|
- pg_check_string(safe_user, user, strlen(user));
|
|
- pg_check_string(safe_group, group, strlen(group));
|
|
+ pg_check_string(safe_user, user, strlen(user), r, sec);
|
|
+ pg_check_string(safe_group, group, strlen(group), r, sec);
|
|
|
|
if ((!sec->auth_pg_grp_table) ||
|
|
(!sec->auth_pg_grp_group_field) || (!sec->auth_pg_grp_user_field))
|
|
@@ -777,6 +788,14 @@ static int pg_authenticate_basic_user(request_rec * r)
|
|
}
|
|
pg_errstr[0] = '\0';
|
|
|
|
+ if (!pg_conn) {
|
|
+ if (!(pg_conn = pg_connect(sec))) {
|
|
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - cannot connect to database");
|
|
+ ap_note_basic_auth_failure(r);
|
|
+ return HTTP_UNAUTHORIZED;
|
|
+ }
|
|
+ }
|
|
+
|
|
if (sec->auth_pg_cache_passwords
|
|
&& (!apr_is_empty_table(sec->cache_pass_table))) {
|
|
val = (char *) apr_table_get(sec->cache_pass_table, user);
|
|
@@ -904,6 +923,13 @@ static int pg_check_auth(request_rec * r)
|
|
#endif /* DEBUG_AUTH_PGSQL */
|
|
|
|
|
|
+ if (!pg_conn) {
|
|
+ if (!(pg_conn = pg_connect(sec))) {
|
|
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "[mod_auth_pgsql.c] - cannot connect to database");
|
|
+ ap_note_basic_auth_failure(r);
|
|
+ return HTTP_UNAUTHORIZED;
|
|
+ }
|
|
+ }
|
|
|
|
/* if we cannot do it; leave it to some other guy
|
|
*/
|
|
@@ -1015,9 +1041,9 @@ pg_log_auth_user(request_rec * r, pg_auth_config_rec * sec, char *user,
|
|
}
|
|
|
|
/* AUD: MAX_STRING_LEN probably isn't always correct */
|
|
- pg_check_string(safe_user, user, strlen(user));
|
|
- pg_check_string(safe_pw, sent_pw, strlen(sent_pw));
|
|
- pg_check_string(safe_req, r->the_request, strlen(r->the_request));
|
|
+ pg_check_string(safe_user, user, strlen(user), r, sec);
|
|
+ pg_check_string(safe_pw, sent_pw, strlen(sent_pw), r, sec);
|
|
+ pg_check_string(safe_req, r->the_request, strlen(r->the_request), r, sec);
|
|
|
|
|
|
if (sec->auth_pg_lowercaseuid) {
|
|
diff --git a/mod_auth_pgsql.html b/mod_auth_pgsql.html
|
|
index d35768b..5474314 100644
|
|
--- a/mod_auth_pgsql.html
|
|
+++ b/mod_auth_pgsql.html
|
|
@@ -48,6 +48,7 @@ Notes</a> |<a href="#Changelog"> Changelog</a> </p>
|
|
<li><a href="#host">Auth_PG_host</a> </li>
|
|
<li><a href="#port">Auth_PG_port</a> </li>
|
|
<li><a href="#options">Auth_PG_options</a> </li>
|
|
+ <li><a href="#charset">Auth_PG_charset</a> </li>
|
|
<li><a href="#database">Auth_PG_database</a> </li>
|
|
<li><a href="#user">Auth_PG_user</a> </li>
|
|
<li><a href="#pwd">Auth_PG_pwd</a> </li>
|
|
@@ -104,6 +105,14 @@ be found. </p>
|
|
<p>Specifies an option string to be passed to the postgreSQL backend
|
|
process. Refer to the PostgreSQL user manual for a description of the
|
|
available options. </p>
|
|
+<h2><a name="charset"></a> Auth_PG_charset</h2>
|
|
+<b>Syntax:</b> Auth_PG_options <i>option string</i><br>
|
|
+<b>Context:</b> directory, .htaccess <br>
|
|
+<b>Override:</b> AuthConfig <br>
|
|
+<b>Status:</b> Extension
|
|
+<p>Specifies the name of an encoding to be set for the PostgreSQL
|
|
+backend process. Refer to the PostgreSQL user manual for a description
|
|
+of the available options. </p>
|
|
<h2><a name="database"></a> Auth_PG_database</h2>
|
|
<b>Syntax:</b> Auth_PG_database <i>database name</i><br>
|
|
<b>Context:</b> directory, .htaccess <br>
|