1 /* $NetBSD: pw_yp.c,v 1.10 1997/05/21 02:20:15 lukem 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.10 1997/05/21 02:20:15 lukem Exp $"; 40 #endif 41 #endif /* not lint */ 42 43 #ifdef YP 44 45 #include <stdio.h> 46 #include <string.h> 47 #include <netdb.h> 48 #include <time.h> 49 #include <pwd.h> 50 #include <errno.h> 51 #include <rpc/rpc.h> 52 #include <rpcsvc/yp_prot.h> 53 #include <rpcsvc/ypclnt.h> 54 #define passwd yp_passwd_rec 55 #include <rpcsvc/yppasswd.h> 56 #undef passwd 57 58 static char *domain; 59 60 /* 61 * Check if rpc.yppasswdd is running on the master YP server. 62 * XXX this duplicates some code, but is much less complex 63 * than the alternative. 64 */ 65 int 66 check_yppasswdd() 67 { 68 char *master; 69 int rpcport; 70 71 /* 72 * Get local domain 73 */ 74 if (!domain && yp_get_default_domain(&domain) != 0) 75 return (1); 76 77 /* 78 * Find the host for the passwd map; it should be running 79 * the daemon. 80 */ 81 master = NULL; 82 if (yp_master(domain, "passwd.byname", &master) != 0) { 83 if (master != NULL) 84 free (master); 85 return (1); 86 } 87 88 /* 89 * Ask the portmapper for the port of the daemon. 90 */ 91 if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, 92 IPPROTO_UDP)) == 0) 93 return (1); 94 95 /* 96 * Successful contact with rpc.yppasswdd. 97 */ 98 return (0); 99 } 100 101 pw_yp(pw, uid) 102 struct passwd *pw; 103 uid_t uid; 104 { 105 char *master; 106 char *pp; 107 int r, rpcport, status; 108 struct yppasswd yppasswd; 109 struct timeval tv; 110 CLIENT *client; 111 extern char *getpass(); 112 113 /* 114 * Get local domain 115 */ 116 if (!domain && (r = yp_get_default_domain(&domain))) 117 errx(1, "can't get local YP domain. Reason: %s", 118 yperr_string(r)); 119 120 /* 121 * Find the host for the passwd map; it should be running 122 * the daemon. 123 */ 124 master = NULL; 125 if ((r = yp_master(domain, "passwd.byname", &master)) != 0) { 126 if (master) 127 free (master); 128 warnx("can't find the master YP server. Reason: %s", 129 yperr_string(r)); 130 return (1); 131 } 132 133 /* 134 * Ask the portmapper for the port of the daemon. 135 */ 136 if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, 137 IPPROTO_UDP)) == 0) { 138 warnx("master YP server not running yppasswd daemon.\n\t%s\n", 139 "Can't change password."); 140 return (1); 141 } 142 143 /* 144 * Be sure the port is priviledged 145 */ 146 if (rpcport >= IPPORT_RESERVED) { 147 warnx("yppasswd daemon is on an invalid port."); 148 return (1); 149 } 150 151 /* prompt for old password */ 152 bzero(&yppasswd, sizeof yppasswd); 153 yppasswd.oldpass = "none"; 154 yppasswd.oldpass = getpass("Old password:"); 155 if (!yppasswd.oldpass) { 156 warnx("Cancelled."); 157 return (1); 158 } 159 160 /* tell rpc.yppasswdd */ 161 yppasswd.newpw.pw_name = pw->pw_name; 162 yppasswd.newpw.pw_passwd= pw->pw_passwd; 163 yppasswd.newpw.pw_uid = pw->pw_uid; 164 yppasswd.newpw.pw_gid = pw->pw_gid; 165 yppasswd.newpw.pw_gecos = pw->pw_gecos; 166 yppasswd.newpw.pw_dir = pw->pw_dir; 167 yppasswd.newpw.pw_shell = pw->pw_shell; 168 169 client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); 170 if (client==NULL) { 171 warnx("cannot contact yppasswdd on %s: Reason: %s", 172 master, yperr_string(YPERR_YPBIND)); 173 return (1); 174 } 175 client->cl_auth = authunix_create_default(); 176 tv.tv_sec = 5; 177 tv.tv_usec = 0; 178 r = clnt_call(client, YPPASSWDPROC_UPDATE, 179 xdr_yppasswd, &yppasswd, xdr_int, &status, tv); 180 if (r) { 181 warnx("rpc to yppasswdd failed."); 182 return (1); 183 } else if (status) 184 printf("Couldn't change YP password.\n"); 185 else 186 printf("%s %s, %s\n", 187 "The YP password information has been changed on", 188 master, "the master YP passwd server."); 189 return (0); 190 } 191 192 static char * 193 pwskip(p) 194 char *p; 195 { 196 while (*p && *p != ':' && *p != '\n') 197 ++p; 198 if (*p) 199 *p++ = 0; 200 return (p); 201 } 202 203 static struct passwd * 204 interpret(pwent, line) 205 struct passwd *pwent; 206 char *line; 207 { 208 char *p = line; 209 int c; 210 211 pwent->pw_passwd = "*"; 212 pwent->pw_uid = 0; 213 pwent->pw_gid = 0; 214 pwent->pw_gecos = ""; 215 pwent->pw_dir = ""; 216 pwent->pw_shell = ""; 217 pwent->pw_change = 0; 218 pwent->pw_expire = 0; 219 pwent->pw_class = ""; 220 221 /* line without colon separators is no good, so ignore it */ 222 if(!strchr(p,':')) 223 return(NULL); 224 225 pwent->pw_name = p; 226 p = pwskip(p); 227 pwent->pw_passwd = p; 228 p = pwskip(p); 229 pwent->pw_uid = (uid_t)strtoul(p, NULL, 10); 230 p = pwskip(p); 231 pwent->pw_gid = (gid_t)strtoul(p, NULL, 10); 232 p = pwskip(p); 233 pwent->pw_gecos = p; 234 p = pwskip(p); 235 pwent->pw_dir = p; 236 p = pwskip(p); 237 pwent->pw_shell = p; 238 while (*p && *p != '\n') 239 p++; 240 *p = '\0'; 241 return (pwent); 242 } 243 244 struct passwd * 245 ypgetpwnam(nam) 246 char *nam; 247 { 248 static struct passwd pwent; 249 static char line[1024]; 250 char *val; 251 int reason, vallen; 252 253 /* 254 * Get local domain 255 */ 256 if (!domain && (reason = yp_get_default_domain(&domain))) 257 errx(1, "can't get local YP domain. Reason: %s", 258 yperr_string(reason)); 259 260 val = NULL; 261 reason = yp_match(domain, "passwd.byname", nam, strlen(nam), 262 &val, &vallen); 263 if (reason != 0) { 264 if (val) 265 free (val); 266 return (NULL); 267 } 268 val[vallen] = '\0'; 269 (void)strncpy(line, val, sizeof(line) - 1); 270 free(val); 271 272 return(interpret(&pwent, line)); 273 } 274 275 struct passwd * 276 ypgetpwuid(uid) 277 uid_t uid; 278 { 279 static struct passwd pwent; 280 static char line[1024]; 281 char *val; 282 int reason, vallen; 283 char namebuf[16]; 284 285 if (!domain && (reason = yp_get_default_domain(&domain))) 286 errx(1, "can't get local YP domain. Reason: %s\n", 287 yperr_string(reason)); 288 289 (void)snprintf(namebuf, sizeof namebuf, "%d", uid); 290 val = NULL; 291 reason = yp_match(domain, "passwd.byuid", namebuf, strlen(namebuf), 292 &val, &vallen); 293 if (reason != 0) { 294 if (val) 295 free (val); 296 return (NULL); 297 } 298 val[vallen] = '\0'; 299 (void)strncpy(line, val, sizeof(line) - 1); 300 free(val); 301 302 return(interpret(&pwent, line)); 303 } 304 305 void 306 yppw_error(name, err, eval) 307 const char *name; 308 int err, eval; 309 { 310 311 if (err) 312 warn(name); 313 314 errx(eval, "YP passwd information unchanged"); 315 } 316 317 void 318 yppw_prompt() 319 { 320 int c; 321 322 (void)printf("re-edit the password file? [y]: "); 323 (void)fflush(stdout); 324 c = getchar(); 325 if (c != EOF && c != '\n') 326 while (getchar() != '\n'); 327 if (c == 'n') 328 yppw_error(NULL, 0, 0); 329 } 330 #endif /* YP */ 331