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 47int 48p_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 77int 78p_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 90int 91p_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 109int 110p_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 137int 138p_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 150int 151p_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 159int 160p_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 168int 169p_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 180int 181p_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 194int 195p_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