1 /* $NetBSD: field.c,v 1.8 2002/05/09 01:58:39 simonb Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1993, 1994 5 * The Regents of the University of California. 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 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "@(#)field.c 8.4 (Berkeley) 4/2/94"; 40 #else 41 __RCSID("$NetBSD: field.c,v 1.8 2002/05/09 01:58:39 simonb Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include <sys/param.h> 46 47 #include <ctype.h> 48 #include <err.h> 49 #include <errno.h> 50 #include <grp.h> 51 #include <pwd.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <unistd.h> 56 57 #include "chpass.h" 58 #include "pathnames.h" 59 60 /* ARGSUSED */ 61 int 62 p_login(p, pw, ep) 63 const char *p; 64 struct passwd *pw; 65 ENTRY *ep; 66 { 67 68 if (!*p) { 69 warnx("empty login field"); 70 return (1); 71 } 72 if (*p == '-') { 73 warnx("login names may not begin with a hyphen"); 74 return (1); 75 } 76 if (!(pw->pw_name = strdup(p))) { 77 warnx("can't save entry"); 78 return (1); 79 } 80 if (strchr(p, '.')) 81 warnx("\'.\' is dangerous in a login name"); 82 for (; *p; ++p) 83 if (isupper(*p)) { 84 warnx("upper-case letters are dangerous in a login name"); 85 break; 86 } 87 return (0); 88 } 89 90 /* ARGSUSED */ 91 int 92 p_passwd(p, pw, ep) 93 const char *p; 94 struct passwd *pw; 95 ENTRY *ep; 96 { 97 98 if (!*p) 99 pw->pw_passwd = ""; /* "NOLOGIN"; */ 100 else if (!(pw->pw_passwd = strdup(p))) { 101 warnx("can't save password entry"); 102 return (1); 103 } 104 105 return (0); 106 } 107 108 /* ARGSUSED */ 109 int 110 p_uid(p, pw, ep) 111 const char *p; 112 struct passwd *pw; 113 ENTRY *ep; 114 { 115 unsigned long id; 116 char *np; 117 118 if (!*p) { 119 warnx("empty uid field"); 120 return (1); 121 } 122 if (!isdigit(*p)) { 123 warnx("illegal uid"); 124 return (1); 125 } 126 errno = 0; 127 id = strtoul(p, &np, 10); 128 /* 129 * We don't need to check the return value of strtoul() 130 * since ULONG_MAX is greater than UID_MAX. 131 */ 132 if (*np || id > UID_MAX) { 133 warnx("illegal uid"); 134 return (1); 135 } 136 pw->pw_uid = (uid_t)id; 137 return (0); 138 } 139 140 /* ARGSUSED */ 141 int 142 p_gid(p, pw, ep) 143 const char *p; 144 struct passwd *pw; 145 ENTRY *ep; 146 { 147 struct group *gr; 148 unsigned long id; 149 char *np; 150 151 if (!*p) { 152 warnx("empty gid field"); 153 return (1); 154 } 155 if (!isdigit(*p)) { 156 if (!(gr = getgrnam(p))) { 157 warnx("unknown group %s", p); 158 return (1); 159 } 160 pw->pw_gid = gr->gr_gid; 161 return (0); 162 } 163 errno = 0; 164 id = strtoul(p, &np, 10); 165 /* 166 * We don't need to check the return value of strtoul() 167 * since ULONG_MAX is greater than GID_MAX. 168 */ 169 if (*np || id > GID_MAX) { 170 warnx("illegal gid"); 171 return (1); 172 } 173 pw->pw_gid = (gid_t)id; 174 return (0); 175 } 176 177 /* ARGSUSED */ 178 int 179 p_class(p, pw, ep) 180 const char *p; 181 struct passwd *pw; 182 ENTRY *ep; 183 { 184 185 if (!*p) 186 pw->pw_class = ""; 187 else if (!(pw->pw_class = strdup(p))) { 188 warnx("can't save entry"); 189 return (1); 190 } 191 192 return (0); 193 } 194 195 /* ARGSUSED */ 196 int 197 p_change(p, pw, ep) 198 const char *p; 199 struct passwd *pw; 200 ENTRY *ep; 201 { 202 203 if (!atot(p, &pw->pw_change)) 204 return (0); 205 warnx("illegal date for change field"); 206 return (1); 207 } 208 209 /* ARGSUSED */ 210 int 211 p_expire(p, pw, ep) 212 const char *p; 213 struct passwd *pw; 214 ENTRY *ep; 215 { 216 217 if (!atot(p, &pw->pw_expire)) 218 return (0); 219 warnx("illegal date for expire field"); 220 return (1); 221 } 222 223 /* ARGSUSED */ 224 int 225 p_gecos(p, pw, ep) 226 const char *p; 227 struct passwd *pw; 228 ENTRY *ep; 229 { 230 231 if (!(ep->save = strdup(p))) { 232 warnx("can't save entry"); 233 return (1); 234 } 235 return (0); 236 } 237 238 /* ARGSUSED */ 239 int 240 p_hdir(p, pw, ep) 241 const char *p; 242 struct passwd *pw; 243 ENTRY *ep; 244 { 245 246 if (!*p) { 247 warnx("empty home directory field"); 248 return (1); 249 } 250 if (!(pw->pw_dir = strdup(p))) { 251 warnx("can't save entry"); 252 return (1); 253 } 254 return (0); 255 } 256 257 /* ARGSUSED */ 258 int 259 p_shell(p, pw, ep) 260 const char *p; 261 struct passwd *pw; 262 ENTRY *ep; 263 { 264 const char *t; 265 266 if (!*p) { 267 pw->pw_shell = _PATH_BSHELL; 268 return (0); 269 } 270 /* only admin can change from or to "restricted" shells */ 271 if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) { 272 warnx("%s: current shell non-standard", pw->pw_shell); 273 return (1); 274 } 275 if (!(t = ok_shell(p))) { 276 if (uid) { 277 warnx("%s: non-standard shell", p); 278 return (1); 279 } 280 } 281 else 282 p = t; 283 if (!(pw->pw_shell = strdup(p))) { 284 warnx("can't save entry"); 285 return (1); 286 } 287 return (0); 288 } 289