1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights 7 * Reserved. This file contains Original Code and/or Modifications of 8 * Original Code as defined in and that are subject to the Apple Public 9 * Source License Version 1.0 (the 'License'). You may not use this file 10 * except in compliance with the License. Please obtain a copy of the 11 * License at http://www.apple.com/publicsource and read it before using 12 * this file. 13 * 14 * The Original Code and all software distributed under the License are 15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 19 * License for the specific language governing rights and limitations 20 * under the License." 21 * 22 * @APPLE_LICENSE_HEADER_END@ 23 */ 24/* 25 * Portions Copyright (c) 1998 by Apple Computer, Inc. 26 * Portions Copyright (c) 1988 by Sun Microsystems, Inc. 27 * Portions Copyright (c) 1988 The Regents of the University of California. 28 * All rights reserved. 29 * 30 * Redistribution and use in source and binary forms, with or without 31 * modification, are permitted provided that the following conditions 32 * are met: 33 * 1. Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * 2. Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in the 37 * documentation and/or other materials provided with the distribution. 38 * 3. All advertising materials mentioning features or use of this software 39 * must display the following acknowledgement: 40 * This product includes software developed by the University of 41 * California, Berkeley and its contributors. 42 * 4. Neither the name of the University nor the names of its contributors 43 * may be used to endorse or promote products derived from this software 44 * without specific prior written permission. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 56 * SUCH DAMAGE. 57 */ 58 59#include "passwd.h" 60 61#ifdef INFO_NIS 62 63/* update a user's password in NIS. This was based on the Sun implementation 64 * we used in NEXTSTEP, although I've added some stuff from OpenBSD. And 65 * it uses the API to support Rhapsody's proprietry infosystem switch. 66 * lukeh 67 */ 68 69#include <stdio.h> 70#include <stdlib.h> 71#include <unistd.h> 72#include <string.h> 73#include <pwd.h> 74#include <netinet/in.h> 75#include <rpc/types.h> 76#include <rpc/xdr.h> 77#include <rpc/rpc.h> 78#include <rpcsvc/yp_prot.h> 79#include <rpcsvc/ypclnt.h> 80#include <rpcsvc/yppasswd.h> 81#include <netdb.h> 82#include <sys/socket.h> 83#include <sys/file.h> 84#include <errno.h> 85 86extern int getrpcport(char *, int, int, int); 87extern void getpasswd(char *, int, int, int, int, char *, char **, char**, char **); 88 89static struct passwd *ypgetpwnam(char *name, char *domain); 90static struct passwd *interpret(struct passwd *pwent, char *line); 91 92int nis_passwd(char *uname, char *domain) 93{ 94 int ans, port, ok = -1; 95 char *master; 96 char *ne; /* new encrypted password */ 97 char *oc; /* old cleartext password */ 98 char *nc; /* new cleartext password */ 99 static struct yppasswd yppasswd; 100 struct passwd *pwd; 101 int uid; 102 struct timeval tv; 103 CLIENT *cl; 104 105 if (domain == NULL) 106 { 107 if (yp_get_default_domain(&domain) != 0) 108 { 109 (void)fprintf(stderr, "can't get domain\n"); 110 exit(1); 111 } 112 } 113 114 if (yp_master(domain, "passwd.byname", &master) != 0) 115 { 116 (void)fprintf(stderr, "can't get master for passwd file\n"); 117 exit(1); 118 } 119 120 port = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, 121 IPPROTO_UDP); 122 if (port == 0) 123 { 124 (void)fprintf(stderr, "%s is not running yppasswd daemon\n", 125 master); 126 exit(1); 127 } 128 if (port >= IPPORT_RESERVED) 129 { 130 (void)fprintf(stderr, 131 "yppasswd daemon is not running on privileged port\n"); 132 exit(1); 133 } 134 135 pwd = ypgetpwnam(uname, domain); 136 if (pwd == NULL) 137 { 138 (void)fprintf(stderr, "user %s not found\n", uname); 139 exit(1); 140 } 141 142 uid = getuid(); 143 if (uid != 0 && uid != pwd->pw_uid) 144 { 145 (void)fprintf(stderr, "you may only change your own password\n"); 146 exit(1); 147 } 148 149 getpasswd(uname, 0, 5, 0, 0, pwd->pw_passwd, &ne, &oc, &nc); 150 151 yppasswd.oldpass = oc; 152 yppasswd.newpw.pw_name = pwd->pw_name; 153 yppasswd.newpw.pw_passwd = ne; 154 yppasswd.newpw.pw_uid = pwd->pw_uid; 155 yppasswd.newpw.pw_gid = pwd->pw_gid; 156 yppasswd.newpw.pw_gecos = pwd->pw_gecos; 157 yppasswd.newpw.pw_dir = pwd->pw_dir; 158 yppasswd.newpw.pw_shell = pwd->pw_shell; 159 160 cl = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); 161 if (cl == NULL) 162 { 163 (void)fprintf(stderr, "could not contact yppasswdd on %s\n", master); 164 exit(1); 165 } 166 cl->cl_auth = authunix_create_default(); 167 tv.tv_sec = 2; 168 tv.tv_usec = 0; 169 ans = clnt_call(cl, YPPASSWDPROC_UPDATE, 170 (xdrproc_t)xdr_yppasswd, &yppasswd, (xdrproc_t)xdr_int, &ok, tv); 171 172 if (ans != 0) 173 { 174 clnt_perrno(ans); 175 (void)fprintf(stderr, "\n"); 176 (void)fprintf(stderr, "couldn't change passwd\n"); 177 exit(1); 178 } 179 if (ok != 0) 180 { 181 (void)fprintf(stderr, "couldn't change passwd\n"); 182 exit(1); 183 } 184 return(0); 185} 186 187static char * 188pwskip(register char *p) 189{ 190 while (*p && *p != ':' && *p != '\n') 191 ++p; 192 if (*p) 193 *p++ = 0; 194 return (p); 195} 196 197static struct passwd * 198interpret(struct passwd *pwent, char *line) 199{ 200 register char *p = line; 201 202 pwent->pw_passwd = "*"; 203 pwent->pw_uid = 0; 204 pwent->pw_gid = 0; 205 pwent->pw_gecos = ""; 206 pwent->pw_dir = ""; 207 pwent->pw_shell = ""; 208#ifndef __SLICK__ 209 pwent->pw_change = 0; 210 pwent->pw_expire = 0; 211 pwent->pw_class = ""; 212#endif 213 214 /* line without colon separators is no good, so ignore it */ 215 if(!strchr(p, ':')) 216 return(NULL); 217 218 pwent->pw_name = p; 219 p = pwskip(p); 220 pwent->pw_passwd = p; 221 p = pwskip(p); 222 pwent->pw_uid = (uid_t)strtoul(p, NULL, 10); 223 p = pwskip(p); 224 pwent->pw_gid = (gid_t)strtoul(p, NULL, 10); 225 p = pwskip(p); 226 pwent->pw_gecos = p; 227 p = pwskip(p); 228 pwent->pw_dir = p; 229 p = pwskip(p); 230 pwent->pw_shell = p; 231 while (*p && *p != '\n') 232 p++; 233 *p = '\0'; 234 return (pwent); 235} 236 237 238static struct passwd * 239ypgetpwnam(char *nam, char *domain) 240{ 241 static struct passwd pwent; 242 char *val; 243 int reason, vallen; 244 static char *__yplin = NULL; 245 246 reason = yp_match(domain, "passwd.byname", nam, (int)strlen(nam), 247 &val, &vallen); 248 switch(reason) { 249 case 0: 250 break; 251 default: 252 return (NULL); 253 break; 254 } 255 val[vallen] = '\0'; 256 if (__yplin) 257 free(__yplin); 258 __yplin = (char *)malloc(vallen + 1); 259 strcpy(__yplin, val); 260 free(val); 261 262 return(interpret(&pwent, __yplin)); 263} 264 265#endif /* INFO_NIS */ 266