1 /* $OpenBSD: field.c,v 1.12 2009/10/27 23:59:36 deraadt Exp $ */ 2 /* $NetBSD: field.c,v 1.3 1995/03/26 04:55:28 glass Exp $ */ 3 4 /* 5 * Copyright (c) 1988, 1993, 1994 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 35 #include <ctype.h> 36 #include <err.h> 37 #include <errno.h> 38 #include <grp.h> 39 #include <paths.h> 40 #include <pwd.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 46 #include "chpass.h" 47 48 /* ARGSUSED */ 49 int 50 p_login(char *p, struct passwd *pw, ENTRY *ep) 51 { 52 if (!*p) { 53 warnx("empty login field"); 54 return (1); 55 } 56 if (*p == '-') { 57 warnx("login names may not begin with a hyphen"); 58 return (1); 59 } 60 /* XXX - what about truncated names? */ 61 if (strcmp(pw->pw_name, p) != 0 && getpwnam(p) != NULL) { 62 warnx("login %s already exists", p); 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 const char *errstr; 99 100 if (!*p) { 101 warnx("empty uid field"); 102 return (1); 103 } 104 id = (uid_t)strtonum(p, 0, UID_MAX, &errstr); 105 if (errstr) { 106 warnx("uid is %s", errstr); 107 return (1); 108 } 109 pw->pw_uid = id; 110 return (0); 111 } 112 113 /* ARGSUSED */ 114 int 115 p_gid(char *p, struct passwd *pw, ENTRY *ep) 116 { 117 struct group *gr; 118 const char *errstr; 119 gid_t id; 120 121 if (!*p) { 122 warnx("empty gid field"); 123 return (1); 124 } 125 if (!isdigit(*p)) { 126 if (!(gr = getgrnam(p))) { 127 warnx("unknown group %s", p); 128 return (1); 129 } 130 pw->pw_gid = gr->gr_gid; 131 return (0); 132 } 133 id = (uid_t)strtonum(p, 0, GID_MAX, &errstr); 134 if (errstr) { 135 warnx("gid is %s", errstr); 136 return (1); 137 } 138 pw->pw_gid = id; 139 return (0); 140 } 141 142 /* ARGSUSED */ 143 int 144 p_class(char *p, struct passwd *pw, ENTRY *ep) 145 { 146 if (!*p) 147 pw->pw_class = ""; 148 else if (!(pw->pw_class = strdup(p))) { 149 warnx("can't save entry"); 150 return (1); 151 } 152 153 return (0); 154 } 155 156 /* ARGSUSED */ 157 int 158 p_change(char *p, struct passwd *pw, ENTRY *ep) 159 { 160 if (!atot(p, &pw->pw_change)) 161 return (0); 162 warnx("illegal date for change field"); 163 return (1); 164 } 165 166 /* ARGSUSED */ 167 int 168 p_expire(char *p, struct passwd *pw, ENTRY *ep) 169 { 170 if (!atot(p, &pw->pw_expire)) 171 return (0); 172 warnx("illegal date for expire field"); 173 return (1); 174 } 175 176 /* ARGSUSED */ 177 int 178 p_gecos(char *p, struct passwd *pw, ENTRY *ep) 179 { 180 if (!*p) 181 ep->save = ""; 182 else if (!(ep->save = strdup(p))) { 183 warnx("can't save entry"); 184 return (1); 185 } 186 return (0); 187 } 188 189 /* ARGSUSED */ 190 int 191 p_hdir(char *p, struct passwd *pw, ENTRY *ep) 192 { 193 if (!*p) { 194 warnx("empty home directory field"); 195 return (1); 196 } 197 if (!(pw->pw_dir = strdup(p))) { 198 warnx("can't save entry"); 199 return (1); 200 } 201 return (0); 202 } 203 204 /* ARGSUSED */ 205 int 206 p_shell(char *p, struct passwd *pw, ENTRY *ep) 207 { 208 char *t; 209 210 if (!*p) { 211 pw->pw_shell = _PATH_BSHELL; 212 return (0); 213 } 214 /* only admin can change from or to "restricted" shells */ 215 if (uid && pw->pw_shell && !ok_shell(pw->pw_shell, NULL)) { 216 warnx("%s: current shell non-standard", pw->pw_shell); 217 return (1); 218 } 219 if (!ok_shell(p, &t)) { 220 if (uid) { 221 warnx("%s: non-standard shell", p); 222 return (1); 223 } else 224 t = strdup(p); 225 } 226 if (!(pw->pw_shell = t)) { 227 warnx("can't save entry"); 228 return (1); 229 } 230 return (0); 231 } 232