e26ae5b13a
used anymore (/var/yp/Makefile creates a new /var/yp/passwd file from /var/yp/master.passwd using awk, so yppasswdd doesn't have to make it anymore).
156 lines
4.1 KiB
C
156 lines
4.1 KiB
C
/*
|
|
* yppasswdd
|
|
* Copyright 1994 Olaf Kirch, <okir@monad.swb.de>
|
|
*
|
|
* This program is covered by the GNU General Public License, version 2.
|
|
* It is provided in the hope that it is useful. However, the author
|
|
* disclaims ALL WARRANTIES, expressed or implied. See the GPL for details.
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/errno.h>
|
|
#include <sys/stat.h>
|
|
#include <netinet/in.h>
|
|
#include <arpa/inet.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <ctype.h>
|
|
#include <time.h>
|
|
#include <pwd.h>
|
|
|
|
#include <syslog.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <rpc/rpc.h>
|
|
#include <rpc/pmap_clnt.h>
|
|
#include "yppasswd.h"
|
|
|
|
char *tempname, *passfile;
|
|
extern int *allow_chfn, *allow_chsh;
|
|
|
|
#define xprt_addr(xprt) (svc_getcaller(xprt)->sin_addr)
|
|
#define xprt_port(xprt) ntohs(svc_getcaller(xprt)->sin_port)
|
|
void reaper( int sig );
|
|
|
|
/*===============================================================*
|
|
* Argument validation. Avoid \n... (ouch).
|
|
* We can't use isprint, because people may use 8bit chars which
|
|
* aren't recognized as printable in the default locale.
|
|
*===============================================================*/
|
|
static int
|
|
validate_string(char *str)
|
|
{
|
|
while (*str && !iscntrl(*str)) str++;
|
|
return (*str == '\0');
|
|
}
|
|
|
|
static int
|
|
validate_args(struct xpasswd *pw)
|
|
{
|
|
return validate_string(pw->pw_passwd)
|
|
&& validate_string(pw->pw_shell)
|
|
&& validate_string(pw->pw_gecos);
|
|
}
|
|
|
|
/*===============================================================*
|
|
* The passwd update handler
|
|
*===============================================================*/
|
|
int *
|
|
yppasswdproc_pwupdate_1(yppasswd *yppw, struct svc_req *rqstp)
|
|
{
|
|
struct xpasswd *newpw; /* passwd struct passed by the client */
|
|
struct passwd *pw; /* passwd struct obtained from getpwent() */
|
|
int chsh = 0, chfn = 0;
|
|
static int res;
|
|
char logbuf[255];
|
|
int pfd, tfd, c;
|
|
|
|
newpw = &yppw->newpw;
|
|
res = 1;
|
|
|
|
sprintf( logbuf, "update %.12s (uid=%d) from host %s",
|
|
yppw->newpw.pw_name,
|
|
yppw->newpw.pw_uid,
|
|
inet_ntoa(xprt_addr(rqstp->rq_xprt)));
|
|
|
|
if (!validate_args(newpw)) {
|
|
syslog ( LOG_ALERT, "%s failed", logbuf );
|
|
syslog ( LOG_ALERT, "Invalid characters in argument. "
|
|
"Possible spoof attempt?" );
|
|
return &res;
|
|
}
|
|
|
|
pw_init();
|
|
pfd = pw_lock();
|
|
tfd = pw_tmp();
|
|
|
|
/* Check if the user exists
|
|
*/
|
|
if (!(pw = getpwnam(yppw->newpw.pw_name))) {
|
|
syslog ( LOG_WARNING, "%s failed", logbuf );
|
|
syslog ( LOG_WARNING, "User not in password file." );
|
|
return (&res);
|
|
}
|
|
|
|
/* Check the password.
|
|
*/
|
|
if (strcmp(crypt(yppw->oldpass, pw->pw_passwd), pw->pw_passwd)) {
|
|
syslog ( LOG_WARNING, "%s rejected", logbuf );
|
|
syslog ( LOG_WARNING, "Invalid password." );
|
|
sleep(1);
|
|
return(&res);
|
|
}
|
|
|
|
/* set the new passwd, shell, and full name
|
|
*/
|
|
pw->pw_passwd = newpw->pw_passwd;
|
|
|
|
if (allow_chsh) {
|
|
chsh = (strcmp(pw->pw_shell, newpw->pw_shell) != 0);
|
|
pw->pw_shell = newpw->pw_shell;
|
|
}
|
|
|
|
if (allow_chfn) {
|
|
chfn = (strcmp(pw->pw_gecos, newpw->pw_gecos) != 0);
|
|
pw->pw_gecos = newpw->pw_gecos;
|
|
}
|
|
|
|
pw->pw_change = 0;
|
|
pw_copy(pfd, tfd, pw);
|
|
if (strcmp(passfile, _PATH_MASTERPASSWD)) {
|
|
close(pfd);
|
|
close(tfd);
|
|
rename(tempname,passfile);
|
|
}
|
|
else
|
|
if (pw_mkdb()) {
|
|
syslog ( LOG_WARNING, "%s failed to rebuild password database", logbuf );
|
|
return(&res);
|
|
}
|
|
|
|
/* Fork off process to rebuild NIS passwd.* maps. If the fork
|
|
* fails, restore old passwd file and return an error.
|
|
*/
|
|
if ((c = fork()) < 0) {
|
|
syslog( LOG_ERR, "%s failed", logbuf );
|
|
syslog( LOG_ERR, "Couldn't fork map update process: %m" );
|
|
return (&res);
|
|
}
|
|
if (c == 0) {
|
|
execlp(MAP_UPDATE_PATH, MAP_UPDATE, NULL);
|
|
syslog( LOG_ERR, "Error: couldn't exec map update process: %m" );
|
|
exit(1);
|
|
}
|
|
|
|
syslog ( LOG_INFO, "%s successful. Password changed.", logbuf );
|
|
if (chsh || chfn) {
|
|
syslog ( LOG_INFO, "Shell %schanged (%s), GECOS %schanged (%s).",
|
|
chsh? "" : "un", newpw->pw_shell,
|
|
chfn? "" : "un", newpw->pw_gecos );
|
|
}
|
|
res = 0;
|
|
|
|
return (&res);
|
|
}
|