1 /* $OpenBSD: field.c,v 1.14 2015/01/16 06:40:06 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 <ctype.h> 34 #include <err.h> 35 #include <errno.h> 36 #include <grp.h> 37 #include <paths.h> 38 #include <pwd.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 #include <limits.h> 44 45 #include "chpass.h" 46 47 /* ARGSUSED */ 48 int 49 p_login(char *p, struct passwd *pw, ENTRY *ep) 50 { 51 if (!*p) { 52 warnx("empty login field"); 53 return (1); 54 } 55 if (*p == '-') { 56 warnx("login names may not begin with a hyphen"); 57 return (1); 58 } 59 /* XXX - what about truncated names? */ 60 if (strcmp(pw->pw_name, p) != 0 && getpwnam(p) != NULL) { 61 warnx("login %s already exists", p); 62 return (1); 63 } 64 if (!(pw->pw_name = strdup(p))) { 65 warnx("can't save entry"); 66 return (1); 67 } 68 if (strchr(p, '.')) 69 warnx("\'.\' is dangerous in a login name"); 70 for (; *p; ++p) 71 if (isupper((unsigned char)*p)) { 72 warnx("upper-case letters are dangerous in a login name"); 73 break; 74 } 75 return (0); 76 } 77 78 /* ARGSUSED */ 79 int 80 p_passwd(char *p, struct passwd *pw, ENTRY *ep) 81 { 82 if (!*p) 83 pw->pw_passwd = ""; /* "NOLOGIN"; */ 84 else if (!(pw->pw_passwd = strdup(p))) { 85 warnx("can't save password entry"); 86 return (1); 87 } 88 89 return (0); 90 } 91 92 /* ARGSUSED */ 93 int 94 p_uid(char *p, struct passwd *pw, ENTRY *ep) 95 { 96 uid_t id; 97 const char *errstr; 98 99 if (!*p) { 100 warnx("empty uid field"); 101 return (1); 102 } 103 id = (uid_t)strtonum(p, 0, UID_MAX, &errstr); 104 if (errstr) { 105 warnx("uid is %s", errstr); 106 return (1); 107 } 108 pw->pw_uid = id; 109 return (0); 110 } 111 112 /* ARGSUSED */ 113 int 114 p_gid(char *p, struct passwd *pw, ENTRY *ep) 115 { 116 struct group *gr; 117 const char *errstr; 118 gid_t id; 119 120 if (!*p) { 121 warnx("empty gid field"); 122 return (1); 123 } 124 if (!isdigit((unsigned char)*p)) { 125 if (!(gr = getgrnam(p))) { 126 warnx("unknown group %s", p); 127 return (1); 128 } 129 pw->pw_gid = gr->gr_gid; 130 return (0); 131 } 132 id = (uid_t)strtonum(p, 0, GID_MAX, &errstr); 133 if (errstr) { 134 warnx("gid is %s", errstr); 135 return (1); 136 } 137 pw->pw_gid = id; 138 return (0); 139 } 140 141 /* ARGSUSED */ 142 int 143 p_class(char *p, struct passwd *pw, ENTRY *ep) 144 { 145 if (!*p) 146 pw->pw_class = ""; 147 else if (!(pw->pw_class = strdup(p))) { 148 warnx("can't save entry"); 149 return (1); 150 } 151 152 return (0); 153 } 154 155 /* ARGSUSED */ 156 int 157 p_change(char *p, struct passwd *pw, ENTRY *ep) 158 { 159 if (!atot(p, &pw->pw_change)) 160 return (0); 161 warnx("illegal date for change field"); 162 return (1); 163 } 164 165 /* ARGSUSED */ 166 int 167 p_expire(char *p, struct passwd *pw, ENTRY *ep) 168 { 169 if (!atot(p, &pw->pw_expire)) 170 return (0); 171 warnx("illegal date for expire field"); 172 return (1); 173 } 174 175 /* ARGSUSED */ 176 int 177 p_gecos(char *p, struct passwd *pw, ENTRY *ep) 178 { 179 if (!*p) 180 ep->save = ""; 181 else if (!(ep->save = strdup(p))) { 182 warnx("can't save entry"); 183 return (1); 184 } 185 return (0); 186 } 187 188 /* ARGSUSED */ 189 int 190 p_hdir(char *p, struct passwd *pw, ENTRY *ep) 191 { 192 if (!*p) { 193 warnx("empty home directory field"); 194 return (1); 195 } 196 if (!(pw->pw_dir = strdup(p))) { 197 warnx("can't save entry"); 198 return (1); 199 } 200 return (0); 201 } 202 203 /* ARGSUSED */ 204 int 205 p_shell(char *p, struct passwd *pw, ENTRY *ep) 206 { 207 char *t; 208 209 if (!*p) { 210 pw->pw_shell = _PATH_BSHELL; 211 return (0); 212 } 213 /* only admin can change from or to "restricted" shells */ 214 if (uid && pw->pw_shell && !ok_shell(pw->pw_shell, NULL)) { 215 warnx("%s: current shell non-standard", pw->pw_shell); 216 return (1); 217 } 218 if (!ok_shell(p, &t)) { 219 if (uid) { 220 warnx("%s: non-standard shell", p); 221 return (1); 222 } else 223 t = strdup(p); 224 } 225 if (!(pw->pw_shell = t)) { 226 warnx("can't save entry"); 227 return (1); 228 } 229 return (0); 230 } 231