Here is an executable that would allow a user to change the linux and SMB passwords simultaneously. The website indicated in the comments had some problems in the code, but they are fixed in the cpasswd.c file which is below and also attached. Hope that this helps others. The code is a fix, not a solution. it only works from the command prompt, but it helps with keeping linyx and Samba passwords the same. Good Luck /* * cpasswords.c * Copyright N. Dean Pentcheff 1998 * University of South Carolina * dean2@mail.biol.sc.edu * This program may be redistributed either under the terms of the GNU Copyleft * or the Perl Artistic License (http://www.perl.com). * * Change both the Unix and SMB passwords for a user. * * To work, must be installed SUID-root. * Uses the current user's username, except that if the program is called * by the root user, a username can be given as an argument. * If called interactively (from a tty), is slightly verbose, and uses * the standard getpass() routine to query for a password twice. * If called noninteractively, expects the password (once) on stdin. * * Customize the locations of the standard Unix and SMB password programs * in the "#defines" near the top (do NOT be tempted to add code to make * these changeable from command-line arguments: these programs will * be run as root!). If your paths are obscenely long, examine the * size of STRLEN to make sure it will accomodate them. * The only check on password quality is existence (len > 0) and for * non-root callers a minimum length (MINPWLEN). This can be enhanced. * The sleep()s in the actual pwd-changing routines appeared to be necessary * in some early tests I did with the PAM-passwd program on Linux. I'm * not convinced they're always necessary. Delays in a pwd-changing * program aren't a bad idea anyway, so I've left them in. * Program from http://www.linuxvoodoo.com/howto/all/00000074.html * */ #include <fcntl.h> #include <sys/ioctl.h> #include <pwd.h> #include <errno.h> #include <stdio.h> #include <unistd.h> #include <string.h> #define PASSWD "/usr/bin/passwd_old" #define SMBPASSWD "/usr/bin/smbpasswd_old" #define PROMPT1 "Type a new password: " #define PROMPT2 "Type the same password again: " #define MINPWLEN 6 #define STRLEN 1024 int change(char *program, char *user, char *pwd, FILE *mystderr); int main ( int argc, char **argv) { int fd; struct passwd *pwentry; char name[STRLEN]; char newpw[STRLEN]; int reallyroot = 0; char *cp; FILE *mystderr; /* do we have the appropriate permissions? */ if (geteuid() != 0) { fprintf(stderr, "This program cannot run unless it is SUID-root, " "exiting...\n"); exit(1); } if (getuid() == 0) reallyroot = 1; /* get the appropriate username */ if (argc > 1) { if (reallyroot) { /* if root, we can specify a username */ strncpy(name, *++argv, STRLEN); } else { fprintf(stderr, "Only the root user can specify a name, exiting...\n"); exit(1); } } else { /* pick up the current user's username */ if ((pwentry = getpwuid(getuid())) == NULL) { fprintf(stderr, "Failed getting name entry for UID=%d, exiting...\n", getuid()); exit(1); } strncpy(name, pwentry->pw_name, STRLEN); } /* get a password and clean any cr/lf stuff */ if (isatty(0)) { /* interactive, so use a no-echo prompt twice */ fprintf(stderr, "Changing password for user '%s'\n", name); cp = getpass(PROMPT1); strncpy(newpw, cp, STRLEN); cp = getpass(PROMPT2); if (strcmp(newpw, cp)) { fprintf(stderr, "The two versions don't match, exiting...\n"); exit(1); } } else { /* noninteractive, so just get it from stdin */ if (read(0, newpw, STRLEN) <= 0) { fprintf(stderr, "Failed to read a new password, exiting...\n"); exit(1); } } // for(cp=newpw; *cp!='\n' && *cp!='\r' && cp-newpw<=0) { // fprintf(stderr, "No password entered, exiting...\n"); // exit(1); // } if ( ! reallyroot) { if (strlen(newpw) < MINPWLEN) { fprintf(stderr, "Password must be at least %d characters long, " "exiting...\n", MINPWLEN); exit(1); } } /* get a private stderr, then close stderr/stdout to silence pwd programs */ if ((fd=dup(2)) < 0) { fprintf(stderr, "Strange! Couldn't dup error-output fd, exiting...\n"); exit(1); } if ((mystderr=fdopen(fd, "w"))== NULL) { fprintf(stderr, "Strange! Couldn't fdopen new stderr fd, exiting...\n"); exit(1); } close(1); close(2); /* detach from controlling tty to get password programs to read stdin */ if ((fd=open("/dev/tty", O_RDWR))>= 0) { if (ioctl(fd, TIOCNOTTY) <0) { fprintf(mystderr, "Failed to detach from /dev/tty: %s, exiting...\n", strerror(errno)); exit(1); } close(fd); } /* shuffle UIDs for permissions we know we are running SUID-root */ if (setuid(geteuid()) !=0) { fprintf(stderr, "Failed to properly set UID, exiting...\n"); exit(1); } /* change the Unix password */ if (isatty(0)) fprintf(mystderr, "Changing Unix password...\n"); if ( ! change(PASSWD, name, newpw, mystderr)) exit(1); if (isatty(0)) fprintf(mystderr, "\tSuccessfully changed Unix password.\n"); /* change the SMB password */ if (isatty(0)) fprintf(mystderr, "Changing SMB/Windows password...\n"); if ( ! change(SMBPASSWD, name, newpw, mystderr)) exit(1); if (isatty(0)) fprintf(mystderr, "\tSuccessfully changed SMB/Windows password.\n"); exit(0); } int change(char *program, char *user, char *pwd, FILE *mystderr) { char cmd[STRLEN]; FILE *cmdpipe; int status; /* open a pipe to and then feed the password program, slowly */ strncpy(cmd, program, STRLEN); strncat(cmd, " ", STRLEN + 1); strncat(cmd, user, STRLEN + strlen(cmd)); if ((cmdpipe=popen(cmd, "w"))== NULL) { fprintf(mystderr, "Failed to open pipe to '%s', exiting...\n", cmd); return 0; } sleep(3); fprintf(cmdpipe, "%s\n", pwd); fflush(cmdpipe); sleep(2); fprintf(cmdpipe, "%s\n", pwd); fflush(cmdpipe); sleep(2); if ((status=pclose(cmdpipe)) !=0) { fprintf(mystderr, "Program '%s' returned error code %d, exiting...\n", cmd, status); return 0; } return 1; } -------------- next part -------------- /* * cpasswords.c * Copyright N. Dean Pentcheff 1998 * University of South Carolina * dean2@mail.biol.sc.edu * This program may be redistributed either under the terms of the GNU Copyleft * or the Perl Artistic License (http://www.perl.com). * * Change both the Unix and SMB passwords for a user. * * To work, must be installed SUID-root. * Uses the current user's username, except that if the program is called * by the root user, a username can be given as an argument. * If called interactively (from a tty), is slightly verbose, and uses * the standard getpass() routine to query for a password twice. * If called noninteractively, expects the password (once) on stdin. * * Customize the locations of the standard Unix and SMB password programs * in the "#defines" near the top (do NOT be tempted to add code to make * these changeable from command-line arguments: these programs will * be run as root!). If your paths are obscenely long, examine the * size of STRLEN to make sure it will accomodate them. * The only check on password quality is existence (len > 0) and for * non-root callers a minimum length (MINPWLEN). This can be enhanced. * The sleep()s in the actual pwd-changing routines appeared to be necessary * in some early tests I did with the PAM-passwd program on Linux. I'm * not convinced they're always necessary. Delays in a pwd-changing * program aren't a bad idea anyway, so I've left them in. * Program from http://www.linuxvoodoo.com/howto/all/00000074.html * */ #include <fcntl.h> #include <sys/ioctl.h> #include <pwd.h> #include <errno.h> #include <stdio.h> #include <unistd.h> #include <string.h> #define PASSWD "/usr/bin/passwd_old" #define SMBPASSWD "/usr/bin/smbpasswd_old" #define PROMPT1 "Type a new password: " #define PROMPT2 "Type the same password again: " #define MINPWLEN 6 #define STRLEN 1024 int change(char *program, char *user, char *pwd, FILE *mystderr); int main ( int argc, char **argv) { int fd; struct passwd *pwentry; char name[STRLEN]; char newpw[STRLEN]; int reallyroot = 0; char *cp; FILE *mystderr; /* do we have the appropriate permissions? */ if (geteuid() != 0) { fprintf(stderr, "This program cannot run unless it is SUID-root, " "exiting...\n"); exit(1); } if (getuid() == 0) reallyroot = 1; /* get the appropriate username */ if (argc > 1) { if (reallyroot) { /* if root, we can specify a username */ strncpy(name, *++argv, STRLEN); } else { fprintf(stderr, "Only the root user can specify a name, exiting...\n"); exit(1); } } else { /* pick up the current user's username */ if ((pwentry = getpwuid(getuid())) == NULL) { fprintf(stderr, "Failed getting name entry for UID=%d, exiting...\n", getuid()); exit(1); } strncpy(name, pwentry->pw_name, STRLEN); } /* get a password and clean any cr/lf stuff */ if (isatty(0)) { /* interactive, so use a no-echo prompt twice */ fprintf(stderr, "Changing password for user '%s'\n", name); cp = getpass(PROMPT1); strncpy(newpw, cp, STRLEN); cp = getpass(PROMPT2); if (strcmp(newpw, cp)) { fprintf(stderr, "The two versions don't match, exiting...\n"); exit(1); } } else { /* noninteractive, so just get it from stdin */ if (read(0, newpw, STRLEN) <= 0) { fprintf(stderr, "Failed to read a new password, exiting...\n"); exit(1); } } // for(cp=newpw; *cp!='\n' && *cp!='\r' && cp-newpw<=0) { // fprintf(stderr, "No password entered, exiting...\n"); // exit(1); // } if ( ! reallyroot) { if (strlen(newpw) < MINPWLEN) { fprintf(stderr, "Password must be at least %d characters long, " "exiting...\n", MINPWLEN); exit(1); } } /* get a private stderr, then close stderr/stdout to silence pwd programs */ if ((fd=dup(2)) < 0) { fprintf(stderr, "Strange! Couldn't dup error-output fd, exiting...\n"); exit(1); } if ((mystderr=fdopen(fd, "w"))== NULL) { fprintf(stderr, "Strange! Couldn't fdopen new stderr fd, exiting...\n"); exit(1); } close(1); close(2); /* detach from controlling tty to get password programs to read stdin */ if ((fd=open("/dev/tty", O_RDWR))>= 0) { if (ioctl(fd, TIOCNOTTY) <0) { fprintf(mystderr, "Failed to detach from /dev/tty: %s, exiting...\n", strerror(errno)); exit(1); } close(fd); } /* shuffle UIDs for permissions we know we are running SUID-root */ if (setuid(geteuid()) !=0) { fprintf(stderr, "Failed to properly set UID, exiting...\n"); exit(1); } /* change the Unix password */ if (isatty(0)) fprintf(mystderr, "Changing Unix password...\n"); if ( ! change(PASSWD, name, newpw, mystderr)) exit(1); if (isatty(0)) fprintf(mystderr, "\tSuccessfully changed Unix password.\n"); /* change the SMB password */ if (isatty(0)) fprintf(mystderr, "Changing SMB/Windows password...\n"); if ( ! change(SMBPASSWD, name, newpw, mystderr)) exit(1); if (isatty(0)) fprintf(mystderr, "\tSuccessfully changed SMB/Windows password.\n"); exit(0); } int change(char *program, char *user, char *pwd, FILE *mystderr) { char cmd[STRLEN]; FILE *cmdpipe; int status; /* open a pipe to and then feed the password program, slowly */ strncpy(cmd, program, STRLEN); strncat(cmd, " ", STRLEN + 1); strncat(cmd, user, STRLEN + strlen(cmd)); if ((cmdpipe=popen(cmd, "w"))== NULL) { fprintf(mystderr, "Failed to open pipe to '%s', exiting...\n", cmd); return 0; } sleep(3); fprintf(cmdpipe, "%s\n", pwd); fflush(cmdpipe); sleep(2); fprintf(cmdpipe, "%s\n", pwd); fflush(cmdpipe); sleep(2); if ((status=pclose(cmdpipe)) !=0) { fprintf(mystderr, "Program '%s' returned error code %d, exiting...\n", cmd, status); return 0; } return 1; }