pkgsrc/mail/poppassd/patches/patch-ac
taca 9ffff00520 - Fix hangup when communicating with smbpasswd(8).
- Quiet pkglint; changing make macro in double quotation into :Q modifier.

Bump PKGREVISION.
2005-12-05 14:12:29 +00:00

406 lines
12 KiB
Text

$NetBSD: patch-ac,v 1.8 2005/12/05 14:12:29 taca Exp $
--- password/poppassd.c.orig Mon Dec 5 10:45:21 2005
+++ password/poppassd.c
@@ -171,8 +171,13 @@
/* LANMAN allows up to 14 char passwords (truncates if longer), but tacacs
only seems to allow 11. */
+#ifndef PASSWD_BINARY
#define PASSWD_BINARY "/usr/bin/passwd" /* TBD: config.h */
+#endif
+
+#ifndef SMBPASSWD_BINARY
#define SMBPASSWD_BINARY "/usr/bin/smbpasswd" /* TBD: config.h */
+#endif
#include "config.h"
@@ -180,6 +185,8 @@
#include <sys/stat.h>
#include <sys/wait.h>
+#include <signal.h>
+
#if HAVE_SYS_NETINET_IN_H
# include <sys/netinet/in.h>
#endif
@@ -257,7 +264,7 @@ int dochild (int master, char *slave
int findpty (char **slave);
void writestring (int fd, char *s);
int talktochild (int master, char *user, char *oldpass, char *newpass,
- char *emess, int asroot);
+ char *emess);
int match (char *str, char *pat);
int expect (int master, char **expected, char *buf);
void getemess (int master, char **expected, char *buf);
@@ -274,7 +281,7 @@ void get_client_info ( POP *p, BOOL n
char *sock_ntop ( struct sockaddr *p, int salen );
int sock_port ( struct sockaddr *p, int salen );
char *debug_str ( char *p, int inLen, int order );
-
+void reapchild (int);
/*
* External prototypes
@@ -295,6 +302,8 @@ pop_result auth_user ( POP *p, char *pas
static char *P1[] =
{
+ "changing local password for *\nold password: ", /* BSD */
+ "old password: ", /* NetBSD>=3.0 */
"changing password for *\nold password: ", /* shadow */
"enter login password: ", /* Solaris */
"old smb password: ", /* smb */
@@ -324,6 +333,7 @@ static char *P4[] =
{
"password changed. ", /* shadow */
"password changed ", /* smb */
+ "password changed for user *\n", /* smb */
""
};
@@ -338,6 +348,8 @@ char msg_buf [ 2048 ] = ""
char *pwd_binary = PASSWD_BINARY;
char *smb_binary = SMBPASSWD_BINARY;
+int child_pid;
+int child_status;
/*
* Be careful using TRACE in an 'if' statement!
@@ -347,18 +359,19 @@ char *smb_binary = SM
#define RUN_PASSWD 1
#define RUN_SMBPASSWD 2
-
int main ( int argc, char *argv[] )
{
char line [BUFSIZE] = "";
char oldpass [BUFSIZE] = "";
char newpass [BUFSIZE] = "";
int nopt = -1;
- static char options [] = "dl:p:Rs:t:vy:?";
+ static char options [] = "dhl:oPp:RSs:t:vy:";
int mode = 0;
char *ptr = NULL;
POP p;
BOOL no_rev_lookup = FALSE;
+ int compat_mode = 0;
+ BOOL bad_user = FALSE;
#ifdef HAS_SHADOW
struct spwd *spwd;
@@ -376,8 +389,6 @@ int main ( int argc, char *argv[] )
pname = ptr + 1;
}
- openlog ( pname, POP_LOGOPTS, LOG_LOCAL2 );
-
/*
* Set up some stuff in -p- so we can call Qpopper routines
*/
@@ -385,6 +396,17 @@ int main ( int argc, char *argv[] )
p.AuthType = noauth;
p.myname = pname;
+#ifndef POP_FACILITY
+# if defined(OSF1) || defined(LINUX)
+# define POP_FACILITY LOG_MAIL
+# else
+# define POP_FACILITY LOG_LOCAL0
+# endif /* OSF1 or Linux */
+#endif /* POP_FACILITY not defined */
+
+ p.log_facility = (log_facility_type) POP_FACILITY;
+ openlog ( pname, POP_LOGOPTS, p.log_facility );
+
/*
* Handle command-line options
*/
@@ -393,9 +415,9 @@ int main ( int argc, char *argv[] )
{
switch (nopt)
{
- case '?':
- fprintf ( stderr, "%s [-?] [-d] [-l 0|1|2] [-p [passd-path]] "
- "[-R] [-s [smbpasswd-path]]\n\t"
+ case 'h':
+ fprintf ( stderr, "%s [-h] [-d] [-l 0|1|2] [-p [passd-path]] "
+ "[-P] [-R] [-S] [-s [smbpasswd-path]]\n\t"
"[-t trace-file] [-v] [-y log-facility]\n",
pname );
exit (1);
@@ -412,20 +434,34 @@ int main ( int argc, char *argv[] )
verbose = TRUE;
break;
+ case 'S':
+ mode |= RUN_SMBPASSWD;
+ TRACE ( trace_file, POP_DEBUG, HERE,
+ "Changing SMB password enabled" );
+ break;
+
+
case 's':
mode |= RUN_SMBPASSWD;
if ( optarg != NULL && *optarg != '\0' )
smb_binary = optarg;
TRACE ( trace_file, POP_DEBUG, HERE,
- "Changing SMB passwords using %s", smb_binary );
+ "Changing SMB password using %s", smb_binary );
+ break;
+
+ case 'P':
+ mode |= RUN_PASSWD;
+ TRACE ( trace_file, POP_DEBUG, HERE,
+ "Changing standard password enabled" );
break;
+
case 'p':
mode |= RUN_PASSWD;
if ( optarg != NULL && *optarg != '\0' )
pwd_binary = optarg;
TRACE ( trace_file, POP_DEBUG, HERE,
- "Changing standard passwords using %s", pwd_binary );
+ "Changing standard password using %s", pwd_binary );
break;
case 't':
@@ -476,6 +512,10 @@ int main ( int argc, char *argv[] )
"Avoiding reverse lookups (-R)" );
break;
+ case 'o': /* compatibility mode */
+ compat_mode = 1;
+ break;
+
case 'y': /* log facility */
if ( optarg == NULL || *optarg == '\0' ) {
err_msg ( HERE, "-y value expected" );
@@ -563,44 +603,50 @@ int main ( int argc, char *argv[] )
return 1;
}
- WriteToClient ( "200 your new password please." );
- ReadFromClient ( line );
- sscanf ( line, "newpass %s", newpass );
-
- /* new pass required */
- if ( strlen (newpass) == 0 )
- {
- WriteToClient ("500 New password required.");
- return 1;
- }
-
pw = getpwnam ( userid );
if ( pw == NULL )
{
- WriteToClient ( "500 Invalid user or password" );
- return 1;
- }
+ bad_user = TRUE;
+ } else {
#ifdef HAS_SHADOW
- if ((spwd = getspnam(userid)) == NULL)
- pw->pw_passwd = "";
- else
- pw->pw_passwd = spwd->sp_pwdp;
+ if ((spwd = getspnam(userid)) == NULL)
+ pw->pw_passwd = "";
+ else
+ pw->pw_passwd = spwd->sp_pwdp;
#endif
+ if ( chkPass ( userid, oldpass, pw, &p ) == FAILURE )
+ {
+ syslog ( LOG_ERR, "password failure for %s", userid );
+ bad_user = TRUE;
+ }
+
+ if ( pw->pw_uid <= BLOCK_UID )
+ {
+ syslog( LOG_ERR, "someone tried to change %s's password", userid );
+ bad_user = TRUE;
+ }
+ }
+ if (compat_mode && bad_user) {
+ sleep(1); /* XXX */
+ WriteToClient ( "500 Invalid user or password" );
+ return 1;
+ }
- if ( chkPass ( userid, oldpass, pw, &p ) == FAILURE )
- {
- syslog ( LOG_ERR, "password failure for %s", userid );
- WriteToClient ( "500 Invalid user or password" );
- return 1;
+ WriteToClient ( "200 your new password please." );
+ ReadFromClient ( line );
+ sscanf ( line, "newpass %s", newpass );
+
+ if (bad_user) {
+ WriteToClient ( "500 Invalid user or password" );
+ return 1;
}
- if ( pw->pw_uid <= BLOCK_UID )
-
+ /* new pass required */
+ if ( strlen (newpass) == 0 )
{
- syslog ( LOG_ERR, "someone tried to change %s's password", userid );
- WriteToClient ( "500 Not a user account." );
+ WriteToClient ("500 New password required.");
return 1;
}
@@ -633,6 +679,20 @@ int main ( int argc, char *argv[] )
return 0;
}
+/* catch child */
+void
+reapchild(sig)
+ int sig;
+{
+ int status;
+ int pid;
+
+ while ((pid = wait3(&status, WNOHANG, NULL)) > 0) {
+ child_pid = pid;
+ child_status = status;
+ }
+}
+
/* Run a child process to do the password change */
@@ -653,6 +713,10 @@ void runchild ( char *userid, char *oldp
exit ( 1 );
}
+ signal(SIGCHLD, reapchild);
+ child_pid = 0;
+ child_status = -1;
+
/* fork child process to talk to password program */
pid = fork();
@@ -665,7 +729,7 @@ void runchild ( char *userid, char *oldp
if ( pid > 0 ) /* Parent */
{
- if (talktochild (master, userid, oldpass, newpass, emess, smb) == FAILURE)
+ if (talktochild (master, userid, oldpass, newpass, emess) == FAILURE)
{
logit ( trace_file, LOG_ERR, HERE,
"%s failed for %s", smb ? "smbpasswd" : "passwd", userid );
@@ -677,10 +741,16 @@ void runchild ( char *userid, char *oldp
wpid = waitpid ( pid, &wstat, 0 );
if ( wpid < 0 )
{
- logit ( trace_file, LOG_ERR, HERE, "wait for child failed" );
- WriteToClient ("500 Server error (wait failed), get help!");
- exit(1);
+ if (child_pid > 0) {
+ wpid = child_pid;
+ wstat = child_status;
+ } else {
+ logit ( trace_file, LOG_ERR, HERE, "wait for child failed" );
+ WriteToClient ("500 Server error (wait failed), get help!");
+ exit(1);
+ }
}
+ signal(SIGCHLD, SIG_DFL);
if ( pid != wpid )
{
@@ -702,7 +772,6 @@ void runchild ( char *userid, char *oldp
WriteToClient ("500 Server error (abnormal exit), get help!");
exit(1);
}
-
close ( master ); /* done with the pty */
}
else /* Child */
@@ -784,6 +853,13 @@ int dochild (int master, char *slavedev,
chdir ("/");
umask (0);
+#ifdef HAVE_SETLOGIN
+ if (setlogin(userid) < 0) {
+ err_msg ( HERE, "setlogin failed: %m" );
+ return(0);
+ }
+#endif
+
/*
* Become the user and run passwd. Linux shadowed passwd doesn't need
* to be run as root with the username passed on the command line.
@@ -883,20 +959,19 @@ void writestring (int fd, char *s)
* that the password wasn't changed).
*/
int talktochild (int master, char *userid, char *oldpass, char *newpass,
- char *emess, int asroot)
+ char *emess)
{
+ int n;
char buf[BUFSIZE];
char pswd[BUFSIZE+1];
*emess = 0;
TRACE ( trace_file, POP_DEBUG, HERE,
- "talktochild; master=%d; userid=%s; asroot=%d",
- master, userid, asroot );
+ "talktochild; master=%d; userid=%s", master, userid);
/* only get current password if not root */
- if (!asroot)
- {
+ if (geteuid() == 0) {
/* wait for current password prompt */
if (!expect(master, P1, buf)) return FAILURE;
@@ -926,6 +1001,10 @@ int talktochild (int master, char *useri
if ( !expect(master, P4, buf) )
TRACE ( trace_file, POP_DEBUG, HERE, "no response -- assuming OK" );
+ while ((n = read(master, buf, sizeof buf)) > 0) {
+ TRACE ( trace_file, POP_DEBUG, HERE, "reading remained output" );
+ ;
+ }
return SUCCESS;
}
@@ -955,8 +1034,12 @@ int match (char *str, char *pat)
strlen(pat), debug_str(pat, strlen(pat), 1) );
while (*str && *pat) {
- if (*pat == '*')
- break;
+ if (*pat == '*') {
+ pat++;
+ while (*str != '\0' && *str != '\n')
+ *str++;
+ continue;
+ }
/* ignore multiple space sequences */
if (*pat == ' ' && isspace (*str)) {
@@ -1055,7 +1138,11 @@ int expect (int master, char **expected,
if ( m < 0 ) {
err_msg ( HERE, "read error from child" );
return FAILURE;
- }
+ } else if (m == 0) {
+ TRACE ( trace_file, POP_DEBUG, HERE, "no data from child");
+ return FAILURE;
+ }
+
buf [ n + m ] = '\0';
TRACE ( trace_file, POP_DEBUG, HERE, "...read: (%d) '%.128s'",