1 /* $NetBSD: pw_yp.c,v 1.21 2005/02/17 17:09:48 xtraeme Exp $ */ 2 3 /* 4 * Copyright (c) 1988 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 #include <sys/cdefs.h> 32 #ifndef lint 33 #if 0 34 static char sccsid[] = "@(#)pw_yp.c 1.0 2/2/93"; 35 #else 36 __RCSID("$NetBSD: pw_yp.c,v 1.21 2005/02/17 17:09:48 xtraeme Exp $"); 37 #endif 38 #endif /* not lint */ 39 40 #ifdef YP 41 42 #include <err.h> 43 #include <errno.h> 44 #include <netdb.h> 45 #include <pwd.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <time.h> 50 #include <unistd.h> 51 52 #include <rpc/rpc.h> 53 #include <rpcsvc/yp_prot.h> 54 #include <rpcsvc/ypclnt.h> 55 56 #define passwd yp_passwd_rec 57 #include <rpcsvc/yppasswd.h> 58 #undef passwd 59 60 #include "chpass.h" 61 62 static char *domain; 63 64 /* 65 * Check if rpc.yppasswdd is running on the master YP server. 66 * XXX this duplicates some code, but is much less complex 67 * than the alternative. 68 */ 69 int 70 check_yppasswdd(void) 71 { 72 char *master; 73 int rpcport; 74 75 /* 76 * Get local domain 77 */ 78 if (!domain && yp_get_default_domain(&domain) != 0) 79 return (1); 80 81 /* 82 * Find the host for the passwd map; it should be running 83 * the daemon. 84 */ 85 master = NULL; 86 if (yp_master(domain, "passwd.byname", &master) != 0) { 87 if (master != NULL) 88 free (master); 89 return (1); 90 } 91 92 /* 93 * Ask the portmapper for the port of the daemon. 94 */ 95 if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, 96 IPPROTO_UDP)) == 0) 97 return (1); 98 99 /* 100 * Successful contact with rpc.yppasswdd. 101 */ 102 return (0); 103 } 104 105 int 106 pw_yp(struct passwd *pw, uid_t uid) 107 { 108 char *master; 109 int r, rpcport, status; 110 struct yppasswd yppasswd; 111 struct timeval tv; 112 CLIENT *client; 113 114 /* 115 * Get local domain 116 */ 117 if (!domain && (r = yp_get_default_domain(&domain))) 118 errx(1, "can't get local YP domain. Reason: %s", 119 yperr_string(r)); 120 121 /* 122 * Find the host for the passwd map; it should be running 123 * the daemon. 124 */ 125 master = NULL; 126 if ((r = yp_master(domain, "passwd.byname", &master)) != 0) { 127 if (master) 128 free (master); 129 warnx("can't find the master YP server. Reason: %s", 130 yperr_string(r)); 131 return (1); 132 } 133 134 /* 135 * Ask the portmapper for the port of the daemon. 136 */ 137 if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, 138 IPPROTO_UDP)) == 0) { 139 warnx("master YP server not running yppasswd daemon.\n\t%s\n", 140 "Can't change password."); 141 return (1); 142 } 143 144 /* 145 * Be sure the port is privileged 146 */ 147 if (rpcport >= IPPORT_RESERVED) { 148 warnx("yppasswd daemon is on an invalid port."); 149 return (1); 150 } 151 152 /* prompt for old password */ 153 memset(&yppasswd, 0, sizeof yppasswd); 154 yppasswd.oldpass = "none"; 155 yppasswd.oldpass = getpass("Old password:"); 156 if (!yppasswd.oldpass) { 157 warnx("Cancelled."); 158 return (1); 159 } 160 161 /* tell rpc.yppasswdd */ 162 yppasswd.newpw.pw_name = strdup(pw->pw_name); 163 if (!yppasswd.newpw.pw_name) { 164 err(1, "strdup"); 165 /*NOTREACHED*/ 166 } 167 yppasswd.newpw.pw_passwd = strdup(pw->pw_passwd); 168 if (!yppasswd.newpw.pw_passwd) { 169 err(1, "strdup"); 170 /*NOTREACHED*/ 171 } 172 yppasswd.newpw.pw_uid = pw->pw_uid; 173 yppasswd.newpw.pw_gid = pw->pw_gid; 174 yppasswd.newpw.pw_gecos = strdup(pw->pw_gecos); 175 if (!yppasswd.newpw.pw_gecos) { 176 err(1, "strdup"); 177 /*NOTREACHED*/ 178 } 179 yppasswd.newpw.pw_dir = strdup(pw->pw_dir); 180 if (!yppasswd.newpw.pw_dir) { 181 err(1, "strdup"); 182 /*NOTREACHED*/ 183 } 184 yppasswd.newpw.pw_shell = strdup(pw->pw_shell); 185 if (!yppasswd.newpw.pw_shell) { 186 err(1, "strdup"); 187 /*NOTREACHED*/ 188 } 189 190 client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); 191 if (client == NULL) { 192 warnx("cannot contact yppasswdd on %s: Reason: %s", 193 master, yperr_string(YPERR_YPBIND)); 194 return (1); 195 } 196 client->cl_auth = authunix_create_default(); 197 tv.tv_sec = 5; 198 tv.tv_usec = 0; 199 r = clnt_call(client, YPPASSWDPROC_UPDATE, 200 xdr_yppasswd, &yppasswd, xdr_int, &status, tv); 201 if (r) { 202 warnx("rpc to yppasswdd failed."); 203 return (1); 204 } else if (status) 205 printf("Couldn't change YP password.\n"); 206 else 207 printf("%s %s, %s\n", 208 "The YP password information has been changed on", 209 master, "the master YP passwd server."); 210 return (0); 211 } 212 213 void 214 yppw_error(const char *name, int err, int eval) 215 { 216 217 if (err) { 218 if (name) 219 warn("%s", name); 220 else 221 warn(NULL); 222 } 223 224 errx(eval, "YP passwd information unchanged"); 225 } 226 227 void 228 yppw_prompt(void) 229 { 230 int c; 231 232 (void)printf("re-edit the password file? [y]: "); 233 (void)fflush(stdout); 234 c = getchar(); 235 if (c != EOF && c != '\n') 236 while (getchar() != '\n'); 237 if (c == 'n') 238 yppw_error(NULL, 0, 0); 239 } 240 #endif /* YP */ 241