From 6c394ac5f97c8cf97a6793f215c60a550bafbebb Mon Sep 17 00:00:00 2001 From: Bill Paul Date: Tue, 31 Jan 1995 09:12:52 +0000 Subject: [PATCH] Obtained from: The NYS project This is a ported/modified version of yppasswd from the NYS yppasswd-0.5 package. This package has code in it from both Olaf Kirch and Theo de Raadt. There are GPL references and BSD-style copyright all over the place... hopefully I won't get flamed into oblivion for commiting this. This program has been modified from the original in the following ways: - Changed the ALLOW_CHFN and ALLOW_CHSH compile-time options into run-time options. - Demolished the password update functions and replaced them with routines to handle FreeBSD-style passwordd databases. It is expected that a seperate master.passwd file will be maintained for use with the NIS maps. yppasswd will have to be told where it is: % yppasswdd -m /var/yp/master.passwd A /var/yp/passwd file will be generated from /var/yp/master.passwd by /var/yp/Makefile. When yppasswdd has finished modifying the master.passwd file, it will invoke /usr/libexec/yppwupdate, which is a script that will run /var/yp/Makefile to generate new maps and push them. Note that there are copies if pw_util.c and pw_copy.c here. This is deliberate: they are *not* identical to the originals. Very similar, yes, but not identical. *sigh* --- gnu/usr.sbin/yppasswdd/Makefile | 16 ++ gnu/usr.sbin/yppasswdd/pw_copy.c | 108 ++++++++++++++ gnu/usr.sbin/yppasswdd/pw_util.c | 206 ++++++++++++++++++++++++++ gnu/usr.sbin/yppasswdd/update.c | 156 +++++++++++++++++++ gnu/usr.sbin/yppasswdd/yppasswd.h | 57 +++++++ gnu/usr.sbin/yppasswdd/yppasswd_xdr.c | 57 +++++++ gnu/usr.sbin/yppasswdd/yppasswdd.8 | 92 ++++++++++++ gnu/usr.sbin/yppasswdd/yppasswdd.c | 205 +++++++++++++++++++++++++ 8 files changed, 897 insertions(+) create mode 100644 gnu/usr.sbin/yppasswdd/Makefile create mode 100644 gnu/usr.sbin/yppasswdd/pw_copy.c create mode 100644 gnu/usr.sbin/yppasswdd/pw_util.c create mode 100644 gnu/usr.sbin/yppasswdd/update.c create mode 100644 gnu/usr.sbin/yppasswdd/yppasswd.h create mode 100644 gnu/usr.sbin/yppasswdd/yppasswd_xdr.c create mode 100644 gnu/usr.sbin/yppasswdd/yppasswdd.8 create mode 100644 gnu/usr.sbin/yppasswdd/yppasswdd.c diff --git a/gnu/usr.sbin/yppasswdd/Makefile b/gnu/usr.sbin/yppasswdd/Makefile new file mode 100644 index 000000000000..115c217256fa --- /dev/null +++ b/gnu/usr.sbin/yppasswdd/Makefile @@ -0,0 +1,16 @@ +# @(#)Makefile 8.3 (Berkeley) 4/2/94 + +PROG= yppasswdd +MAN8= yppasswdd.8 + +SRCS= yppasswdd.c yppasswd_xdr.c update.c pw_copy.c pw_util.c + +LDADD= -lcrypt +CFLAGS+=-DCRYPT -I${.CURDIR} -I${.CURDIR}/../../../usr.sbin/vipw \ + -I${.CURDIR}/../../../usr.bin/chpass +CFLAGS+=-DVERSION=\"0.5\" -DYPLIBDIR=\"/usr/libexec\" -D_GNU_SOURCE + +BINOWN= bin +BINMODE=555 + +.include diff --git a/gnu/usr.sbin/yppasswdd/pw_copy.c b/gnu/usr.sbin/yppasswdd/pw_copy.c new file mode 100644 index 000000000000..8eea0cd62154 --- /dev/null +++ b/gnu/usr.sbin/yppasswdd/pw_copy.c @@ -0,0 +1,108 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)pw_copy.c 8.4 (Berkeley) 4/2/94"; +#endif /* not lint */ + +/* + * This module is used to copy the master password file, replacing a single + * record, by chpass(1) and passwd(1). + */ + +#include +#include +#include +#include + +#include +#include "pw_copy.h" + +extern char *tempname; +extern char *passfile; + +void +pw_copy(ffd, tfd, pw) + int ffd, tfd; + struct passwd *pw; +{ + FILE *from, *to; + int done; + char *p, buf[8192]; + + if (!(from = fdopen(ffd, "r"))) + pw_error(passfile, 1, 1); + if (!(to = fdopen(tfd, "w"))) + pw_error(tempname, 1, 1); + + for (done = 0; fgets(buf, sizeof(buf), from);) { + if (!strchr(buf, '\n')) { + warnx("%s: line too long", passfile); + pw_error(NULL, 0, 1); + } + if (done) { + (void)fprintf(to, "%s", buf); + if (ferror(to)) + goto err; + continue; + } + if (!(p = strchr(buf, ':'))) { + warnx("%s: corrupted entry", passfile); + pw_error(NULL, 0, 1); + } + *p = '\0'; + if (strcmp(buf, pw->pw_name)) { + *p = ':'; + (void)fprintf(to, "%s", buf); + if (ferror(to)) + goto err; + continue; + } + (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", + pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, + pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos, + pw->pw_dir, pw->pw_shell); + done = 1; + if (ferror(to)) + goto err; + } + if (!done) + (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", + pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, + pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos, + pw->pw_dir, pw->pw_shell); + + if (ferror(to)) +err: pw_error(NULL, 1, 1); + (void)fclose(to); +} diff --git a/gnu/usr.sbin/yppasswdd/pw_util.c b/gnu/usr.sbin/yppasswdd/pw_util.c new file mode 100644 index 000000000000..9ca2d16f27dd --- /dev/null +++ b/gnu/usr.sbin/yppasswdd/pw_util.c @@ -0,0 +1,206 @@ +/*- + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ + +/* + * This file is used by all the "password" programs; vipw(8), chpass(1), + * and passwd(1). + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pw_util.h" + +extern char *tempname; +extern char *passfile; + +void +pw_init() +{ + struct rlimit rlim; + + /* Unlimited resource limits. */ + rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; + (void)setrlimit(RLIMIT_CPU, &rlim); + (void)setrlimit(RLIMIT_FSIZE, &rlim); + (void)setrlimit(RLIMIT_STACK, &rlim); + (void)setrlimit(RLIMIT_DATA, &rlim); + (void)setrlimit(RLIMIT_RSS, &rlim); + + /* Don't drop core (not really necessary, but GP's). */ + rlim.rlim_cur = rlim.rlim_max = 0; + (void)setrlimit(RLIMIT_CORE, &rlim); + + /* Turn off signals. */ + (void)signal(SIGALRM, SIG_IGN); + (void)signal(SIGHUP, SIG_IGN); + (void)signal(SIGINT, SIG_IGN); + (void)signal(SIGPIPE, SIG_IGN); + (void)signal(SIGQUIT, SIG_IGN); + (void)signal(SIGTERM, SIG_IGN); + (void)signal(SIGTSTP, SIG_IGN); + (void)signal(SIGTTOU, SIG_IGN); + + /* Create with exact permissions. */ + (void)umask(0); +} + +static int lockfd; + +int +pw_lock() +{ + /* + * If the master password file doesn't exist, the system is hosed. + * Might as well try to build one. Set the close-on-exec bit so + * that users can't get at the encrypted passwords while editing. + * Open should allow flock'ing the file; see 4.4BSD. XXX + */ + lockfd = open(passfile, O_RDONLY, 0); + if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) + err(1, "%s", passfile); + if (flock(lockfd, LOCK_EX|LOCK_NB)) + errx(1, "the password db file is busy"); + return (lockfd); +} + +int +pw_tmp() +{ + static char path[MAXPATHLEN]; + int fd; + char *p; + + sprintf(path,"%s",passfile); + if (p = strrchr(path, '/')) + ++p; + else + p = path; + strcpy(p, "pw.XXXXXX"); + if ((fd = mkstemp(path)) == -1) + err(1, "%s", path); + tempname = path; + return (fd); +} + +int +pw_mkdb() +{ + int pstat; + pid_t pid; + + warnx("rebuilding the database..."); + (void)fflush(stderr); + if (!(pid = vfork())) { + execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL); + pw_error(_PATH_PWD_MKDB, 1, 1); + } + pid = waitpid(pid, &pstat, 0); + if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) + return (0); + warnx("done"); + return (1); +} + +void +pw_edit(notsetuid) + int notsetuid; +{ + int pstat; + pid_t pid; + char *p, *editor; + + if (!(editor = getenv("EDITOR"))) + editor = _PATH_VI; + if (p = strrchr(editor, '/')) + ++p; + else + p = editor; + + if (!(pid = vfork())) { + if (notsetuid) { + (void)setgid(getgid()); + (void)setuid(getuid()); + } + execlp(editor, p, tempname, NULL); + _exit(1); + } + pid = waitpid(pid, (int *)&pstat, 0); + if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) + pw_error(editor, 1, 1); +} + +void +pw_prompt() +{ + int c; + + (void)printf("re-edit the password file? [y]: "); + (void)fflush(stdout); + c = getchar(); + if (c != EOF && c != '\n') + while (getchar() != '\n'); + if (c == 'n') + pw_error(NULL, 0, 0); +} + +void +pw_error(name, err, eval) + char *name; + int err, eval; +{ + if (err) + warn(name); + + warnx("%s: unchanged", passfile); + (void)unlink(tempname); + exit(eval); +} diff --git a/gnu/usr.sbin/yppasswdd/update.c b/gnu/usr.sbin/yppasswdd/update.c new file mode 100644 index 000000000000..69bad95e9e56 --- /dev/null +++ b/gnu/usr.sbin/yppasswdd/update.c @@ -0,0 +1,156 @@ +/* + * yppasswdd + * Copyright 1994 Olaf Kirch, + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include "yppasswd.h" + +char *tempname; +extern char *passfile, *opassfile; +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); +} diff --git a/gnu/usr.sbin/yppasswdd/yppasswd.h b/gnu/usr.sbin/yppasswdd/yppasswd.h new file mode 100644 index 000000000000..fb85d8630c44 --- /dev/null +++ b/gnu/usr.sbin/yppasswdd/yppasswd.h @@ -0,0 +1,57 @@ +/* + * yppasswdd + * Copyright 1994 Olaf Kirch, + * + * 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. + * + * This file was generated automatically by rpcgen from yppasswd.x, and + * editied manually. + */ + +#ifndef _YPPASSWD_H_ +#define _YPPASSWD_H_ + +#define YPPASSWDPROG ((u_long)100009) +#define YPPASSWDVERS ((u_long)1) +#define YPPASSWDPROC_UPDATE ((u_long)1) + +/* + * The password struct passed by the update call. I renamed it to + * xpasswd to avoid a type clash with the one defined in . + */ +typedef struct xpasswd { + char *pw_name; + char *pw_passwd; + int pw_uid; + int pw_gid; + char *pw_gecos; + char *pw_dir; + char *pw_shell; +} xpasswd; + +/* The updated password information, plus the old password. + */ +typedef struct yppasswd { + char *oldpass; + xpasswd newpw; +} yppasswd; + +/* XDR encoding/decoding routines */ +bool_t xdr_xpasswd (XDR *xdrs, xpasswd *objp); +bool_t xdr_yppasswd(XDR *xdrs, yppasswd *objp); + +/* The server procedure invoked by the main loop. */ +void yppasswdprog_1(struct svc_req *rqstp, SVCXPRT *transp); + +/* Password update handler. */ +int * yppasswdproc_pwupdate_1(yppasswd *yppw, struct svc_req *rqstp); + +/* This command is forked to rebuild the NIS maps after a successful + * update. MAP_UPDATE is used as argv[0]. + */ +#define MAP_UPDATE "yppwupdate" +#define MAP_UPDATE_PATH YPLIBDIR "/yppwupdate" + +#endif _YPPASSWD_H_ diff --git a/gnu/usr.sbin/yppasswdd/yppasswd_xdr.c b/gnu/usr.sbin/yppasswdd/yppasswd_xdr.c new file mode 100644 index 000000000000..30b55c22d62c --- /dev/null +++ b/gnu/usr.sbin/yppasswdd/yppasswd_xdr.c @@ -0,0 +1,57 @@ +/* + * yppasswdd + * Copyright 1994 Olaf Kirch, + * + * 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. + * + * This file was generated automatically by rpcgen from yppasswd.x, and + * editied manually. + */ + +#include +#include "yppasswd.h" + + +bool_t +xdr_xpasswd(XDR *xdrs, xpasswd *objp) +{ + if (!xdr_string(xdrs, &objp->pw_name, ~0)) { + return (FALSE); + } + if (!xdr_string(xdrs, &objp->pw_passwd, ~0)) { + return (FALSE); + } + if (!xdr_int(xdrs, &objp->pw_uid)) { + return (FALSE); + } + if (!xdr_int(xdrs, &objp->pw_gid)) { + return (FALSE); + } + if (!xdr_string(xdrs, &objp->pw_gecos, ~0)) { + return (FALSE); + } + if (!xdr_string(xdrs, &objp->pw_dir, ~0)) { + return (FALSE); + } + if (!xdr_string(xdrs, &objp->pw_shell, ~0)) { + return (FALSE); + } + return (TRUE); +} + + +bool_t +xdr_yppasswd(XDR *xdrs, yppasswd *objp) +{ + if (!xdr_string(xdrs, &objp->oldpass, ~0)) { + return (FALSE); + } + if (!xdr_xpasswd(xdrs, &objp->newpw)) { + return (FALSE); + } + return (TRUE); +} + + diff --git a/gnu/usr.sbin/yppasswdd/yppasswdd.8 b/gnu/usr.sbin/yppasswdd/yppasswdd.8 new file mode 100644 index 000000000000..24e3ddac10b1 --- /dev/null +++ b/gnu/usr.sbin/yppasswdd/yppasswdd.8 @@ -0,0 +1,92 @@ +.\" +.\" Copyright 1994 Olaf Kirch, +.\" +.\" 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. +.\" +.TH YPPASSWDD 8 "12 December 1994" "" "" +.SH NAME +rpc.yppasswdd \- NIS password update server +.SH SYNOPSIS +.B "rpc.yppasswdd [-s]" +.SH DESCRIPTION +\fByppasswdd\fP is the RPC server that lets users change their passwords +in the presence of NIS (a.k.a. YP). It must be run on the NIS master +server for that NIS domain. +.P +When a \fByppasswd(1)\fP client contacts the server, it sends the old user +password along with the new one. \fByppasswdd\fP will search the system's +\fB/etc/passwd\fP file for the specified user name, verify that the +given (old) password matches, and update the entry. If the user +specified does not exist, or if the password, UID or GID doesn't match +the information in the password file, the update request is rejected, +and an error returned to the client. +.P +After updating the \fBpasswd\fP file and returning a success notification +to the client, \fByppasswdd\fP executes the \fBpwupdate\fP script that +updates the NIS server's \fBpasswd.*\fP maps. This script assumes all +NIS maps are kept in directories named +.BI /var/yp/< nisdomain > +that each contain a \fBMakefile\fP customized for that NIS domain. +.SH OPTIONS +The following options are available with \fByppasswdd\fP: +.IP "\-s" +When \fByppasswdd\fP is compiled with support for John\ F. Haugh's shadow +library, this option makes the server use the password functions from the +\fBlibshadow\fP library instead of the standard ones. See below for a +brief discussion of shadow support. +.SH MISCELLANEOUS +.SS Shadow Passwords +Using Shadow passwords alongside NIS does not make too much sense, because +the supposedly inaccesible passwords now become readable through a simple +invocation of \fBypcat(8)\fP. +.P +Shadow support in \fByppasswdd\fP does not mean that it offers a very +clever solution to this problem, it simply means that it can read and write +password entries in \fB/etc/shadow\fP. You still have to produce a normal +NIS map to distribute password information to your NIS clients. +The \fByp.pwupdate\fP script supplied with +\fByppasswdd\fP creates a standard \fB/etc/passwd\fP file from +\fP/etc/shadow\fP using \fBpwunconv(8)\fP and produces the NIS maps from +that. +.SS Logging +\fByppasswdd\fP logs all password update requests to \fBsyslogd(8)\fP's +auth facility. The logging information includes the originating host's +IP address and the user name and UID contained in the request. The +user-supplied password itself is not logged. +.SS Security +Unless I've screwed up completely (as I did with versions prior to +version\ 0.5), \fByppasswdd\fP should be as secure or insecure as any +program relying on simple password authentication. If you feel that +this is not enough, you may want to protect \fByppasswdd\fP from outside +access by using the `securenets' feature of the new \fBportmap(8)\fP +version\ 3. Better still, use Kerberos. +.SH COPYRIGHT +\fByppasswdd\fP is copyright (C) Olaf Kirch. You can use and distribute it +under the GNU General Public License Version 2. Note that it does \fInot\fP +contain any code from the shadow password suite. This means that as long as +you don't use shadow passwords, you won't be affected by the ``no commercial +use'' policy of the shadow suite. +.SH FILES +\fB/usr/sbin/rpc.yppasswdd\fP +.br +\fB/usr/lib/yp/pwupdate\fP +.br +\fB/etc/passwd\fP +.br +\fB/etc/shadow\fP +.SH SEE ALSO +.IR passwd(5) , +.IR passwd(8) , +.IR portmap(8) , +.IR pwunconv(8) , +.IR yppasswd(1) , +.IR ypchsh(1) , +.IR ypchfn(1) , +.IR ypserv(8) , +.IR ypcat(8) . +.SH AUTHOR +Olaf Kirch, +.br +Charles Lopez, (shadow support) diff --git a/gnu/usr.sbin/yppasswdd/yppasswdd.c b/gnu/usr.sbin/yppasswdd/yppasswdd.c new file mode 100644 index 000000000000..1088637861dc --- /dev/null +++ b/gnu/usr.sbin/yppasswdd/yppasswdd.c @@ -0,0 +1,205 @@ +/* + * yppasswdd + * Copyright 1994 Olaf Kirch, + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include "yppasswd.h" + +extern char *optarg; +static char *program_name = ""; +static char *version = "yppsswdd " VERSION; +char *passfile = _PATH_MASTERPASSWD; +char *opassfile = NULL; +int allow_chfn = 0, allow_chsh = 0; + +#define xprt_addr(xprt) (svc_getcaller(xprt)->sin_addr) +#define xprt_port(xprt) ntohs(svc_getcaller(xprt)->sin_port) +void yppasswdprog_1( struct svc_req *rqstp, SVCXPRT *transp ); +void reaper( int sig ); + +/*==============================================================* + * RPC dispatch function + *==============================================================*/ +void +yppasswdprog_1(struct svc_req *rqstp, SVCXPRT *transp) +{ + union { + yppasswd yppasswdproc_update_1_arg; + } argument; + char *result; + bool_t (*xdr_argument)(), (*xdr_result)(); + char *(*local)(); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void)svc_sendreply(transp, xdr_void, (char *)NULL); + return; + + case YPPASSWDPROC_UPDATE: + xdr_argument = xdr_yppasswd; + xdr_result = xdr_int; + local = (char *(*)()) yppasswdproc_pwupdate_1; + break; + + default: + svcerr_noproc(transp); + return; + } + bzero((char *)&argument, sizeof(argument)); + if (!svc_getargs(transp, xdr_argument, &argument)) { + svcerr_decode(transp); + return; + } + result = (*local)(&argument, rqstp); + if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, xdr_argument, &argument)) { + (void)fprintf(stderr, "unable to free arguments\n"); + exit(1); + } +} + +static void +usage(FILE *fp, int n) +{ + fprintf (fp, "usage: %s [-m master password file] [-o password file]\n [-h] [-f] [-s] [-v]\n", program_name ); + exit(n); +} + +void +reaper( int sig ) +{ + wait(NULL); +} + +void +install_reaper( void ) +{ + struct sigaction act, oact; + + act.sa_handler = reaper; + act.sa_mask = 0; + act.sa_flags = SA_RESTART; + sigaction( SIGCHLD, &act, &oact ); +} + + +int +main(int argc, char **argv) +{ + SVCXPRT *transp; + char *sp; + int opterr; + int c; + + program_name = argv[0]; + if ((sp = strrchr(program_name, '/')) != NULL) { + program_name = ++sp; + } + + /* Parse the command line options and arguments. */ + opterr = 0; + while ((c = getopt(argc, argv, "m:o:fshv")) != EOF) + switch (c) { + case 'm': + passfile = strdup(optarg); + break; + case 'o': + opassfile = strdup(optarg); + break; + case 'f': + allow_chfn = 1; + break; + case 's': + allow_chsh = 1; + break; + case 'h': + usage (stdout, 0); + break; + case 'v': + printf("%s\n", version); + exit(0); + case 0: + break; + case '?': + default: + usage(stderr, 1); + } + +#ifndef RPC_SVC_FG + /* We first fork off a child. */ + if ((c = fork()) > 0) + exit(0); + if (c < 0) { + fprintf(stderr, "yppasswdd: cannot fork: %s\n", strerror(errno)); + exit(-1); + } + /* Now we remove ourselves from the foreground. */ + (void) close(0); + (void) close(1); + (void) close(2); +#ifdef TIOCNOTTY + if ((c = open("/dev/tty", O_RDWR)) >= 0) { + (void) ioctl(c, TIOCNOTTY, (char *) NULL); + (void) close(c); + } +#else + setsid(); +#endif +#endif /* not RPC_SVC_FG */ + + /* Initialize logging. + */ + openlog ( "yppasswdd", LOG_PID, LOG_AUTH ); + + /* Register a signal handler to reap children after they terminated + */ + install_reaper(); + + /* + * Create the RPC server + */ + (void)pmap_unset(YPPASSWDPROG, YPPASSWDVERS); + + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL) { + (void)fprintf(stderr, "cannot create udp service.\n"); + exit(1); + } + if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1, + IPPROTO_UDP)) { + (void)fprintf(stderr, "unable to register yppaswdd udp service.\n"); + exit(1); + } + + /* + * Run the server + */ + svc_run(); + (void)fprintf(stderr, "svc_run returned\n"); + + return 1; +} +