1 /* 2 * Copyright (c) 1988, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)field.c 8.4 (Berkeley) 4/2/94 34 * $DragonFly: src/usr.bin/chpass/field.c,v 1.3 2003/10/02 17:42:26 hmp Exp $ 35 */ 36 37 #include <sys/param.h> 38 #include <sys/stat.h> 39 40 #include <ctype.h> 41 #include <err.h> 42 #include <errno.h> 43 #include <grp.h> 44 #include <pwd.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include "chpass.h" 51 #include "pathnames.h" 52 53 /* ARGSUSED */ 54 int 55 p_login(char *p, struct passwd *pw, ENTRY *ep) 56 { 57 if (!*p) { 58 warnx("empty login field"); 59 return (1); 60 } 61 if (*p == '-') { 62 warnx("login names may not begin with a hyphen"); 63 return (1); 64 } 65 if (!(pw->pw_name = strdup(p))) { 66 warnx("can't save entry"); 67 return (1); 68 } 69 if (strchr(p, '.')) 70 warnx("\'.\' is dangerous in a login name"); 71 for (; *p; ++p) 72 if (isupper(*p)) { 73 warnx("upper-case letters are dangerous in a login name"); 74 break; 75 } 76 return (0); 77 } 78 79 /* ARGSUSED */ 80 int 81 p_passwd(char *p, struct passwd *pw, ENTRY *ep) 82 { 83 if (!*p) 84 pw->pw_passwd = ""; /* "NOLOGIN"; */ 85 else if (!(pw->pw_passwd = strdup(p))) { 86 warnx("can't save password entry"); 87 return (1); 88 } 89 90 return (0); 91 } 92 93 /* ARGSUSED */ 94 int 95 p_uid(char *p, struct passwd *pw, ENTRY *ep) 96 { 97 uid_t id; 98 char *np; 99 100 if (!*p) { 101 warnx("empty uid field"); 102 return (1); 103 } 104 if (!isdigit(*p)) { 105 warnx("illegal uid"); 106 return (1); 107 } 108 errno = 0; 109 id = strtoul(p, &np, 10); 110 if (*np || (id == ULONG_MAX && errno == ERANGE)) { 111 warnx("illegal uid"); 112 return (1); 113 } 114 pw->pw_uid = id; 115 return (0); 116 } 117 118 /* ARGSUSED */ 119 int 120 p_gid(char *p, struct passwd *pw, ENTRY *ep) 121 { 122 struct group *gr; 123 gid_t id; 124 char *np; 125 126 if (!*p) { 127 warnx("empty gid field"); 128 return (1); 129 } 130 if (!isdigit(*p)) { 131 if (!(gr = getgrnam(p))) { 132 warnx("unknown group %s", p); 133 return (1); 134 } 135 pw->pw_gid = gr->gr_gid; 136 return (0); 137 } 138 errno = 0; 139 id = strtoul(p, &np, 10); 140 if (*np || (id == ULONG_MAX && errno == ERANGE)) { 141 warnx("illegal gid"); 142 return (1); 143 } 144 pw->pw_gid = id; 145 return (0); 146 } 147 148 /* ARGSUSED */ 149 int 150 p_class(char *p, struct passwd *pw, ENTRY *ep) 151 { 152 if (!*p) 153 pw->pw_class = ""; 154 else if (!(pw->pw_class = strdup(p))) { 155 warnx("can't save entry"); 156 return (1); 157 } 158 159 return (0); 160 } 161 162 /* ARGSUSED */ 163 int 164 p_change(char *p, struct passwd *pw, ENTRY *ep) 165 { 166 if (!atot(p, &pw->pw_change)) 167 return (0); 168 warnx("illegal date for change field"); 169 return (1); 170 } 171 172 /* ARGSUSED */ 173 int 174 p_expire(char *p, struct passwd *pw, ENTRY *ep) 175 { 176 if (!atot(p, &pw->pw_expire)) 177 return (0); 178 warnx("illegal date for expire field"); 179 return (1); 180 } 181 182 /* ARGSUSED */ 183 int 184 p_gecos(char *p, struct passwd *pw, ENTRY *ep) 185 { 186 if (!*p) 187 ep->save = ""; 188 else if (!(ep->save = strdup(p))) { 189 warnx("can't save entry"); 190 return (1); 191 } 192 return (0); 193 } 194 195 /* ARGSUSED */ 196 int 197 p_hdir(char *p, struct passwd *pw, ENTRY *ep) 198 { 199 if (!*p) { 200 warnx("empty home directory field"); 201 return (1); 202 } 203 if (!(pw->pw_dir = strdup(p))) { 204 warnx("can't save entry"); 205 return (1); 206 } 207 return (0); 208 } 209 210 /* ARGSUSED */ 211 int 212 p_shell(char *p, struct passwd *pw, ENTRY *ep) 213 { 214 char *t, *ok_shell(); 215 struct stat sbuf; 216 217 if (!*p) { 218 pw->pw_shell = _PATH_BSHELL; 219 return (0); 220 } 221 /* only admin can change from or to "restricted" shells */ 222 if (uid && pw->pw_shell && !ok_shell(pw->pw_shell)) { 223 warnx("%s: current shell non-standard", pw->pw_shell); 224 return (1); 225 } 226 if (!(t = ok_shell(p))) { 227 if (uid) { 228 warnx("%s: non-standard shell", p); 229 return (1); 230 } 231 } 232 else 233 p = t; 234 if (!(pw->pw_shell = strdup(p))) { 235 warnx("can't save entry"); 236 return (1); 237 } 238 if (stat(pw->pw_shell, &sbuf) < 0) { 239 if (errno == ENOENT) 240 warnx("WARNING: shell '%s' does not exist", 241 pw->pw_shell); 242 else 243 warn("WARNING: can't stat shell '%s'", pw->pw_shell); 244 return (0); 245 } 246 if (!S_ISREG(sbuf.st_mode)) { 247 warnx("WARNING: shell '%s' is not a regular file", 248 pw->pw_shell); 249 return (0); 250 } 251 if ((sbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) == 0) { 252 warnx("WARNING: shell '%s' is not executable", pw->pw_shell); 253 return (0); 254 } 255 return (0); 256 } 257