Package: libpam-pgsql
Version: 0.5.2-9+b1
Severity: normal
Tags: patch

Hi,

the current libpam-pgsql library escapes the SQL options table name and
various column names specified from within the pam configuration file or
the pam_pgsql.conf.

This prevents more complex SQL constructs within those parameters (such
as nested SQL statements instead of a simple table or view name) without
providing any real additional security, as the options' source should be
trustworthy anyway (only system administrators can modify the PAM
configuration or pam_pgsql.conf files). Nothing was changed regarding
user provided input (such as the user name).

The attached patch removes the unnecessary escaping and is tested on our
systems. Please apply.

Greetings, Fabian

-- System Information:
Debian Release: 4.0
  APT prefers stable
  APT policy: (800, 'stable'), (3, 'testing'), (2, 'unstable'), (1, 
'experimental')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.18-4-k7
Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8)

Versions of packages libpam-pgsql depends on:
ii  libc6                       2.3.6.ds1-13 GNU C Library: Shared libraries
ii  libmhash2                   0.9.7-1      Library for cryptographic hashing 
ii  libpam0g                    0.79-4       Pluggable Authentication Modules l
ii  libpq4                      8.1.8-1      PostgreSQL C client library

libpam-pgsql recommends no packages.

-- no debconf information
This patch removes unnecessary SQL escaping of the options table name and
column names. This allows more complex SQL constructs within the
aforementioned options when specified via the configuration file.

 -- Fabian Knittel <[EMAIL PROTECTED]>

diff -urN pam-pgsql-0.5.2.orig/pam_pgsql.c pam-pgsql-0.5.2/pam_pgsql.c
--- pam-pgsql-0.5.2.orig/pam_pgsql.c	2007-05-14 18:35:20.000000000 +0200
+++ pam-pgsql-0.5.2/pam_pgsql.c	2007-05-14 20:07:23.000000000 +0200
@@ -425,9 +425,6 @@
     PGconn *conn;
     int rc, esclen;
     char *user_s;
-    char *pwd_column_s;
-    char *table_s;
-    char *user_column_s;
 #define CRYPT_LEN 13
 
     if(!(conn = pg_connect(options)))
@@ -439,28 +436,13 @@
     sqlescape(user, user_s, strlen(user));
     DBGLOG("%s", user_s);
 
-    esclen = strlen(options->pwd_column)*2+1;
-    pwd_column_s = malloc(esclen);
-    sqlescape(options->pwd_column, pwd_column_s, strlen(options->pwd_column));
-
-    esclen = strlen(options->table)*2+1;
-    table_s = malloc(esclen);
-    sqlescape(options->table, table_s, strlen(options->table));
-
-    esclen = strlen(options->user_column)*2+1;
-    user_column_s = malloc(esclen);
-    sqlescape(options->user_column, user_column_s, strlen(options->user_column));
-
-    DBGLOG("query: SELECT %s FROM %s WHERE %s='%s'", pwd_column_s, table_s, user_column_s, user_s);
+    DBGLOG("query: SELECT %s FROM %s WHERE %s='%s'", options->pwd_column, options->table, options->user_column, user_s);
     if(pg_exec(options, conn, &res, "SELECT %s FROM %s WHERE %s='%s'",
-               pwd_column_s,
-               table_s,
-               user_column_s,
+               options->pwd_column,
+               options->table,
+               options->user_column,
                user_s) != 0) {
 	free(user_s);
-	free(table_s);
-	free(user_column_s);  
-	free(pwd_column_s);   
                
         PQclear(res);
         PQfinish(conn);
@@ -518,9 +500,6 @@
     PQclear(res);
     PQfinish(conn);
     free(user_s);
-    free(table_s);
-    free(user_column_s);
-    free(pwd_column_s);
     return rc;
 }
 
@@ -570,10 +549,6 @@
     struct module_options *options;
     const char *user;
     char *user_s;
