Files
Arquivotheca.SunOS-4.1.4/usr.etc/rpc.yppasswdd.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

907 lines
23 KiB
C

#ifndef lint
static char sccsid[] = "@(#)rpc.yppasswdd.c 1.1 94/10/31 Copyr 1985 Sun Micro";
#endif
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <signal.h>
#include <sys/file.h>
#include <rpc/rpc.h>
#include <pwd.h>
#include <sys/label.h>
#include <sys/audit.h>
#include <pwdadj.h>
#include <rpcsvc/yppasswd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <ctype.h>
#include <strings.h>
#include <syslog.h>
#include <sys/resource.h>
#define pwmatch(name, line, cnt) \
(line[cnt] == ':' && strncmp(name, line, cnt) == 0)
char *file; /* file in which passwd's are found */
char *filea; /* adjunct file in which passwd's are found */
char temp[96]; /* lockfile for modifying 'file' */
int mflag; /* do a make */
int useadjunct; /* use the adjunct file */
char *audit_argv[] = { "rpc.yppasswdd", 0, 0 };
extern char *crypt();
extern int errno;
static void boilerplate();
int Argc;
char **Argv;
/* must match sizes in passwd */
#define STRSIZE 100
#define PWBUFSIZE 10
#define PWSIZE (PWBUFSIZE - 1)
#define CRYPTPWSIZE 13
#define FINGERSIZE (4 * STRSIZE - 4)
#define SHELLSIZE (STRSIZE - 2)
#define AUDIT_USER "AUyppasswdd"
int Mstart;
int single = 1;
int nogecos = 0;
int noshell = 0;
int nopw = 0;
int childpid = 0;
#define LOCK "/etc/ptmp"
main(argc, argv)
int argc;
char **argv;
{
SVCXPRT *transp;
int s;
char *cp; /* Temporary for building the temp file name */
int i;
Argc = argc;
Argv = argv;
if (argc < 2) {
(void)fprintf(stderr,
"usage: %s file [adjfile] [-nosingle] [-nopw] [-nogecos] [-noshell] [-m arg1 arg2 ...]\n",
argv[0]);
exit(1);
}
file = argv[1];
if (access(file, W_OK) < 0) {
(void)fprintf(stderr, "yppasswdd: can't write %s\n", file);
exit(1);
}
useadjunct = 0;
if (argc > 2 && argv[2][0] == '-' && argv[2][1] == 'm')
mflag++;
else if (argc > 2) {
/*
* see if they have specified an adjunct passwd file
*/
if (argv[2][0] != '-') {
filea = argv[2];
useadjunct = 1;
if (access(filea, W_OK) < 0) {
(void)fprintf(stderr,
"yppasswdd: can't write %s\n", filea);
exit(1);
}
i = 3;
} else
i = 2;
for (; i<argc; i++){
if (strcmp(argv[i], "-m") == 0) {
mflag++;
Mstart=i;
break;
} else if (strcmp(argv[i], "-single") == 0)
single = 1;
else if (strcmp(argv[i], "-nosingle") == 0)
single = 0;
else if (strcmp(argv[i], "-nogecos") == 0)
nogecos = 1;
else if (strcmp(argv[i], "-nopw") == 0)
nopw = 1;
else if (strcmp(argv[i], "-noshell") == 0)
noshell = 1;
else
(void)fprintf(stderr,
"yppasswdd: unknown option %s ignored\n",
argv[i]);
}
}
if (!useadjunct) {
/*
* they didn't specify an adjunct file - see whether
* /etc/security/passwd.adjunct is accessible
*/
filea = "/etc/security/passwd.adjunct";
if (access(filea, W_OK) == 0) {
/* They are using the adjunct file */
useadjunct = 1;
}
}
if (chdir("/var/yp") < 0) {
(void)fprintf(stderr, "yppasswdd: can't chdir to /var/yp\n");
exit(1);
}
/* make a temp file in the same dir as the passwd file */
(void)strcpy(temp, useadjunct ? filea : file);
/* find end of the path ... */
for (cp = &(temp[strlen(temp)]); (cp != temp) && (*cp != '/'); cp--)
;
if (*cp == '/')
(void)strcat(cp+1, ".ptmp");
else
(void)strcat(cp, ".ptmp");
/* temp now has either '.ptmp' or 'filepath/.ptmp' in it */
#ifndef DEBUG
if (fork())
exit(0);
{ int t;
for (t = getdtablesize()-1; t >= 0; t--)
(void) close(t);
}
(void) open("/dev/null", O_RDWR);
(void) dup2(0, 1);
(void) dup2(0, 2);
{
int tt = open("/dev/tty", O_RDWR);
if (tt > 0) {
(void)ioctl(tt, TIOCNOTTY, 0);
(void)close(tt);
}
}
#endif
openlog("yppasswdd", LOG_CONS| LOG_PID, LOG_AUTH);
unlimit(RLIMIT_CPU);
unlimit(RLIMIT_FSIZE);
if ((s = rresvport()) < 0) {
syslog(LOG_ERR,
"yppasswdd: can't bind to a privileged socket\n");
exit(1);
}
transp = svcudp_create(s);
if (transp == NULL) {
syslog(LOG_ERR, "yppasswdd: couldn't create an RPC server\n");
exit(1);
}
(void)pmap_unset((u_long)YPPASSWDPROG, (u_long)YPPASSWDVERS);
if (!svc_register(transp, (u_long)YPPASSWDPROG, (u_long)YPPASSWDVERS,
boilerplate, IPPROTO_UDP)) {
syslog(LOG_ERR, "yppasswdd: couldn't register yppasswdd\n");
exit(1);
}
svc_run();
syslog(LOG_ERR, "yppasswdd: svc_run shouldn't have returned\n");
exit(1);
/* NOTREACHED */
}
static void
boilerplate(rqstp, transp)
struct svc_req *rqstp;
SVCXPRT *transp;
{
switch (rqstp->rq_proc) {
case NULLPROC:
if (!svc_sendreply(transp, xdr_void, (char *)0))
syslog(LOG_WARNING,
"yppasswdd: couldn't reply to RPC call\n");
break;
case YPPASSWDPROC_UPDATE:
changepasswd(rqstp, transp, useadjunct);
break;
}
}
/*ARGSUSED*/
changepasswd(rqstp, transp, useadjunct)
struct svc_req *rqstp;
SVCXPRT *transp;
int useadjunct; /* local copy */
{
int num, tmpfd, tempfd, lockfd, i, len;
static int ans;
FILE *tempfp, *filefp;
char tmpbuf[512], buf[256], *p;
char cmdbuf[BUFSIZ];
void (*f1)(), (*f2)(), (*f3)();
struct passwd *oldpw, *newpw, temppw;
struct passwd *getpwnam();
struct passwd_adjunct *oldpwa;
struct passwd_adjunct *getpwanam();
struct yppasswd yppasswd;
union wait status;
char *ptr;
char str1[224];
char str2[224];
char tmpname[30], tmppw[30];
char tmpcomment[512], tmpgecos[512], tmpdir[256], tmpshell[100];
int changedpw = 0;
int changedsh = 0;
int changedgecos = 0;
char *cp;
#ifdef EXTRA_PARANOID
struct sockaddr_in *caller;
caller = svc_getcaller(transp);
if ((caller->sin_family != AF_INET) ||
(ntohs(caller->sin_port)) >= IPPORT_RESERVED ||
(! yp_valid_client(ntohl(caller->sin_addr.s_addr)))) {
svcerr_weakauth(transp);
return;
}
#endif
bzero((char *)&yppasswd, sizeof (yppasswd));
if (!svc_getargs(transp, xdr_yppasswd, &yppasswd)) {
svcerr_decode(transp);
return;
}
if ((! validstr(yppasswd.oldpass, PWSIZE)) ||
(! validstr(yppasswd.newpw.pw_passwd, CRYPTPWSIZE)) ||
(! validstr(yppasswd.newpw.pw_gecos, FINGERSIZE)) ||
(! validstr(yppasswd.newpw.pw_shell, SHELLSIZE))) {
svcerr_decode(transp);
return;
}
/*
* Clean up from previous changepasswd() call
*/
while (wait3(&status, WNOHANG, (struct rusage *)0) > 0)
continue;
if (mflag && childpid) {
if (kill(childpid, 0) == 0) {
syslog(LOG_WARNING, "password file busy - try again.\n");
ans = 8;
goto cleanup;
}
else
childpid = 0;
}
newpw = &yppasswd.newpw;
ans = 2;
changedsh = 0;
changedpw = 0;
changedgecos = 0;
oldpw = getpwnam(newpw->pw_name);
/*
This fixed part of bug 1059261, which is running "chsh -y" will
overwrote the user's passwd entry by the "AUyppasswdd" passwd entry.
Now make a dup of oldpw contents. This will prevent the oldpw
contents get wrap out by the "passwd" static variable which
was defined in the getpwnam routine.
*/
(void)strncpy(tmpname, oldpw->pw_name, strlen(oldpw->pw_name));
tmpname[strlen(oldpw->pw_name)] = '\0';
(void)strncpy(tmppw, oldpw->pw_passwd, strlen(oldpw->pw_passwd));
tmppw[strlen(oldpw->pw_passwd)] = '\0';
(void)strncpy(tmpcomment, oldpw->pw_comment, strlen(oldpw->pw_comment)); tmpcomment[strlen(oldpw->pw_comment)] = '\0';
(void)strncpy(tmpgecos, oldpw->pw_gecos, strlen(oldpw->pw_gecos));
tmpgecos[strlen(oldpw->pw_gecos)] = '\0';
(void)strncpy(tmpdir, oldpw->pw_dir, strlen(oldpw->pw_dir));
tmpdir[strlen(oldpw->pw_dir)] = '\0';
(void)strncpy(tmpshell, oldpw->pw_shell, strlen(oldpw->pw_shell));
tmpshell[strlen(oldpw->pw_shell)] = '\0';
bcopy(oldpw, &temppw, sizeof(struct passwd));
temppw.pw_name = tmpname;
temppw.pw_passwd = tmppw;
temppw.pw_comment = tmpcomment;
temppw.pw_gecos = tmpgecos;
temppw.pw_dir = tmpdir;
temppw.pw_shell = tmpshell;
oldpw = &temppw;
if (oldpw == NULL) {
syslog(LOG_NOTICE, "yppasswdd: no passwd for %s\n",
newpw->pw_name);
goto done;
}
if ((!nopw) && (strcmp(oldpw->pw_passwd, newpw->pw_passwd) != 0))
changedpw = 1;
if ((!noshell) &&
(strcmp(oldpw->pw_shell, newpw->pw_shell) != 0)){
if (single) changedpw = 0;
changedsh = 1;
}
if ((!nogecos) &&
(strcmp(oldpw->pw_gecos, newpw->pw_gecos) != 0)){
if (single){
changedpw = 0;
changedsh = 0;
}
changedgecos = 1;
}
if (!(changedpw + changedgecos + changedsh)) {
syslog(LOG_NOTICE, "yppasswdd: no change for %s\n",
newpw->pw_name);
ans = 3;
goto done;
}
if (/* changedpw && */ useadjunct) { /* check passwd always */
if (setauditid()) {
syslog(LOG_ERR,
"yppasswdd: no entry in adjunct for %s\n",
AUDIT_USER);
goto done;
}
audit_argv[1] = newpw->pw_name;
oldpwa = getpwanam(newpw->pw_name);
if (oldpwa == NULL) {
audit_argv[2] = "Not in passwd.adjunct.";
audit_text(AU_ADMIN, 0, 1, 3, audit_argv);
syslog(LOG_ERR,
"yppasswdd: no passwd in adjunct for %s\n",
newpw->pw_name);
ans = 4;
goto done;
}
if (oldpwa->pwa_passwd && *oldpwa->pwa_passwd &&
oldpwa->pwa_passwd[0] != '#' &&
strcmp(crypt(yppasswd.oldpass, oldpwa->pwa_passwd),
oldpwa->pwa_passwd) != 0) {
audit_argv[2] = "Bad password in passwd.adjunct.";
audit_text(AU_ADMIN, 0, 1, 3, audit_argv);
syslog(LOG_ERR, "yppasswdd: %s: bad password\n",
newpw->pw_name);
ans = 5;
goto done;
}
ptr = oldpw->pw_passwd;
if (ptr && *ptr && (*ptr++ != '#' && *ptr++ != '#' &&
!strcmp(ptr, oldpw->pw_name))) {
audit_argv[2] = "Inconsistency between passwd files.";
audit_text(AU_ADMIN, 0, 1, 3, audit_argv);
syslog(LOG_ERR, "yppasswdd: inconsistency for %s\n",
newpw->pw_name);
ans = 6;
goto done;
}
} else {
if (/*changedpw && */oldpw->pw_passwd && *oldpw->pw_passwd &&
strcmp(crypt(yppasswd.oldpass, oldpw->pw_passwd),
oldpw->pw_passwd) != 0) {
syslog(LOG_NOTICE,
"%s: password incorrect\n", newpw->pw_name);
ans = 7;
goto done;
}
}
(void)printf("%d %d %d\n", changedsh, changedgecos, changedpw);
(void)printf("%s %s %s\n", yppasswd.newpw.pw_shell,
yppasswd.newpw.pw_gecos, yppasswd.newpw.pw_passwd);
(void)printf("%s %s %s\n", oldpw->pw_shell, oldpw->pw_gecos,
oldpw->pw_passwd);
if (changedsh && !validloginshell(oldpw, yppasswd.newpw.pw_shell)) {
goto done;
}
(void) umask(0);
f1 = signal(SIGHUP, SIG_IGN);
f2 = signal(SIGINT, SIG_IGN);
f3 = signal(SIGQUIT, SIG_IGN);
(void)signal(SIGTSTP, SIG_IGN);
/* check if somebody has /etc/ptmp open to be compatible with other programs */
lockfd = open(LOCK, O_WRONLY|O_CREAT|O_EXCL, 0644);
if (lockfd < 0) {
if (errno == EEXIST){
syslog(LOG_WARNING,
"password file is locked - try again.\n");
ans = 8;
} else {
ans = 9;
syslog(LOG_ERR,
"password lock file open bug %s %m.\n", LOCK);
perror(LOCK);
}
goto cleanup;
}
changeothers:
(void)strcpy(temp, useadjunct ? filea : file);
/* find end of the path ... */
for (cp = &(temp[strlen(temp)]); (cp != temp) && (*cp != '/'); cp--)
;
if (*cp == '/')
(void)strcat(cp + 1, ".ptmp");
else
(void)strcat(cp, ".ptmp");
/* temp now has either '.ptmp' or 'filepath/.ptmp' in it */
tempfd = open(temp, O_WRONLY|O_CREAT|O_EXCL, 0644);
if (tempfd < 0) {
if (errno == EEXIST){
syslog(LOG_WARNING,
"password file busy - try again.\n");
ans = 8;
} else {
ans = 9;
syslog(LOG_ERR,
"password temp file open bug %s %m.\n", temp);
perror(temp);
}
goto cleanup;
}
if ((tempfp = fdopen(tempfd, "w")) == NULL) {
syslog(LOG_ERR, "yppasswdd: %s fdopen failed\n", temp);
ans = 10;
goto cleanup;
}
/*
* Copy passwd to temp, replacing matching lines
* with new password.
*/
if (changedpw && useadjunct) {
if ((filefp = fopen(filea, "r")) == NULL) {
syslog(LOG_CRIT, "fopen of %s failed %m\n",
filea);
ans = 11;
goto cleanup;
}
} else {
if ((filefp = fopen(file, "r")) == NULL) {
syslog(LOG_CRIT, "fopen of %s failed %m\n",
file);
ans = 12;
goto cleanup;
}
}
len = strlen(newpw->pw_name);
/*
* This fixes a really bogus security hole, basically anyone can
* call the rpc passwd daemon, give them their own passwd and a
* new one that consists of ':0:0:Im root now:/:/bin/csh^J' and
* give themselves root access. With this code it will simply make
* it impossible for them to login again, and as a bonus leave
* a cookie for the always vigilant system administrator to ferret
* them out.
*/
for (p = newpw->pw_name; (*p != '\0'); p++)
if ((*p == ':') || !(isprint(*p)))
*p = '$'; /* you lose buckwheat */
for (p = newpw->pw_passwd; (*p != '\0'); p++)
if ((*p == ':') || !(isprint(*p)))
*p = '$'; /* you lose buckwheat */
while (fgets(buf, sizeof (buf), filefp)) {
p = index(buf, ':');
if (p && p - buf == len &&
strncmp(newpw->pw_name, buf, p - buf) == 0) {
if (changedpw && useadjunct) {
getauditflagschar(str1, &oldpwa->pwa_au_always,
0);
getauditflagschar(str2, &oldpwa->pwa_au_never,
0);
(void)fprintf(tempfp, "%s:%s:%s:%s:%s:%s:%s\n",
oldpwa->pwa_name,
newpw->pw_passwd,
labeltostring(0, &oldpwa->pwa_minimum, 0),
labeltostring(0, &oldpwa->pwa_maximum, 0),
labeltostring(0, &oldpwa->pwa_def, 0),
str1,
str2);
} else
(void)fprintf(tempfp, "%s:%s:%d:%d:%s:%s:%s\n",
oldpw->pw_name,
(changedpw ?
newpw->pw_passwd: oldpw->pw_passwd),
oldpw->pw_uid,
oldpw->pw_gid,
(changedgecos ?
newpw->pw_gecos : oldpw->pw_gecos),
oldpw->pw_dir,
(changedsh ?
newpw->pw_shell : oldpw->pw_shell));
} else {
if (fputs(buf, tempfp) == EOF) {
syslog(LOG_CRIT, "%s: write error\n", "passwd");
ans = 13;
goto cleanup;
}
}
if (ferror(tempfp)) {
syslog(LOG_CRIT, "%s: write ferror set.\n", "passwd");
ans = 14;
goto cleanup;
}
}
(void)fclose(filefp);
(void)fflush(tempfp);
if (ferror(tempfp)) {
syslog(LOG_CRIT, "%s: fflush ferror set.\n", "passwd");
ans = 15;
goto cleanup;
}
(void)fclose(tempfp);
tempfp = (FILE *) NULL;
tempfd = open(temp, O_RDONLY);
/* Since the fix for security bug id 1043667 always use
/etc/ptmp as lock file and there is a chance that both
/etc/ptmp and NIS passwd file do not resided in the same
file system, therefore we cannot use "rename" to update the
passwd file. Instead I use read, write and unlink to
replace the rename
*/
if (useadjunct) { /* always gen audit record */
/*
this fixed the passwd.adjunct file get overwritten
by the /etc/passwd. Bug id 1059261
*/
if (changedpw) {
/* if (rename(temp, filea) < 0)
syslog(LOG_CRIT, "yppasswdd: "); perror("rename");
(void)unlink(temp);
*/
tmpfd = open(filea, O_WRONLY|O_TRUNC);
while ((num = read(tempfd, tmpbuf, 512)) > 0)
if (write(tmpfd, tmpbuf, num) < 0) {
syslog(LOG_CRIT, "yppasswdd: "); perror("write");
(void)unlink(temp);
ans = 16;
goto cleanup;
}
} else {
/* if (rename(temp, file) < 0)
syslog(LOG_CRIT, "yppasswdd: "); perror("rename");
(void)unlink(temp);
*/
tmpfd = open(file, O_WRONLY|O_TRUNC);
while ((num = read(tempfd, tmpbuf, 512)) > 0)
if (write(tmpfd, tmpbuf, num) < 0) {
syslog(LOG_CRIT, "yppasswdd: "); perror("write");
(void)unlink(temp);
ans = 17;
goto cleanup;
}
}
audit_argv[2] = "Successful.";
audit_text(AU_ADMIN, 0, 0, 3, audit_argv);
} else {
/* if (rename(temp, file) < 0)
syslog(LOG_CRIT, "yppasswdd: "); perror("rename");
(void)unlink(temp);
*/
tmpfd = open(file, O_WRONLY|O_TRUNC);
while ((num = read(tempfd, tmpbuf, 512)) > 0)
if (write(tmpfd, tmpbuf, num) < 0) {
syslog(LOG_CRIT, "yppasswdd: "); perror("write");
(void)unlink(temp);
ans = 17;
goto cleanup;
}
}
close(tempfd);
close(tmpfd);
(void)unlink(temp);
if (useadjunct && changedpw && (changedsh || changedgecos)) {
(void)printf("changed both pw and %d %d\n",
changedsh, changedgecos);
useadjunct = 0;
changedpw = 0; /* already changed it */
goto changeothers;
}
ans = 0;
if (mflag) {
if ((childpid = fork()) == 0) {
(void)strcpy(cmdbuf, "make");
for (i = Mstart; i < Argc; i++) {
(void)strcat(cmdbuf, " ");
(void)strcat(cmdbuf, Argv[i]);
}
#ifdef DEBUG
syslog(LOG_ERR, "about to execute %s\n", cmdbuf);
#else
(void)system(cmdbuf);
#endif
if (lockfd > 0) {
close(lockfd);
unlink(LOCK);
}
exit(0);
}
}
cleanup:
if (tempfp)
(void)fclose(tempfp);
if (lockfd > 0) {
close(lockfd);
unlink(LOCK);
}
(void)signal(SIGHUP, f1);
(void)signal(SIGINT, f2);
(void)signal(SIGQUIT, f3);
done:
if (!svc_sendreply(transp, xdr_int, (char *)&ans))
syslog(LOG_WARNING, "yppasswdd: couldnt reply to RPC call\n");
}
static int
rresvport()
{
struct sockaddr_in sin;
int s, alport = IPPORT_RESERVED - 1;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s < 0)
return (-1);
for (; ;) {
sin.sin_port = htons((u_short)alport);
if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) >= 0)
return (s);
if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
perror("socket");
syslog(LOG_ERR, "socket: %m\n");
return (-1);
}
(alport)--;
if (alport == IPPORT_RESERVED/2) {
syslog(LOG_ERR, "socket: All ports in use\n");
return (-1);
}
}
}
static char *
pwskip(p)
register char *p;
{
while (*p && *p != ':' && *p != '\n')
++p;
if (*p) *p++ = 0;
return (p);
}
static struct passwd *
getpwnam(name)
char *name;
{
FILE *pwf;
int cnt;
char *p;
static char line[BUFSIZ+1];
static struct passwd passwd;
pwf = fopen(file, "r");
if (pwf == NULL)
return (NULL);
cnt = strlen(name);
while ((p = fgets(line, BUFSIZ, pwf)) && !pwmatch(name, line, cnt))
;
if (p) {
passwd.pw_name = p;
p = pwskip(p);
passwd.pw_passwd = p;
p = pwskip(p);
passwd.pw_uid = atoi(p);
p = pwskip(p);
passwd.pw_gid = atoi(p);
passwd.pw_comment = "";
p = pwskip(p);
passwd.pw_gecos = p;
p = pwskip(p);
passwd.pw_dir = p;
p = pwskip(p);
passwd.pw_shell = p;
while (*p && *p != '\n') p++;
*p = '\0';
(void)fclose(pwf);
return (&passwd);
} else {
(void)fclose(pwf);
return (NULL);
}
}
static struct passwd_adjunct *
getpwanam(name)
char *name;
{
FILE *pwfa;
int cnt;
char *p;
static char line[BUFSIZ+1];
static struct passwd_adjunct pwdadj;
char *field;
pwfa = fopen(filea, "r");
if (pwfa == NULL)
return (NULL);
cnt = strlen(name);
while ((p = fgets(line, BUFSIZ, pwfa)) && !pwmatch(name, line, cnt))
;
if (p) {
pwdadj.pwa_name = p;
p = pwskip(p);
pwdadj.pwa_passwd = p;
p = pwskip(p);
field = p;
p = pwskip(p);
labelfromstring(0, field, &pwdadj.pwa_minimum);
field = p;
p = pwskip(p);
labelfromstring(0, field, &pwdadj.pwa_maximum);
field = p;
p = pwskip(p);
labelfromstring(0, field, &pwdadj.pwa_def);
field = p;
p = pwskip(p);
pwdadj.pwa_au_always.as_success = 0;
pwdadj.pwa_au_always.as_failure = 0;
if (getauditflagsbin(field, &pwdadj.pwa_au_always) != 0)
return (NULL);
field = p;
while (*p && *p != '\n') p++;
*p = '\0';
pwdadj.pwa_au_never.as_success = 0;
pwdadj.pwa_au_never.as_failure = 0;
if (getauditflagsbin(field, &pwdadj.pwa_au_never) != 0)
return (NULL);
(void)fclose(pwfa);
return (&pwdadj);
} else {
(void)fclose(pwfa);
return (NULL);
}
}
validstr(str, size)
char *str;
int size;
{
char c;
if (str == NULL || strlen(str) > size ||
(size != PWSIZE && index(str, ':')))
return (0);
while (c = *str++) {
if (iscntrl(c))
return (0);
}
return (1);
}
#define DEFSHELL "/bin/sh"
bool_t
validloginshell(pwd, arg)
struct passwd *pwd;
char *arg;
{
static char newshell[STRSIZE];
char *cp, *valid, *getusershell();
setusershell(); /* XXX */
if (pwd->pw_shell == 0 || *pwd->pw_shell == '\0')
pwd->pw_shell = DEFSHELL;
for (valid = getusershell(); valid; valid = getusershell())
if (strcmp(pwd->pw_shell, valid) == 0)
break;
if (valid == NULL) {
(void) syslog(LOG_ERR,
"Cannot change from restricted shell %s\n",
pwd->pw_shell);
return (0);
}
if (arg != 0) {
(void) strncpy(newshell, arg, sizeof newshell - 1);
newshell[sizeof newshell - 1] = 0;
} else {
return (0);
}
/*
* Allow user to give shell name w/o preceding pathname.
*/
setusershell(); /* XXX */
for (valid = getusershell(); valid; valid = getusershell()) {
if (newshell[0] == '/') {
cp = valid;
} else {
cp = rindex(valid, '/');
if (cp == 0)
cp = valid;
else
cp++;
}
if (strcmp(newshell, cp) == 0)
break;
}
if (valid == 0) {
(void) syslog(LOG_WARNING,
"%s is unacceptable as a new shell.\n", newshell);
return (0);
}
if (access(valid, X_OK) < 0) {
(void) syslog(LOG_WARNING, "%s is unavailable.\n", valid);
return (0);
}
pwd->pw_shell = newshell;
return (1);
}
#ifdef EXTRA_PARANOID
/*ARGSUSED*/
int
yp_valid_client(a)
unsigned long a;
{
return (TRUE);
}
#endif
unlimit(lim)
{
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
(void) setrlimit(lim, &rlim);
}
setauditid()
{
int audit_uid; /* default audit uid */
audit_state_t audit_state; /* audit state */
struct passwd *pw; /* password file entry */
struct passwd_adjunct *pwa; /* adjunct file entry */
if ((pw = getpwnam(AUDIT_USER)) == (struct passwd *) NULL ||
(pwa = getpwanam(AUDIT_USER)) == (struct passwd_adjunct *) NULL)
return 1;
else {
audit_uid = pw->pw_uid;
if (getfauditflags(&pwa->pwa_au_always,
&pwa->pwa_au_never, &audit_state) != 0) {
/*
* if we can't tell how to audit from the flags, audit
* everything that's not never for this user.
*/
audit_state.as_success = pwa->pwa_au_never.as_success
^ (-1);
audit_state.as_failure = pwa->pwa_au_never.as_failure
^ (-1);
}
}
(void) setauid(audit_uid);
(void) setaudit(&audit_state);
return 0;
}