GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/tokenadm/tokenadm.c Lines: 0 170 0.0 %
Date: 2017-11-07 Branches: 0 140 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: tokenadm.c,v 1.12 2016/03/22 00:06:55 bluhm Exp $	*/
2
3
/*-
4
 * Copyright (c) 1995 Migration Associates Corp. All Rights Reserved
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 * 3. All advertising materials mentioning features or use of this software
15
 *    must display the following acknowledgement:
16
 *      This product includes software developed by Berkeley Software Design,
17
 *      Inc.
18
 * 4. The name of Berkeley Software Design, Inc.  may not be used to endorse
19
 *    or promote products derived from this software without specific prior
20
 *    written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
23
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
 * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32
 * SUCH DAMAGE.
33
 *
34
 *	BSDI $From: tokenadm.c,v 1.2 1996/10/17 00:54:28 prb Exp $
35
 */
36
37
#include <sys/signal.h>
38
#include <sys/resource.h>
39
#include <sys/time.h>
40
41
#include <err.h>
42
#include <errno.h>
43
#include <stdio.h>
44
#include <syslog.h>
45
#include <stdlib.h>
46
#include <unistd.h>
47
#include <limits.h>
48
#include <string.h>
49
50
#include "token.h"
51
#include "tokendb.h"
52
53
54
typedef enum { LIST, ENABLE, DISABLE, REMOVE, MODECH } what_t;
55
typedef enum {
56
	NOBANNER = 0x01,
57
	TERSE = 0x02,
58
	ENONLY = 0x04,
59
	DISONLY = 0x08,
60
	ONECOL = 0x10,
61
	REVERSE = 0x20
62
} how_t;
63
64
static	int	force_unlock(char *);
65
static	int	process_record(char *, unsigned, unsigned);
66
static	int	process_modes(char *, unsigned, unsigned);
67
static  void	print_record(TOKENDB_Rec *, how_t);
68
69
extern	int
70
main(int argc, char **argv)
71
{
72
	int c, errors;
73
	u_int emode, dmode, pmode;
74
	struct rlimit cds;
75
	what_t what;
76
	how_t how;
77
	TOKENDB_Rec tokenrec;
78
79
	what = LIST;
80
	emode = dmode = 0;
81
	pmode = 0;
82
	errors = 0;
83
	how = 0;
84
85
	(void)signal(SIGQUIT, SIG_IGN);
86
	(void)signal(SIGINT, SIG_IGN);
87
	(void)setpriority(PRIO_PROCESS, 0, 0);
88
89
	openlog(NULL, LOG_ODELAY, LOG_AUTH);
90
91
	/*
92
	 * Make sure we never dump core as we might have a
93
	 * valid user shared-secret in memory.
94
	 */
95
96
	cds.rlim_cur = 0;
97
	cds.rlim_max = 0;
98
	if (setrlimit(RLIMIT_CORE, &cds) < 0)
99
		syslog(LOG_ERR, "couldn't set core dump size to 0: %m");
100
101
	if (pledge("stdio rpath wpath cpath fattr flock getpw", NULL) == -1)
102
		err(1, "pledge");
103
104
	if (token_init(argv[0]) < 0) {
105
		syslog(LOG_ERR, "unknown token type");
106
		errx(1, "unknown token type");
107
	}
108
109
	while ((c = getopt(argc, argv, "BDERT1dem:r")) != -1)
110
		switch (c) {
111
		case 'B':
112
			if (what != LIST)
113
				goto usage;
114
			how |= NOBANNER;
115
			break;
116
		case 'T':
117
			if (what != LIST)
118
				goto usage;
119
			how |= TERSE;
120
			break;
121
		case '1':
122
			if (what != LIST)
123
				goto usage;
124
			how |= ONECOL;
125
			break;
126
		case 'D':
127
			if (what != LIST)
128
				goto usage;
129
			how |= DISONLY;
130
			break;
131
		case 'E':
132
			if (what != LIST)
133
				goto usage;
134
			how |= ENONLY;
135
			break;
136
		case 'R':
137
			if (what != LIST)
138
				goto usage;
139
			how |= REVERSE;
140
			break;
141
		case 'd':
142
			if (what != LIST || how)
143
				goto usage;
144
			what = DISABLE;
145
			break;
146
		case 'e':
147
			if (what != LIST || how)
148
				goto usage;
149
			what = ENABLE;
150
			break;
151
		case 'r':
152
			if (what != LIST || emode || dmode || how)
153
				goto usage;
154
			what = REMOVE;
155
			break;
156
		case 'm':
157
			if (what == REMOVE || how)
158
				goto usage;
159
			if (*optarg == '-') {
160
				if ((c = token_mode(optarg+1)) == 0)
161
					errx(1, "%s: unknown mode", optarg+1);
162
				dmode |= c;
163
			} else {
164
				if ((c = token_mode(optarg)) == 0)
165
					errx(1, "%s: unknown mode", optarg);
166
				emode |= c;
167
			}
168
			break;
169
		default:
170
			goto usage;
171
		}
172
173
	if (what == LIST && (dmode || emode))
174
		what = MODECH;
175
176
	if (what == LIST) {
177
		if ((how & (ENONLY|DISONLY)) == 0)
178
			how |= ENONLY|DISONLY;
179
		if (!(how & NOBANNER)) {
180
			if ((how & (TERSE|ONECOL)) == (TERSE|ONECOL)) {
181
				printf("User\n");
182
				printf("----------------\n");
183
			} else if (how & (TERSE)) {
184
				printf("User             ");
185
				printf("User             ");
186
				printf("User             ");
187
				printf("User\n");
188
				printf("---------------- ");
189
				printf("---------------- ");
190
				printf("---------------- ");
191
				printf("----------------\n");
192
			} else {
193
				printf("User             Status   Modes\n");
194
				printf("---------------- -------- -----\n");
195
			}
196
		}
197
198
		if (optind >= argc) {
199
			if (tokendb_firstrec(how & REVERSE, &tokenrec))
200
				exit(0);
201
			do
202
				print_record(&tokenrec, how);
203
			while (tokendb_nextrec(how & REVERSE, &tokenrec) == 0);
204
			print_record(NULL, how);
205
			exit(0);
206
		}
207
	}
208
209
	if (optind >= argc) {
210
usage:
211
		fprintf(stderr,
212
		    "usage: %sadm [-1BDdEeRrT] [-m [-]mode] [user ...]\n",
213
			tt->name);
214
		exit(1);
215
	}
216
217
	argv += optind - 1;
218
	while (*++argv)
219
		switch (what) {
220
		case LIST:
221
			if (tokendb_getrec(*argv, &tokenrec)) {
222
				printf("%s: no such user\n", *argv);
223
				break;
224
			}
225
			print_record(&tokenrec, how);
226
			break;
227
		case REMOVE:
228
			if (tokendb_delrec(*argv)) {
229
				warnx("%s: could not remove", *argv);
230
				errors++;
231
			}
232
			break;
233
		case DISABLE:
234
			if (process_record(*argv, ~TOKEN_ENABLED, 0)) {
235
				warnx("%s: could not disable", *argv);
236
				++errors;
237
			}
238
			if (emode || dmode)
239
				goto modech;
240
			break;
241
		case ENABLE:
242
			if (process_record(*argv, ~TOKEN_ENABLED, TOKEN_ENABLED)) {
243
				warnx("%s: could not enable", *argv);
244
				++errors;
245
			}
246
			if (emode || dmode)
247
				goto modech;
248
			break;
249
		modech:
250
		case MODECH:
251
			if (process_modes(*argv, ~dmode, emode)) {
252
				warnx("%s: could not change modes", *argv);
253
				++errors;
254
			}
255
			break;
256
		}
257
258
	if (what == LIST)
259
		print_record(NULL, how);
260
261
	exit(errors);
262
}
263
264
/*
265
 * Process a user record
266
 */
