[tpop3d-discuss]Some conditions may lead getpwuid to fail

Giampaolo Tomassoni g.tomassoni at libero.it
Sat, 30 Sep 2006 16:45:54 +0200


This is a multi-part message in MIME format.

------=_NextPart_000_000E_01C6E4AF.E539AD90
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

Dears,

I see that in many auth_ modules in tpop3d (at least auth_pgsql) user =
authentication involves the invoking of parse_uid() from util.c, =
followed by a getpwuid() to obtain the user's struct passwd.

The purpose seems to me to obtain the struct passwd by allowing the user =
database back-ends to return either a username or a uid.

Unfortunately, this causes some troubles to me. When it is difficult to =
assign a unique id to each user, mailbox users are often given a single =
uid and the user itself is identified only by its name, not by its uid. =
So, the chain parse_uid() -> getpwuid() may give wrong results and =
should be avoided. Also, it is inefficient when a username is involved, =
since basicly parse_uid() must already obtain the passwd structure in =
order to convert the username to its uid.

The basic idea for a fix which doesn't impact on other cases, would be =
to use getpwuid() only when the user field contains numbers, while =
relaying on getpwnam() when a username is instead involved.

A attach a small patch which fixes this for the auth_pgsql module, since =
this is the only one I can actually test. The patch adds the new =
function get_pw_by_name_or_uid() to util.c, which basicly mimes the work =
of parse_uid(), but gives back a struct passwd* by mean of getpwuid() or =
getpwnam(). In auth_pgsql.c, a call to this function replaces the =
parse_uid() -> getpwuid() chain.

I hope to see it in the main branch soon or later: it really seems to =
fix my problem.

Regards,

-----------------------------------
Giampaolo Tomassoni - IT Consultant
Piazza VIII Aprile 1948, 4
I-53044 Chiusi (SI) - Italy
Ph: +39-0578-21100

------=_NextPart_000_000E_01C6E4AF.E539AD90
Content-Type: application/octet-stream;
	name="tpop3d-1.5.3+pgsql-nogetpwuid.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="tpop3d-1.5.3+pgsql-nogetpwuid.patch"

diff -rud tpop3d-1.5.3/auth_pgsql.c =
tpop3d-1.5.3+pgsql-nogetpwuid/auth_pgsql.c=0A=
--- tpop3d-1.5.3/auth_pgsql.c	2003-07-15 01:31:20.000000000 +0200=0A=
+++ tpop3d-1.5.3+pgsql-nogetpwuid/auth_pgsql.c	2006-09-30 =
16:00:43.000000000 +0200=0A=
@@ -276,7 +276,6 @@=0A=
         case 0:=0A=
             break;=0A=
         case 1: {=0A=
-                uid_t uid;=0A=
                 struct passwd *pw;=0A=
                 char *user, *passwd, *mailbox, *mboxdrv;=0A=
 =0A=
@@ -302,18 +301,12 @@=0A=
                 }=0A=
 =0A=
                 /* User was not lying (about her password) */=0A=
-                if (!parse_uid(user, &uid)) {=0A=
+		pw =3D get_pw_by_name_or_uid(user);=0A=
+                if (pw =3D=3D NULL) {=0A=
                     log_print(LOG_ERR, _("auth_pgsql_new_apop: unix =
user `%s' for %s does not make sense"), user, who);=0A=
                     break;=0A=
                 }=0A=
 =0A=
-                pw =3D getpwuid(uid);=0A=
-=0A=
-                if (!pw) {=0A=
-                    log_print(LOG_ERR, "auth_pgsql_apop: getpwuid(%d): =
%m", (int)uid);=0A=
-                    break;=0A=
-                }=0A=
-=0A=
                 a =3D authcontext_new(pw->pw_uid, use_gid ? mail_gid : =
pw->pw_gid, mboxdrv, mailbox, pw->pw_dir);=0A=
 =0A=
                 break;=0A=
@@ -371,7 +364,6 @@=0A=
             break;=0A=
         case 1: {=0A=
                 struct passwd *pw;=0A=
-                uid_t uid;=0A=
                 char *user, *pwhash, *mailbox, *mboxdrv;=0A=
 =0A=
                 /* Check that user has UID and password. */=0A=
@@ -395,18 +387,12 @@=0A=
                     break;=0A=
                 }=0A=
 =0A=
-                if (!parse_uid(user, &uid)) {=0A=
+		pw =3D get_pw_by_name_or_uid(user);=0A=
+                if (pw =3D=3D NULL) {=0A=
                     log_print(LOG_ERR, _("auth_pgsql_new_user_pass: =
unix user `%s' for %s does not make sense"), user, who);=0A=
                     break;=0A=
                 }=0A=
 =0A=
-                pw =3D getpwuid(uid);=0A=
-=0A=
-                if (!pw) {=0A=
-                    log_print(LOG_ERR, "auth_pgsql_new_user_pass: =
getpwuid(%d): %m", (int)uid);=0A=
-                    break;=0A=
-                }=0A=
-=0A=
                 a =3D authcontext_new(pw->pw_uid, use_gid ? mail_gid : =
pw->pw_gid, mboxdrv, mailbox, pw->pw_dir);=0A=
                 break;=0A=
             }=0A=
diff -rud tpop3d-1.5.3/util.c tpop3d-1.5.3+pgsql-nogetpwuid/util.c=0A=
--- tpop3d-1.5.3/util.c	2003-11-06 02:19:27.000000000 +0100=0A=
+++ tpop3d-1.5.3+pgsql-nogetpwuid/util.c	2006-09-30 15:49:22.000000000 =
+0200=0A=
@@ -109,6 +109,21 @@=0A=
     return 0;=0A=
 }=0A=
 =0A=
+/* get_pw_by_name_or_uid:=0A=
+ * Obtains a pointer to a passwd struct by user name or uid.=0A=
+ * Returns NULL on failure. */=0A=
+struct passwd *get_pw_by_name_or_uid(const char* user) {=0A=
+    char *v;=0A=
+    long l;=0A=
+=0A=
+    /* Numeric user id? */=0A=
+    l =3D strtol(user, &v, 10);=0A=
+    if(v && !*v)=0A=
+	return(getpwuid((uid_t)l));=0A=
+    else=0A=
+	return(getpwnam(user));=0A=
+}=0A=
+=0A=
 /* xsignal NUMBER HANDLER=0A=
  * Set a signal with a similar interface to signal(2) using =
sigaction(2). */=0A=
 void (*xsignal(int signum, void(*handler)(int)))(int) {=0A=
diff -rud tpop3d-1.5.3/util.h tpop3d-1.5.3+pgsql-nogetpwuid/util.h=0A=
--- tpop3d-1.5.3/util.h	2003-11-06 02:19:27.000000000 +0100=0A=
+++ tpop3d-1.5.3+pgsql-nogetpwuid/util.h	2006-09-30 15:46:39.000000000 =
+0200=0A=
@@ -79,6 +79,9 @@=0A=
 int parse_uid(const char *user, uid_t *u);=0A=
 gid_t parse_gid(const char *group, gid_t *g);=0A=
 =0A=
+/* Obtains passwd struct from name or uid */=0A=
+struct passwd *get_pw_by_name_or_uid(const char* user);=0A=
+=0A=
 /* Some systems do not have inet_aton. */=0A=
 #ifndef HAVE_INET_ATON=0A=
 int inet_aton(const char *s, struct in_addr *ip);=0A=

------=_NextPart_000_000E_01C6E4AF.E539AD90--