#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>
#include <netinet/in.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/rpc.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#include <rpcsvc/yppasswd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <errno.h>
extern int getrpcport(char *, int, int, int);
extern void getpasswd(char *, int, int, int, int, char *, char **, char**, char **);
static struct passwd *ypgetpwnam(char *name, char *domain);
int nis_passwd(char *uname, char *domain)
{
int ans, port, ok = -1;
char *master;
char *ne;
char *oc;
char *nc;
static struct yppasswd yppasswd;
struct passwd *pwd;
int uid;
struct timeval tv;
CLIENT *cl;
if (domain == NULL)
{
if (yp_get_default_domain(&domain) != 0)
{
(void)fprintf(stderr, "can't get domain\n");
exit(1);
}
}
if (yp_master(domain, "passwd.byname", &master) != 0)
{
(void)fprintf(stderr, "can't get master for passwd file\n");
exit(1);
}
port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE,
IPPROTO_UDP);
if (port == 0)
{
(void)fprintf(stderr, "%s is not running yppasswd daemon\n",
master);
exit(1);
}
if (port >= IPPORT_RESERVED)
{
(void)fprintf(stderr,
"yppasswd daemon is not running on privileged port\n");
exit(1);
}
pwd = ypgetpwnam(uname, domain);
if (pwd == NULL)
{
(void)fprintf(stderr, "user %s not found\n", uname);
exit(1);
}
uid = getuid();
if (uid != 0 && uid != pwd->pw_uid)
{
(void)fprintf(stderr, "you may only change your own password\n");
exit(1);
}
getpasswd(uname, 0, 5, 0, 0, pwd->pw_passwd, &ne, &oc, &nc);
yppasswd.oldpass = oc;
yppasswd.newpw.pw_name = pwd->pw_name;
yppasswd.newpw.pw_passwd = ne;
yppasswd.newpw.pw_uid = pwd->pw_uid;
yppasswd.newpw.pw_gid = pwd->pw_gid;
yppasswd.newpw.pw_gecos = pwd->pw_gecos;
yppasswd.newpw.pw_dir = pwd->pw_dir;
yppasswd.newpw.pw_shell = pwd->pw_shell;
cl = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
if (cl == NULL)
{
(void)fprintf(stderr, "could not contact yppasswdd on %s\n", master);
exit(1);
}
cl->cl_auth = authunix_create_default();
tv.tv_sec = 2;
tv.tv_usec = 0;
ans = clnt_call(cl, YPPASSWDPROC_UPDATE,
(xdrproc_t)xdr_yppasswd, &yppasswd, (xdrproc_t)xdr_int, &ok, tv);
if (ans != 0)
{
clnt_perrno(ans);
(void)fprintf(stderr, "\n");
(void)fprintf(stderr, "couldn't change passwd\n");
exit(1);
}
if (ok != 0)
{
(void)fprintf(stderr, "couldn't change passwd\n");
exit(1);
}
return(0);
}
static char *
pwskip(register char *p)
{
while (*p && *p != ':' && *p != '\n')
++p;
if (*p)
*p++ = 0;
return (p);
}
struct passwd *
interpret(struct passwd *pwent, char *line)
{
register char *p = line;
pwent->pw_passwd = "*";
pwent->pw_uid = 0;
pwent->pw_gid = 0;
pwent->pw_gecos = "";
pwent->pw_dir = "";
pwent->pw_shell = "";
#ifndef __SLICK__
pwent->pw_change = 0;
pwent->pw_expire = 0;
pwent->pw_class = "";
#endif
if(!strchr(p, ':'))
return(NULL);
pwent->pw_name = p;
p = pwskip(p);
pwent->pw_passwd = p;
p = pwskip(p);
pwent->pw_uid = (uid_t)strtoul(p, NULL, 10);
p = pwskip(p);
pwent->pw_gid = (gid_t)strtoul(p, NULL, 10);
p = pwskip(p);
pwent->pw_gecos = p;
p = pwskip(p);
pwent->pw_dir = p;
p = pwskip(p);
pwent->pw_shell = p;
while (*p && *p != '\n')
p++;
*p = '\0';
return (pwent);
}
static struct passwd *
ypgetpwnam(char *nam, char *domain)
{
static struct passwd pwent;
char *val;
int reason, vallen;
static char *__yplin = NULL;
reason = yp_match(domain, "passwd.byname", nam, strlen(nam),
&val, &vallen);
switch(reason) {
case 0:
break;
default:
return (NULL);
break;
}
val[vallen] = '\0';
if (__yplin)
free(__yplin);
__yplin = (char *)malloc(vallen + 1);
strcpy(__yplin, val);
free(val);
return(interpret(&pwent, __yplin));
}