1 /* $NetBSD: pw_yp.c,v 1.11 1997/07/25 06:37:27 mikel 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 #ifndef lint 36 #if 0 37 static char sccsid[] = "@(#)pw_yp.c 1.0 2/2/93"; 38 #else 39 static char rcsid[] = "$NetBSD: pw_yp.c,v 1.11 1997/07/25 06:37:27 mikel Exp $"; 40 #endif 41 #endif /* not lint */ 42 43 #ifdef YP 44 45 #include <err.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <netdb.h> 50 #include <time.h> 51 #include <pwd.h> 52 #include <errno.h> 53 #include <rpc/rpc.h> 54 #include <rpcsvc/yp_prot.h> 55 #include <rpcsvc/ypclnt.h> 56 #define passwd yp_passwd_rec 57 #include <rpcsvc/yppasswd.h> 58 #undef passwd 59 60 static char *domain; 61 62 /* 63 * Check if rpc.yppasswdd is running on the master YP server. 64 * XXX this duplicates some code, but is much less complex 65 * than the alternative. 66 */ 67 int 68 check_yppasswdd() 69 { 70 char *master; 71 int rpcport; 72 73 /* 74 * Get local domain 75 */ 76 if (!domain && yp_get_default_domain(&domain) != 0) 77 return (1); 78 79 /* 80 * Find the host for the passwd map; it should be running 81 * the daemon. 82 */ 83 master = NULL; 84 if (yp_master(domain, "passwd.byname", &master) != 0) { 85 if (master != NULL) 86 free (master); 87 return (1); 88 } 89 90 /* 91 * Ask the portmapper for the port of the daemon. 92 */ 93 if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, 94 IPPROTO_UDP)) == 0) 95 return (1); 96 97 /* 98 * Successful contact with rpc.yppasswdd. 99 */ 100 return (0); 101 } 102 103 int 104 pw_yp(pw, uid) 105 struct passwd *pw; 106 uid_t uid; 107 { 108 char *master; 109 char *pp; 110 int r, rpcport, status; 111 struct yppasswd yppasswd; 112 struct timeval tv; 113 CLIENT *client; 114 extern char *getpass(); 115 116 /* 117 * Get local domain 118 */ 119 if (!domain && (r = yp_get_default_domain(&domain))) 120 errx(1, "can't get local YP domain. Reason: %s", 121 yperr_string(r)); 122 123 /* 124 * Find the host for the passwd map; it should be running 125 * the daemon. 126 */ 127 master = NULL; 128 if ((r = yp_master(domain, "passwd.byname", &master)) != 0) { 129 if (master) 130 free (master); 131 warnx("can't find the master YP server. Reason: %s", 132 yperr_string(r)); 133 return (1); 134 } 135 136 /* 137 * Ask the portmapper for the port of the daemon. 138 */ 139 if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, 140 IPPROTO_UDP)) == 0) { 141 warnx("master YP server not running yppasswd daemon.\n\t%s\n", 142 "Can't change password."); 143 return (1); 144 } 145 146 /* 147 * Be sure the port is priviledged 148 */ 149 if (rpcport >= IPPORT_RESERVED) { 150 warnx("yppasswd daemon is on an invalid port."); 151 return (1); 152 } 153 154 /* prompt for old password */ 155 bzero(&yppasswd, sizeof yppasswd); 156 yppasswd.oldpass = "none"; 157 yppasswd.oldpass = getpass("Old password:"); 158 if (!yppasswd.oldpass) { 159 warnx("Cancelled."); 160 return (1); 161 } 162 163 /* tell rpc.yppasswdd */ 164 yppasswd.newpw.pw_name = pw->pw_name; 165 yppasswd.newpw.pw_passwd= pw->pw_passwd; 166 yppasswd.newpw.pw_uid = pw->pw_uid; 167 yppasswd.newpw.pw_gid = pw->pw_gid; 168 yppasswd.newpw.pw_gecos = pw->pw_gecos; 169 yppasswd.newpw.pw_dir = pw->pw_dir; 170 yppasswd.newpw.pw_shell = pw->pw_shell; 171 172 client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); 173 if (client==NULL) { 174 warnx("cannot contact yppasswdd on %s: Reason: %s", 175 master, yperr_string(YPERR_YPBIND)); 176 return (1); 177 } 178 client->cl_auth = authunix_create_default(); 179 tv.tv_sec = 5; 180 tv.tv_usec = 0; 181 r = clnt_call(client, YPPASSWDPROC_UPDATE, 182 xdr_yppasswd, &yppasswd, xdr_int, &status, tv); 183 if (r) { 184 warnx("rpc to yppasswdd failed."); 185 return (1); 186 } else if (status) 187 printf("Couldn't change YP password.\n"); 188 else 189 printf("%s %s, %s\n", 190 "The YP password information has been changed on", 191 master, "the master YP passwd server."); 192 return (0); 193 } 194 195 static char * 196 pwskip(p) 197 char *p; 198 { 199 while (*p && *p != ':' && *p != '\n') 200 ++p; 201 if (*p) 202 *p++ = 0; 203 return (p); 204 } 205 206 static struct passwd * 207 interpret(pwent, line) 208 struct passwd *pwent; 209 char *line; 210 { 211 char *p = line; 212 int c; 213 214 pwent->pw_passwd = "*"; 215 pwent->pw_uid = 0; 216 pwent->pw_gid = 0; 217 pwent->pw_gecos = ""; 218 pwent->pw_dir = ""; 219 pwent->pw_shell = ""; 220 pwent->pw_change = 0; 221 pwent->pw_expire = 0; 222 pwent->pw_class = ""; 223 224 /* line without colon separators is no good, so ignore it */ 225 if(!strchr(p,':')) 226 return(NULL); 227 228 pwent->pw_name = p; 229 p = pwskip(p); 230 pwent->pw_passwd = p; 231 p = pwskip(p); 232 pwent->pw_uid = (uid_t)strtoul(p, NULL, 10); 233 p = pwskip(p); 234 pwent->pw_gid = (gid_t)strtoul(p, NULL, 10); 235 p = pwskip(p); 236 pwent->pw_gecos = p; 237 p = pwskip(p); 238 pwent->pw_dir = p; 239 p = pwskip(p); 240 pwent->pw_shell = p; 241 while (*p && *p != '\n') 242 p++; 243 *p = '\0'; 244 return (pwent); 245 } 246 247 struct passwd * 248 ypgetpwnam(nam) 249 char *nam; 250 { 251 static struct passwd pwent; 252 static char line[1024]; 253 char *val; 254 int reason, vallen; 255 256 /* 257 * Get local domain 258 */ 259 if (!domain && (reason = yp_get_default_domain(&domain))) 260 errx(1, "can't get local YP domain. Reason: %s", 261 yperr_string(reason)); 262 263 val = NULL; 264 reason = yp_match(domain, "passwd.byname", nam, strlen(nam), 265 &val, &vallen); 266 if (reason != 0) { 267 if (val) 268 free (val); 269 return (NULL); 270 } 271 val[vallen] = '\0'; 272 (void)strncpy(line, val, sizeof(line) - 1); 273 free(val); 274 275 return(interpret(&pwent, line)); 276 } 277 278 struct passwd * 279 ypgetpwuid(uid) 280 uid_t uid; 281 { 282 static struct passwd pwent; 283 static char line[1024]; 284 char *val; 285 int reason, vallen; 286 char namebuf[16]; 287 288 if (!domain && (reason = yp_get_default_domain(&domain))) 289 errx(1, "can't get local YP domain. Reason: %s\n", 290 yperr_string(reason)); 291 292 (void)snprintf(namebuf, sizeof namebuf, "%d", uid); 293 val = NULL; 294 reason = yp_match(domain, "passwd.byuid", namebuf, strlen(namebuf), 295 &val, &vallen); 296 if (reason != 0) { 297 if (val) 298 free (val); 299 return (NULL); 300 } 301 val[vallen] = '\0'; 302 (void)strncpy(line, val, sizeof(line) - 1); 303 free(val); 304 305 return(interpret(&pwent, line)); 306 } 307 308 void 309 yppw_error(name, err, eval) 310 const char *name; 311 int err, eval; 312 { 313 314 if (err) 315 warn(name); 316 317 errx(eval, "YP passwd information unchanged"); 318 } 319 320 void 321 yppw_prompt() 322 { 323 int c; 324 325 (void)printf("re-edit the password file? [y]: "); 326 (void)fflush(stdout); 327 c = getchar(); 328 if (c != EOF && c != '\n') 329 while (getchar() != '\n'); 330 if (c == 'n') 331 yppw_error(NULL, 0, 0); 332 } 333 #endif /* YP */ 334