Import new rpc.yppasswdd. (Note: accompanying changes to passwd(1) and
chpass(1) are on the way too.) This version supports all the features
of the old one and adds several new ones:
- Supports real multi-domain operation (optional, can be turned
on with a command-line flag). This means you can actually have
several different domains all served from one NIS server and
allow users in any of the supported domains to change their passwords.
The old yppasswdd only allowed changing passwords in the domain
that was set as the system default domain name on the NIS master
server. The new one can change passwords in any domain by trying
to match the user information passed to it against all the passwd
maps it can find. This is something of a hack, but the yppasswd.x
protocol definiton does not allow for a domain to be passwd as an
argument to rpc.yppasswdd, so the server has no choice but to
grope around for a likely match. Since this method can fail if
the same user exists in two domains, this feature is off by default.
If the feature is turned on and the server becomes confused by
duplicate entries, it will abort the update.
- Does not require NIS client services to be available. NIS servers do
_NOT_ necessarily have to be configured as NIS clients in order to
function: the ypserv, ypxfr and yppush programs I've written recently
will operate fine even if the system domain name isn't set, ypbind isn't
running and there are no magic '+' entries in any of the /etc files.
Now rpc.yppasswdd is the same way. The old yppasswdd would not work
like this because it depended on getpwent(3) and friends to look up
users: this will obviously only work if the system where yppasswdd is
running is configured as an NIS client. The new rpc.yppasswdd doesn't
use getpwent(3) at all: instead it searches through the master.passwd
map databases directly. This also makes it easier for it to handle
multiple domains.
- Allows the superuser on the NIS master server to change any user's
password without requiring password authentication. rpc.yppasswdd
creates a UNIX domain socket (/var/run/ypsock) which it monitors
using the same svc_run() loop used to handle incoming RPC requests.
It also clears all the permission bits for /var/run/ypsock; since
this socket is owned by root, this prevents anyone except root from
successfully connect()ing to it. (Using a UNIX domain socket also
prevents IP spoofing attacks.) By building code into passwd(1) and
chpass(1) to take advantage of this 'trusted' channel, the superuser
can use them to send private requests to rpc.yppasswdd.
- Allows the superuser on the NIS master to use chpass(1) to update _all_
of a user's master.passwd information. The UNIX domain access point
accepts a full master.passwd style structure (along with a domain
name and other information), which allows the superuser to update all
of a user's master.passwd information in the NIS master.passwd maps.
Normal users on NIS clients are still only allowed to change their full
name and shell information with chpass.
- Allows the superuser on the NIS master to _add_ records to the NIS
master.passwd maps using chpass(1). This feature is also switchable
with a command-line flag and is off by default.
1996-02-12 15:09:01 +00:00
|
|
|
/*-
|
|
|
|
* 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
|
1997-10-13 11:18:53 +00:00
|
|
|
#if 0
|
Import new rpc.yppasswdd. (Note: accompanying changes to passwd(1) and
chpass(1) are on the way too.) This version supports all the features
of the old one and adds several new ones:
- Supports real multi-domain operation (optional, can be turned
on with a command-line flag). This means you can actually have
several different domains all served from one NIS server and
allow users in any of the supported domains to change their passwords.
The old yppasswdd only allowed changing passwords in the domain
that was set as the system default domain name on the NIS master
server. The new one can change passwords in any domain by trying
to match the user information passed to it against all the passwd
maps it can find. This is something of a hack, but the yppasswd.x
protocol definiton does not allow for a domain to be passwd as an
argument to rpc.yppasswdd, so the server has no choice but to
grope around for a likely match. Since this method can fail if
the same user exists in two domains, this feature is off by default.
If the feature is turned on and the server becomes confused by
duplicate entries, it will abort the update.
- Does not require NIS client services to be available. NIS servers do
_NOT_ necessarily have to be configured as NIS clients in order to
function: the ypserv, ypxfr and yppush programs I've written recently
will operate fine even if the system domain name isn't set, ypbind isn't
running and there are no magic '+' entries in any of the /etc files.
Now rpc.yppasswdd is the same way. The old yppasswdd would not work
like this because it depended on getpwent(3) and friends to look up
users: this will obviously only work if the system where yppasswdd is
running is configured as an NIS client. The new rpc.yppasswdd doesn't
use getpwent(3) at all: instead it searches through the master.passwd
map databases directly. This also makes it easier for it to handle
multiple domains.
- Allows the superuser on the NIS master server to change any user's
password without requiring password authentication. rpc.yppasswdd
creates a UNIX domain socket (/var/run/ypsock) which it monitors
using the same svc_run() loop used to handle incoming RPC requests.
It also clears all the permission bits for /var/run/ypsock; since
this socket is owned by root, this prevents anyone except root from
successfully connect()ing to it. (Using a UNIX domain socket also
prevents IP spoofing attacks.) By building code into passwd(1) and
chpass(1) to take advantage of this 'trusted' channel, the superuser
can use them to send private requests to rpc.yppasswdd.
- Allows the superuser on the NIS master to use chpass(1) to update _all_
of a user's master.passwd information. The UNIX domain access point
accepts a full master.passwd style structure (along with a domain
name and other information), which allows the superuser to update all
of a user's master.passwd information in the NIS master.passwd maps.
Normal users on NIS clients are still only allowed to change their full
name and shell information with chpass.
- Allows the superuser on the NIS master to _add_ records to the NIS
master.passwd maps using chpass(1). This feature is also switchable
with a command-line flag and is off by default.
1996-02-12 15:09:01 +00:00
|
|
|
static char sccsid[] = "@(#)pw_util.c 8.3 (Berkeley) 4/2/94";
|
1997-10-13 11:18:53 +00:00
|
|
|
#endif
|
|
|
|
static const char rcsid[] =
|
1999-08-28 01:35:59 +00:00
|
|
|
"$FreeBSD$";
|
Import new rpc.yppasswdd. (Note: accompanying changes to passwd(1) and
chpass(1) are on the way too.) This version supports all the features
of the old one and adds several new ones:
- Supports real multi-domain operation (optional, can be turned
on with a command-line flag). This means you can actually have
several different domains all served from one NIS server and
allow users in any of the supported domains to change their passwords.
The old yppasswdd only allowed changing passwords in the domain
that was set as the system default domain name on the NIS master
server. The new one can change passwords in any domain by trying
to match the user information passed to it against all the passwd
maps it can find. This is something of a hack, but the yppasswd.x
protocol definiton does not allow for a domain to be passwd as an
argument to rpc.yppasswdd, so the server has no choice but to
grope around for a likely match. Since this method can fail if
the same user exists in two domains, this feature is off by default.
If the feature is turned on and the server becomes confused by
duplicate entries, it will abort the update.
- Does not require NIS client services to be available. NIS servers do
_NOT_ necessarily have to be configured as NIS clients in order to
function: the ypserv, ypxfr and yppush programs I've written recently
will operate fine even if the system domain name isn't set, ypbind isn't
running and there are no magic '+' entries in any of the /etc files.
Now rpc.yppasswdd is the same way. The old yppasswdd would not work
like this because it depended on getpwent(3) and friends to look up
users: this will obviously only work if the system where yppasswdd is
running is configured as an NIS client. The new rpc.yppasswdd doesn't
use getpwent(3) at all: instead it searches through the master.passwd
map databases directly. This also makes it easier for it to handle
multiple domains.
- Allows the superuser on the NIS master server to change any user's
password without requiring password authentication. rpc.yppasswdd
creates a UNIX domain socket (/var/run/ypsock) which it monitors
using the same svc_run() loop used to handle incoming RPC requests.
It also clears all the permission bits for /var/run/ypsock; since
this socket is owned by root, this prevents anyone except root from
successfully connect()ing to it. (Using a UNIX domain socket also
prevents IP spoofing attacks.) By building code into passwd(1) and
chpass(1) to take advantage of this 'trusted' channel, the superuser
can use them to send private requests to rpc.yppasswdd.
- Allows the superuser on the NIS master to use chpass(1) to update _all_
of a user's master.passwd information. The UNIX domain access point
accepts a full master.passwd style structure (along with a domain
name and other information), which allows the superuser to update all
of a user's master.passwd information in the NIS master.passwd maps.
Normal users on NIS clients are still only allowed to change their full
name and shell information with chpass.
- Allows the superuser on the NIS master to _add_ records to the NIS
master.passwd maps using chpass(1). This feature is also switchable
with a command-line flag and is off by default.
1996-02-12 15:09:01 +00:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file is used by all the "password" programs; vipw(8), chpass(1),
|
|
|
|
* and passwd(1).
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/resource.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
|
|
|
#include <err.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <paths.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <pw_util.h>
|
|
|
|
#include "yppasswdd_extern.h"
|
|
|
|
|
|
|
|
int pstat;
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
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(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) {
|
|
|
|
yp_error("%s: %s", passfile, strerror(errno));
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
if (flock(lockfd, LOCK_EX|LOCK_NB)) {
|
|
|
|
yp_error("%s: the password db file is busy", passfile);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
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) {
|
|
|
|
yp_error("%s: %s", path, strerror(errno));
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
tempname = path;
|
|
|
|
return (fd);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1996-07-01 19:38:50 +00:00
|
|
|
pw_mkdb(username)
|
|
|
|
char *username;
|
Import new rpc.yppasswdd. (Note: accompanying changes to passwd(1) and
chpass(1) are on the way too.) This version supports all the features
of the old one and adds several new ones:
- Supports real multi-domain operation (optional, can be turned
on with a command-line flag). This means you can actually have
several different domains all served from one NIS server and
allow users in any of the supported domains to change their passwords.
The old yppasswdd only allowed changing passwords in the domain
that was set as the system default domain name on the NIS master
server. The new one can change passwords in any domain by trying
to match the user information passed to it against all the passwd
maps it can find. This is something of a hack, but the yppasswd.x
protocol definiton does not allow for a domain to be passwd as an
argument to rpc.yppasswdd, so the server has no choice but to
grope around for a likely match. Since this method can fail if
the same user exists in two domains, this feature is off by default.
If the feature is turned on and the server becomes confused by
duplicate entries, it will abort the update.
- Does not require NIS client services to be available. NIS servers do
_NOT_ necessarily have to be configured as NIS clients in order to
function: the ypserv, ypxfr and yppush programs I've written recently
will operate fine even if the system domain name isn't set, ypbind isn't
running and there are no magic '+' entries in any of the /etc files.
Now rpc.yppasswdd is the same way. The old yppasswdd would not work
like this because it depended on getpwent(3) and friends to look up
users: this will obviously only work if the system where yppasswdd is
running is configured as an NIS client. The new rpc.yppasswdd doesn't
use getpwent(3) at all: instead it searches through the master.passwd
map databases directly. This also makes it easier for it to handle
multiple domains.
- Allows the superuser on the NIS master server to change any user's
password without requiring password authentication. rpc.yppasswdd
creates a UNIX domain socket (/var/run/ypsock) which it monitors
using the same svc_run() loop used to handle incoming RPC requests.
It also clears all the permission bits for /var/run/ypsock; since
this socket is owned by root, this prevents anyone except root from
successfully connect()ing to it. (Using a UNIX domain socket also
prevents IP spoofing attacks.) By building code into passwd(1) and
chpass(1) to take advantage of this 'trusted' channel, the superuser
can use them to send private requests to rpc.yppasswdd.
- Allows the superuser on the NIS master to use chpass(1) to update _all_
of a user's master.passwd information. The UNIX domain access point
accepts a full master.passwd style structure (along with a domain
name and other information), which allows the superuser to update all
of a user's master.passwd information in the NIS master.passwd maps.
Normal users on NIS clients are still only allowed to change their full
name and shell information with chpass.
- Allows the superuser on the NIS master to _add_ records to the NIS
master.passwd maps using chpass(1). This feature is also switchable
with a command-line flag and is off by default.
1996-02-12 15:09:01 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
yp_error("rebuilding the database...");
|
|
|
|
(void)fflush(stderr);
|
|
|
|
/* Temporarily turn off SIGCHLD catching */
|
|
|
|
install_reaper(0);
|
|
|
|
if (!(pid = vfork())) {
|
1996-07-01 19:38:50 +00:00
|
|
|
if(!username) {
|
2001-07-09 09:24:06 +00:00
|
|
|
execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname,
|
|
|
|
(char *)NULL);
|
1996-07-01 19:38:50 +00:00
|
|
|
} else {
|
|
|
|
execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-u", username,
|
2001-07-09 09:24:06 +00:00
|
|
|
tempname, (char *)NULL);
|
1996-07-01 19:38:50 +00:00
|
|
|
}
|
Import new rpc.yppasswdd. (Note: accompanying changes to passwd(1) and
chpass(1) are on the way too.) This version supports all the features
of the old one and adds several new ones:
- Supports real multi-domain operation (optional, can be turned
on with a command-line flag). This means you can actually have
several different domains all served from one NIS server and
allow users in any of the supported domains to change their passwords.
The old yppasswdd only allowed changing passwords in the domain
that was set as the system default domain name on the NIS master
server. The new one can change passwords in any domain by trying
to match the user information passed to it against all the passwd
maps it can find. This is something of a hack, but the yppasswd.x
protocol definiton does not allow for a domain to be passwd as an
argument to rpc.yppasswdd, so the server has no choice but to
grope around for a likely match. Since this method can fail if
the same user exists in two domains, this feature is off by default.
If the feature is turned on and the server becomes confused by
duplicate entries, it will abort the update.
- Does not require NIS client services to be available. NIS servers do
_NOT_ necessarily have to be configured as NIS clients in order to
function: the ypserv, ypxfr and yppush programs I've written recently
will operate fine even if the system domain name isn't set, ypbind isn't
running and there are no magic '+' entries in any of the /etc files.
Now rpc.yppasswdd is the same way. The old yppasswdd would not work
like this because it depended on getpwent(3) and friends to look up
users: this will obviously only work if the system where yppasswdd is
running is configured as an NIS client. The new rpc.yppasswdd doesn't
use getpwent(3) at all: instead it searches through the master.passwd
map databases directly. This also makes it easier for it to handle
multiple domains.
- Allows the superuser on the NIS master server to change any user's
password without requiring password authentication. rpc.yppasswdd
creates a UNIX domain socket (/var/run/ypsock) which it monitors
using the same svc_run() loop used to handle incoming RPC requests.
It also clears all the permission bits for /var/run/ypsock; since
this socket is owned by root, this prevents anyone except root from
successfully connect()ing to it. (Using a UNIX domain socket also
prevents IP spoofing attacks.) By building code into passwd(1) and
chpass(1) to take advantage of this 'trusted' channel, the superuser
can use them to send private requests to rpc.yppasswdd.
- Allows the superuser on the NIS master to use chpass(1) to update _all_
of a user's master.passwd information. The UNIX domain access point
accepts a full master.passwd style structure (along with a domain
name and other information), which allows the superuser to update all
of a user's master.passwd information in the NIS master.passwd maps.
Normal users on NIS clients are still only allowed to change their full
name and shell information with chpass.
- Allows the superuser on the NIS master to _add_ records to the NIS
master.passwd maps using chpass(1). This feature is also switchable
with a command-line flag and is off by default.
1996-02-12 15:09:01 +00:00
|
|
|
pw_error(_PATH_PWD_MKDB, 1, 1);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
/* Handle this ourselves. */
|
|
|
|
reaper(-1);
|
|
|
|
/* Put the handler back. Foo. */
|
|
|
|
install_reaper(1);
|
|
|
|
if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) {
|
|
|
|
return (-1);
|
|
|
|
}
|
|
|
|
yp_error("done");
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pw_error(name, err, eval)
|
|
|
|
char *name;
|
|
|
|
int err, eval;
|
|
|
|
{
|
|
|
|
if (err && name != NULL)
|
|
|
|
yp_error("%s", name);
|
|
|
|
|
|
|
|
yp_error("%s: unchanged", passfile);
|
|
|
|
(void)unlink(tempname);
|
|
|
|
}
|