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