267
268
static	int
269
process_record(char *username, unsigned and_mask, unsigned or_mask)
270
{
271
	int	count = 0;
272
	TOKENDB_Rec tokenrec;
273
274
retry:
275
	switch (tokendb_lockrec(username, &tokenrec, TOKEN_LOCKED)) {
276
	case 0:
277
		tokenrec.flags &= and_mask;
278
		tokenrec.flags |= or_mask;
279
		tokenrec.flags &= ~TOKEN_LOCKED;
280
		if (!tokendb_putrec(username, &tokenrec))
281
			return (0);
282
		else
283
			return (-1);
284
	case 1:
285
		sleep(1);
286
		if (count++ < 60)
287
			goto retry;
288
		if (force_unlock(username))
289
			return (1);
290
		goto retry;
291
292
	case ENOENT:
293
		warnx("%s: nonexistent user", username);
294
		return (1);
295
	default:
296
		return (-1);
297
	}
298
}
299
300
static	int
301
process_modes(char *username, unsigned and_mask, unsigned or_mask)
302
{
303
	int	count = 0;
304
	TOKENDB_Rec tokenrec;
305
306
retry:
307
	switch (tokendb_lockrec(username, &tokenrec, TOKEN_LOCKED)) {
308
	case 0:
309
		tokenrec.mode &= and_mask;
310
		tokenrec.mode |= or_mask;
311
		/*
312
		 * When ever we set up for rim mode (even if we are
313
		 * already set up for it) reset the rim key
314
		 */
315
		if (or_mask & TOKEN_RIM)
316
			memset(tokenrec.rim, 0, sizeof(tokenrec.rim));
317
		tokenrec.flags &= ~TOKEN_LOCKED;
318
		if (!tokendb_putrec(username, &tokenrec))
319
			return (0);
320
		else
321
			return (-1);
322
	case 1:
323
		sleep(1);
324
		if (count++ < 60)
325
			goto retry;
326
		if (force_unlock(username))
327
			return (1);
328
		goto retry;
329
330
	case ENOENT:
331
		warnx("%s: nonexistent user", username);
332
		return (1);
333
	default:
334
		return (-1);
335
	}
336
}
337
338
/*
339
 * Force remove a user record-level lock.
340
 */