-    char *table_s;
-    char *expired_column_s;
-    char *user_column_s;
-    char *newtok_column_s;
     int rc, esclen;
     PGconn *conn;
     PGresult *res;
@@ -606,38 +581,17 @@
 
     sqlescape(user, user_s, strlen(user));  
 
-    esclen = strlen(options->expired_column)*2+1;
-    expired_column_s = malloc(esclen);
-    sqlescape(options->expired_column, expired_column_s, strlen(options->expired_column));
-
-    esclen = strlen(options->table)*2+1;
-    table_s = malloc(esclen);
-    sqlescape(options->table, table_s, strlen(options->table));
-
-    esclen = strlen(options->user_column)*2+1;
-    user_column_s = malloc(esclen);
-    sqlescape(options->user_column, user_column_s, strlen(options->user_column));
-
-    esclen = strlen(options->newtok_column)*2+1;
-    newtok_column_s = malloc(esclen);
-    sqlescape(options->newtok_column, newtok_column_s, strlen(options->newtok_column));
-    
-
     /* if account has expired then expired_column = '1' or 'y' */
     if(options->expired_column) {
-    	DBGLOG("query: SELECT 1 FROM %s WHERE %s='%s' AND %s='y' OR %s='1'", table_s, user_column_s, user_s, expired_column_s, expired_column_s);
+    	DBGLOG("query: SELECT 1 FROM %s WHERE %s='%s' AND %s='y' OR %s='1'", options->table, options->user_column, user_s, options->expired_column, options->expired_column);
         if(pg_exec(options, conn, &res, 
                    "SELECT 1 FROM %s WHERE %s='%s' AND (%s='y' OR %s='1')" ,
-                   table_s,
-                   user_column_s,
+                   options->table,
+                   options->user_column,
                    user_s,
-                   expired_column_s,
-                   expired_column_s) != 0) {
+                   options->expired_column,
+                   options->expired_column) != 0) {
 	    free(user_s);
-	    free(table_s);
-	    free(newtok_column_s);
-	    free(user_column_s);
-	    free(expired_column_s); 
 
             PQclear(res);
             PQfinish(conn);
@@ -646,10 +600,6 @@
         }
         if(PQntuples(res) > 0) {
 	    free(user_s);
-	    free(table_s);
-	    free(newtok_column_s);
-	    free(user_column_s);
-	    free(expired_column_s); 
 
             PQclear(res);
             PQfinish(conn);
@@ -661,19 +611,15 @@
 
     /* if new password is required then newtok_column = 'y' or '1' */
     if(options->newtok_column) {
-    	DBGLOG("query: SELECT 1 FROM %s WHERE %s='%s' AND %s='y' OR %s='1'", table_s, user_column_s, user_s, newtok_column_s, newtok_column_s);
+    	DBGLOG("query: SELECT 1 FROM %s WHERE %s='%s' AND %s='y' OR %s='1'", options->table, options->user_column, user_s, options->newtok_column, options->newtok_column);
         if(pg_exec(options, conn, &res, 
                    "SELECT 1 FROM %s WHERE %s='%s' AND (%s='y' OR %s='1')",
-                   table_s,
-                   user_column_s,
+                   options->table,
+                   options->user_column,
                    user_s,
-                   newtok_column_s,
-                   newtok_column_s) != 0) {
+                   options->newtok_column,
+                   options->newtok_column) != 0) {
 	    free(user_s);
-	    free(table_s);
-	    free(newtok_column_s);
-	    free(user_column_s);
-	    free(expired_column_s); 
 
 	    PQclear(res);
             PQfinish(conn);
@@ -682,10 +628,6 @@
         }
         if(PQntuples(res) > 0) {
 	    free(user_s);
-	    free(table_s);
-	    free(newtok_column_s);
-	    free(user_column_s);
-	    free(expired_column_s); 
 
             PQclear(res);
             PQfinish(conn);
@@ -697,10 +639,6 @@
 
     PQfinish(conn);
     free(user_s);
-    free(table_s);
-    free(newtok_column_s);
-    free(user_column_s);
-    free(expired_column_s);
     free_module_options(options);
     return PAM_SUCCESS;
 }
@@ -713,11 +651,7 @@
     int rc, std_flags, esclen;
     const char *user, *pass, *newpass;
     char *newpass_crypt, *user_s;
-    char *table_s;
     char *newpass_crypt_s;
-    char *user_column_s;
-    char *pwd_column_s;
-    char *newtok_column_s;
     PGconn *conn;
     PGresult *res;
 
@@ -811,44 +745,23 @@
 
         sqlescape(user, user_s, strlen(user));
         
-        esclen = strlen(options->pwd_column)*2+1;
-        pwd_column_s = malloc(esclen);
-        sqlescape(options->pwd_column, pwd_column_s, strlen(options->pwd_column));
- 
-        esclen = strlen(options->table)*2+1;
-        table_s = malloc(esclen);
-        sqlescape(options->table, table_s, strlen(options->table));
- 
-        esclen = strlen(options->user_column)*2+1;
-        user_column_s = malloc(esclen);
-        sqlescape(options->user_column, user_column_s, strlen(options->user_column));
- 
         esclen = strlen(newpass_crypt)*2+1;
         newpass_crypt_s = malloc(esclen);  
         sqlescape(newpass_crypt, newpass_crypt_s, strlen(newpass_crypt));
 
-	esclen = strlen(options->newtok_column)*2+1;
-	newtok_column_s = malloc(esclen);
-	sqlescape(options->newtok_column, newtok_column_s, strlen(options->newtok_column));
-
- 
-        DBGLOG("query: UPDATE %s SET %s='%s' WHERE %s='%s'", table_s, pwd_column_s, "******", user_column_s, user_s);
+        DBGLOG("query: UPDATE %s SET %s='%s' WHERE %s='%s'", options->table, options->pwd_column, "******", options->user_column, user_s);
         
     	if (!options->newtok_column) {
 	        if(pg_exec(options, conn, &res,
        	            "UPDATE %s SET %s='%s' WHERE %s='%s'",
-       	            table_s,
-       	            pwd_column_s,
+       	            options->table,
+       	            options->pwd_column,
        	            newpass_crypt_s,
-       	            user_column_s,  
+       	            options->user_column,  
        	            user_s) != 0) {
        	            	free(newpass_crypt);
 		        free(newpass_crypt_s);
 		        free(user_s);
-		        free(pwd_column_s);
-		        free(user_column_s);
-		        free(newtok_column_s);
-		        free(table_s);
 	        	free_module_options(options);
 	        	PQclear(res);
 	        	PQfinish(conn);
@@ -857,19 +770,14 @@
 	} else {
 	        if(pg_exec(options, conn, &res,
        	            "UPDATE %s SET %s='%s', %s='0' WHERE %s='%s'",
-       	            table_s,
-       	            pwd_column_s,
+       	            options->table,
+       	            options->pwd_column,
        	            newpass_crypt_s,
-       	            newtok_column_s,
-       	            user_column_s,  
+       	            options->user_column,  
        	            user_s) != 0) {
        	            	free(newpass_crypt);
 		        free(newpass_crypt_s);
 		        free(user_s);
-		        free(pwd_column_s);
-		        free(user_column_s);
-		        free(newtok_column_s);
-		        free(table_s);
 	        	free_module_options(options);
 	        	PQclear(res);
 	        	PQfinish(conn);
@@ -881,10 +789,6 @@
         free(newpass_crypt);
         free(newpass_crypt_s);
         free(user_s);
-        free(pwd_column_s);
-        free(user_column_s);
-	free(newtok_column_s);
-        free(table_s);
         PQclear(res);
         PQfinish(conn);
     }

Attachment: signature.asc
Description: Digital signature

Reply via email to