* Copyright (c) 1988 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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
/*static char sccsid[] = "from: @(#)yp_passwd.c 1.0 2/2/93";*/
static char rcsid
[] = "$Id: yp_passwd.c,v 1.3 1993/08/01 18:10:17 mycroft Exp $";
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#define passwd yp_passwd_rec
#include <rpcsvc/yppasswd.h>
#define _PASSWORD_LEN PASS_MAX
static char *getnewpasswd();
static struct passwd
*ypgetpwnam();
struct yppasswd yppasswd
;
if (r
= yp_get_default_domain(&domain
)) {
(void)fprintf(stderr
, "%s: can't get local YP domain. Reason: %s\n", progname
, yperr_string(r
));
* Find the host for the passwd map; it should be running
if ((r
= yp_master(domain
, "passwd.byname", &master
)) != 0) {
(void)fprintf(stderr
, "%s: can't find the master YP server. Reason: %s\n", progname
, yperr_string(r
));
* Ask the portmapper for the port of the daemon.
if ((rpcport
= getrpcport(master
, YPPASSWDPROG
, YPPASSWDPROC_UPDATE
, IPPROTO_UDP
)) == 0) {
(void)fprintf(stderr
, "%s: master YP server not running yppasswd daemon.\n\tCan't change password.\n", progname
);
* Be sure the port is priviledged
if (rpcport
>= IPPORT_RESERVED
) {
(void)fprintf(stderr
, "%s: yppasswd daemon running on an invalid port.\n", progname
);
/* Get user's login identity */
if (!(pw
= ypgetpwnam(uname
))) {
(void)fprintf(stderr
, "%s: unknown user %s.\n", progname
, uname
);
if (uid
&& uid
!= pw
->pw_uid
) {
(void)fprintf(stderr
, "%s: you are only allowed to change your own password: %s\n", progname
, strerror(EACCES
));
/* prompt for new password */
yppasswd
.newpw
.pw_passwd
= getnewpasswd(pw
, &yppasswd
.oldpass
);
yppasswd
.newpw
.pw_name
= pw
->pw_name
;
yppasswd
.newpw
.pw_uid
= pw
->pw_uid
;
yppasswd
.newpw
.pw_gid
= pw
->pw_gid
;
yppasswd
.newpw
.pw_gecos
= pw
->pw_gecos
;
yppasswd
.newpw
.pw_dir
= pw
->pw_dir
;
yppasswd
.newpw
.pw_shell
= pw
->pw_shell
;
client
= clnt_create(master
, YPPASSWDPROG
, YPPASSWDVERS
, "udp");
fprintf(stderr
, "can't contact yppasswdd on %s: Reason: %s\n",
master
, yperr_string(YPERR_YPBIND
));
client
->cl_auth
= authunix_create_default();
r
= clnt_call(client
, YPPASSWDPROC_UPDATE
,
xdr_yppasswd
, &yppasswd
, xdr_int
, &status
, tv
);
fprintf(stderr
, "%s: rpc to yppasswdd failed.\n");
printf("Couldn't change YP password.\n");
printf("The YP password has been changed on %s, the master YP passwd server.\n", master
);
getnewpasswd(pw
, old_pass
)
register struct passwd
*pw
;
static char buf
[_PASSWORD_LEN
+1];
char salt
[9], *crypt(), *getpass();
(void)printf("Changing YP password for %s.\n", pw
->pw_name
);
strcmp(crypt(p
= getpass("Old password:"), pw
->pw_passwd
),
strcmp(p
= getpass("Old password:"), pw
->pw_passwd
)) {
for (buf
[0] = '\0', tries
= 0;;) {
p
= getpass("New password:");
(void)printf("Password unchanged.\n");
if (strlen(p
) <= 5 && (uid
!= 0 || ++tries
< 2)) {
(void)printf("Please enter a longer password.\n");
for (t
= p
; *t
&& islower(*t
); ++t
);
if (!*t
&& (uid
!= 0 || ++tries
< 2)) {
(void)printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n");
if (!strcmp(buf
, getpass("Retype new password:")))
(void)printf("Mismatch; try again, EOF to quit.\n");
/* grab a random printable character that isn't a colon */
(void)srandom((int)time((time_t *)NULL
));
salt
[0] = _PASSWORD_EFMT1
;
to64(&salt
[1], (long)(29 * 25), 4);
to64(&salt
[5], random(), 4);
to64(&salt
[0], random(), 2);
return(strdup(crypt(buf
, salt
)));
while (*p
&& *p
!= ':' && *p
!= '\n')
interpret(struct passwd
*pwent
, char *line
)
/* line without colon separators is no good, so ignore it */
pwent
->pw_uid
= (uid_t
)strtoul(p
, NULL
, 10);
pwent
->pw_gid
= (gid_t
)strtoul(p
, NULL
, 10);
static struct passwd pwent
;
reason
= yp_match(domain
, "passwd.byname", nam
, strlen(nam
),
return(interpret(&pwent
, line
));