341
342
static	int
343
force_unlock(char *username)
344
{
345
	TOKENDB_Rec tokenrec;
346
347
	if (tokendb_getrec(username, &tokenrec))
348
		return (-1);
349
350
	tokenrec.flags &= ~TOKEN_LOCKED;
351
	tokenrec.flags &= ~TOKEN_LOGIN;
352
353
	if (tokendb_putrec(username, &tokenrec))
354
		return (1);
355
356
	return (0);
357
}
358
359
/*
360
 * Print a database record according to user a specified format
361
 */
362
363
static	void
364
print_record(TOKENDB_Rec *rec, how_t how)
365
{
366
	static int count = 0;
367
	int i;
368
369
	if (rec == NULL) {
370
		if ((count & 3) && (how & (TERSE|ONECOL)) == TERSE)
371
			printf("\n");
372
		return;
373
	}
374
375
	if (rec->flags & TOKEN_ENABLED) {
376
		if ((how & ENONLY) == 0)
377
			return;
378
	} else {
379
		if ((how & DISONLY) == 0)
380
			return;
381
	}
382
383
	switch (how & (TERSE|ONECOL)) {
384
	case 0:
385
	case ONECOL:
386
		printf("%-16s %-8s", rec->uname,
387
		  rec->flags & TOKEN_ENABLED ? "enabled" : "disabled");
388
389
		for (i = 1; i; i <<= 1)
390
			if (rec->mode & i)
391
				printf(" %s", token_getmode(i));
392
		printf("\n");
393
		break;
394
	case TERSE:
395
		if ((count & 3) == 3)
396
			printf("%s\n", rec->uname);
397
		else
398
			printf("%-16s ", rec->uname);
399
		break;
400
	case TERSE|ONECOL:
401
		printf("%s\n", rec->uname);
402
		break;
403
	}
404
	++count;
405
}