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