1*fe266b8dSbluhm /* $OpenBSD: tokenadm.c,v 1.12 2016/03/22 00:06:55 bluhm Exp $ */
2851d2d47Smillert
3851d2d47Smillert /*-
4851d2d47Smillert * Copyright (c) 1995 Migration Associates Corp. All Rights Reserved
5851d2d47Smillert *
6851d2d47Smillert * Redistribution and use in source and binary forms, with or without
7851d2d47Smillert * modification, are permitted provided that the following conditions
8851d2d47Smillert * are met:
9851d2d47Smillert * 1. Redistributions of source code must retain the above copyright
10851d2d47Smillert * notice, this list of conditions and the following disclaimer.
11851d2d47Smillert * 2. Redistributions in binary form must reproduce the above copyright
12851d2d47Smillert * notice, this list of conditions and the following disclaimer in the
13851d2d47Smillert * documentation and/or other materials provided with the distribution.
14851d2d47Smillert * 3. All advertising materials mentioning features or use of this software
15851d2d47Smillert * must display the following acknowledgement:
16851d2d47Smillert * This product includes software developed by Berkeley Software Design,
17851d2d47Smillert * Inc.
18851d2d47Smillert * 4. The name of Berkeley Software Design, Inc. may not be used to endorse
19851d2d47Smillert * or promote products derived from this software without specific prior
20851d2d47Smillert * written permission.
21851d2d47Smillert *
22851d2d47Smillert * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
23851d2d47Smillert * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24851d2d47Smillert * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25851d2d47Smillert * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
26851d2d47Smillert * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27851d2d47Smillert * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28851d2d47Smillert * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29851d2d47Smillert * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30851d2d47Smillert * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31851d2d47Smillert * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32851d2d47Smillert * SUCH DAMAGE.
33851d2d47Smillert *
34851d2d47Smillert * BSDI $From: tokenadm.c,v 1.2 1996/10/17 00:54:28 prb Exp $
35851d2d47Smillert */
36851d2d47Smillert
37b9fc9a72Sderaadt #include <sys/signal.h>
38851d2d47Smillert #include <sys/resource.h>
39851d2d47Smillert #include <sys/time.h>
40851d2d47Smillert
41851d2d47Smillert #include <err.h>
42851d2d47Smillert #include <errno.h>
43851d2d47Smillert #include <stdio.h>
44851d2d47Smillert #include <syslog.h>
45851d2d47Smillert #include <stdlib.h>
46851d2d47Smillert #include <unistd.h>
47b9fc9a72Sderaadt #include <limits.h>
48851d2d47Smillert #include <string.h>
49851d2d47Smillert
50851d2d47Smillert #include "token.h"
51851d2d47Smillert #include "tokendb.h"
52851d2d47Smillert
53851d2d47Smillert
54851d2d47Smillert typedef enum { LIST, ENABLE, DISABLE, REMOVE, MODECH } what_t;
55851d2d47Smillert typedef enum {
56851d2d47Smillert NOBANNER = 0x01,
57851d2d47Smillert TERSE = 0x02,
58851d2d47Smillert ENONLY = 0x04,
59851d2d47Smillert DISONLY = 0x08,
60851d2d47Smillert ONECOL = 0x10,
614f67eb1dSderaadt REVERSE = 0x20
62851d2d47Smillert } how_t;
63851d2d47Smillert
64851d2d47Smillert static int force_unlock(char *);
65851d2d47Smillert static int process_record(char *, unsigned, unsigned);
66851d2d47Smillert static int process_modes(char *, unsigned, unsigned);
67851d2d47Smillert static void print_record(TOKENDB_Rec *, how_t);
68851d2d47Smillert
69851d2d47Smillert extern int
main(int argc,char ** argv)70851d2d47Smillert main(int argc, char **argv)
71851d2d47Smillert {
72851d2d47Smillert int c, errors;
73851d2d47Smillert u_int emode, dmode, pmode;
74851d2d47Smillert struct rlimit cds;
75851d2d47Smillert what_t what;
76851d2d47Smillert how_t how;
77851d2d47Smillert TOKENDB_Rec tokenrec;
78851d2d47Smillert
79851d2d47Smillert what = LIST;
80851d2d47Smillert emode = dmode = 0;
81851d2d47Smillert pmode = 0;
82851d2d47Smillert errors = 0;
83851d2d47Smillert how = 0;
84851d2d47Smillert
85851d2d47Smillert (void)signal(SIGQUIT, SIG_IGN);
86851d2d47Smillert (void)signal(SIGINT, SIG_IGN);
87851d2d47Smillert (void)setpriority(PRIO_PROCESS, 0, 0);
88851d2d47Smillert
89851d2d47Smillert openlog(NULL, LOG_ODELAY, LOG_AUTH);
90851d2d47Smillert
91851d2d47Smillert /*
92851d2d47Smillert * Make sure we never dump core as we might have a
93851d2d47Smillert * valid user shared-secret in memory.
94851d2d47Smillert */
95851d2d47Smillert
96851d2d47Smillert cds.rlim_cur = 0;
97851d2d47Smillert cds.rlim_max = 0;
98851d2d47Smillert if (setrlimit(RLIMIT_CORE, &cds) < 0)
99851d2d47Smillert syslog(LOG_ERR, "couldn't set core dump size to 0: %m");
100851d2d47Smillert
1010ef08ec4Smestre if (pledge("stdio rpath wpath cpath fattr flock getpw", NULL) == -1)
1020ef08ec4Smestre err(1, "pledge");
1030ef08ec4Smestre
104*fe266b8dSbluhm if (token_init(argv[0]) < 0) {
105*fe266b8dSbluhm syslog(LOG_ERR, "unknown token type");
106*fe266b8dSbluhm errx(1, "unknown token type");
107*fe266b8dSbluhm }
108*fe266b8dSbluhm
10967e491c4Saaron while ((c = getopt(argc, argv, "BDERT1dem:r")) != -1)
110851d2d47Smillert switch (c) {
111851d2d47Smillert case 'B':
112851d2d47Smillert if (what != LIST)
113851d2d47Smillert goto usage;
114851d2d47Smillert how |= NOBANNER;
115851d2d47Smillert break;
116851d2d47Smillert case 'T':
117851d2d47Smillert if (what != LIST)
118851d2d47Smillert goto usage;
119851d2d47Smillert how |= TERSE;
120851d2d47Smillert break;
121851d2d47Smillert case '1':
122851d2d47Smillert if (what != LIST)
123851d2d47Smillert goto usage;
124851d2d47Smillert how |= ONECOL;
125851d2d47Smillert break;
126851d2d47Smillert case 'D':
127851d2d47Smillert if (what != LIST)
128851d2d47Smillert goto usage;
129851d2d47Smillert how |= DISONLY;
130851d2d47Smillert break;
131851d2d47Smillert case 'E':
132851d2d47Smillert if (what != LIST)
133851d2d47Smillert goto usage;
134851d2d47Smillert how |= ENONLY;
135851d2d47Smillert break;
136851d2d47Smillert case 'R':
137851d2d47Smillert if (what != LIST)
138851d2d47Smillert goto usage;
139851d2d47Smillert how |= REVERSE;
140851d2d47Smillert break;
141851d2d47Smillert case 'd':
142851d2d47Smillert if (what != LIST || how)
143851d2d47Smillert goto usage;
144851d2d47Smillert what = DISABLE;
145851d2d47Smillert break;
146851d2d47Smillert case 'e':
147851d2d47Smillert if (what != LIST || how)
148851d2d47Smillert goto usage;
149851d2d47Smillert what = ENABLE;
150851d2d47Smillert break;
151851d2d47Smillert case 'r':
152851d2d47Smillert if (what != LIST || emode || dmode || how)
153851d2d47Smillert goto usage;
154851d2d47Smillert what = REMOVE;
155851d2d47Smillert break;
156851d2d47Smillert case 'm':
157851d2d47Smillert if (what == REMOVE || how)
158851d2d47Smillert goto usage;
159851d2d47Smillert if (*optarg == '-') {
160cd1e9566Savsm if ((c = token_mode(optarg+1)) == 0)
161851d2d47Smillert errx(1, "%s: unknown mode", optarg+1);
162851d2d47Smillert dmode |= c;
163851d2d47Smillert } else {
164cd1e9566Savsm if ((c = token_mode(optarg)) == 0)
165851d2d47Smillert errx(1, "%s: unknown mode", optarg);
166851d2d47Smillert emode |= c;
167851d2d47Smillert }
168851d2d47Smillert break;
169851d2d47Smillert default:
170851d2d47Smillert goto usage;
171851d2d47Smillert }
172851d2d47Smillert
173851d2d47Smillert if (what == LIST && (dmode || emode))
174851d2d47Smillert what = MODECH;
175851d2d47Smillert
176851d2d47Smillert if (what == LIST) {
177851d2d47Smillert if ((how & (ENONLY|DISONLY)) == 0)
178851d2d47Smillert how |= ENONLY|DISONLY;
179851d2d47Smillert if (!(how & NOBANNER)) {
180851d2d47Smillert if ((how & (TERSE|ONECOL)) == (TERSE|ONECOL)) {
181851d2d47Smillert printf("User\n");
182851d2d47Smillert printf("----------------\n");
183851d2d47Smillert } else if (how & (TERSE)) {
184851d2d47Smillert printf("User ");
185851d2d47Smillert printf("User ");
186851d2d47Smillert printf("User ");
187851d2d47Smillert printf("User\n");
188851d2d47Smillert printf("---------------- ");
189851d2d47Smillert printf("---------------- ");
190851d2d47Smillert printf("---------------- ");
191851d2d47Smillert printf("----------------\n");
192851d2d47Smillert } else {
193851d2d47Smillert printf("User Status Modes\n");
194851d2d47Smillert printf("---------------- -------- -----\n");
195851d2d47Smillert }
196851d2d47Smillert }
197851d2d47Smillert
198851d2d47Smillert if (optind >= argc) {
199851d2d47Smillert if (tokendb_firstrec(how & REVERSE, &tokenrec))
200851d2d47Smillert exit(0);
201851d2d47Smillert do
202851d2d47Smillert print_record(&tokenrec, how);
203851d2d47Smillert while (tokendb_nextrec(how & REVERSE, &tokenrec) == 0);
204851d2d47Smillert print_record(NULL, how);
205851d2d47Smillert exit(0);
206851d2d47Smillert }
207851d2d47Smillert }
208851d2d47Smillert
209851d2d47Smillert if (optind >= argc) {
210851d2d47Smillert usage:
211851d2d47Smillert fprintf(stderr,
212d4acc1c4Sjmc "usage: %sadm [-1BDdEeRrT] [-m [-]mode] [user ...]\n",
213851d2d47Smillert tt->name);
214851d2d47Smillert exit(1);
215851d2d47Smillert }
216851d2d47Smillert
217851d2d47Smillert argv += optind - 1;
218851d2d47Smillert while (*++argv)
219851d2d47Smillert switch (what) {
220851d2d47Smillert case LIST:
221851d2d47Smillert if (tokendb_getrec(*argv, &tokenrec)) {
222851d2d47Smillert printf("%s: no such user\n", *argv);
223851d2d47Smillert break;
224851d2d47Smillert }
225851d2d47Smillert print_record(&tokenrec, how);
226851d2d47Smillert break;
227851d2d47Smillert case REMOVE:
228851d2d47Smillert if (tokendb_delrec(*argv)) {
229851d2d47Smillert warnx("%s: could not remove", *argv);
230851d2d47Smillert errors++;
231851d2d47Smillert }
232851d2d47Smillert break;
233851d2d47Smillert case DISABLE:
234851d2d47Smillert if (process_record(*argv, ~TOKEN_ENABLED, 0)) {
235851d2d47Smillert warnx("%s: could not disable", *argv);
236851d2d47Smillert ++errors;
237851d2d47Smillert }
238851d2d47Smillert if (emode || dmode)
239851d2d47Smillert goto modech;
240851d2d47Smillert break;
241851d2d47Smillert case ENABLE:
2420f7bc442Smarkus if (process_record(*argv, ~TOKEN_ENABLED, TOKEN_ENABLED)) {
243851d2d47Smillert warnx("%s: could not enable", *argv);
244851d2d47Smillert ++errors;
245851d2d47Smillert }
246851d2d47Smillert if (emode || dmode)
247851d2d47Smillert goto modech;
248851d2d47Smillert break;
249851d2d47Smillert modech:
250851d2d47Smillert case MODECH:
251851d2d47Smillert if (process_modes(*argv, ~dmode, emode)) {
252851d2d47Smillert warnx("%s: could not change modes", *argv);
253851d2d47Smillert ++errors;
254851d2d47Smillert }
255851d2d47Smillert break;
256851d2d47Smillert }
257851d2d47Smillert
258851d2d47Smillert if (what == LIST)
259851d2d47Smillert print_record(NULL, how);
260851d2d47Smillert
261851d2d47Smillert exit(errors);
262851d2d47Smillert }
263851d2d47Smillert
264851d2d47Smillert /*
265851d2d47Smillert * Process a user record
266851d2d47Smillert */
267851d2d47Smillert
268851d2d47Smillert static int
process_record(char * username,unsigned and_mask,unsigned or_mask)269851d2d47Smillert process_record(char *username, unsigned and_mask, unsigned or_mask)
270851d2d47Smillert {
271851d2d47Smillert int count = 0;
272851d2d47Smillert TOKENDB_Rec tokenrec;
273851d2d47Smillert
274851d2d47Smillert retry:
275851d2d47Smillert switch (tokendb_lockrec(username, &tokenrec, TOKEN_LOCKED)) {
276851d2d47Smillert case 0:
277851d2d47Smillert tokenrec.flags &= and_mask;
278851d2d47Smillert tokenrec.flags |= or_mask;
279851d2d47Smillert tokenrec.flags &= ~TOKEN_LOCKED;
280851d2d47Smillert if (!tokendb_putrec(username, &tokenrec))
281851d2d47Smillert return (0);
282851d2d47Smillert else
283851d2d47Smillert return (-1);
284851d2d47Smillert case 1:
285851d2d47Smillert sleep(1);
286851d2d47Smillert if (count++ < 60)
287851d2d47Smillert goto retry;
288851d2d47Smillert if (force_unlock(username))
289851d2d47Smillert return (1);
290851d2d47Smillert goto retry;
291851d2d47Smillert
292851d2d47Smillert case ENOENT:
293851d2d47Smillert warnx("%s: nonexistent user", username);
294851d2d47Smillert return (1);
295851d2d47Smillert default:
296851d2d47Smillert return (-1);
297851d2d47Smillert }
298851d2d47Smillert }
299851d2d47Smillert
300851d2d47Smillert static int
process_modes(char * username,unsigned and_mask,unsigned or_mask)301851d2d47Smillert process_modes(char *username, unsigned and_mask, unsigned or_mask)
302851d2d47Smillert {
303851d2d47Smillert int count = 0;
304851d2d47Smillert TOKENDB_Rec tokenrec;
305851d2d47Smillert
306851d2d47Smillert retry:
307851d2d47Smillert switch (tokendb_lockrec(username, &tokenrec, TOKEN_LOCKED)) {
308851d2d47Smillert case 0:
309851d2d47Smillert tokenrec.mode &= and_mask;
310851d2d47Smillert tokenrec.mode |= or_mask;
311851d2d47Smillert /*
312851d2d47Smillert * When ever we set up for rim mode (even if we are
313851d2d47Smillert * already set up for it) reset the rim key
314851d2d47Smillert */
315851d2d47Smillert if (or_mask & TOKEN_RIM)
316851d2d47Smillert memset(tokenrec.rim, 0, sizeof(tokenrec.rim));
317851d2d47Smillert tokenrec.flags &= ~TOKEN_LOCKED;
318851d2d47Smillert if (!tokendb_putrec(username, &tokenrec))
319851d2d47Smillert return (0);
320851d2d47Smillert else
321851d2d47Smillert return (-1);
322851d2d47Smillert case 1:
323851d2d47Smillert sleep(1);
324851d2d47Smillert if (count++ < 60)
325851d2d47Smillert goto retry;
326851d2d47Smillert if (force_unlock(username))
327851d2d47Smillert return (1);
328851d2d47Smillert goto retry;
329851d2d47Smillert
330851d2d47Smillert case ENOENT:
331851d2d47Smillert warnx("%s: nonexistent user", username);
332851d2d47Smillert return (1);
333851d2d47Smillert default:
334851d2d47Smillert return (-1);
335851d2d47Smillert }
336851d2d47Smillert }
337851d2d47Smillert
338851d2d47Smillert /*
339851d2d47Smillert * Force remove a user record-level lock.
340851d2d47Smillert */
341851d2d47Smillert
342851d2d47Smillert static int
force_unlock(char * username)343851d2d47Smillert force_unlock(char *username)
344851d2d47Smillert {
345851d2d47Smillert TOKENDB_Rec tokenrec;
346851d2d47Smillert
347851d2d47Smillert if (tokendb_getrec(username, &tokenrec))
348851d2d47Smillert return (-1);
349851d2d47Smillert
350851d2d47Smillert tokenrec.flags &= ~TOKEN_LOCKED;
351851d2d47Smillert tokenrec.flags &= ~TOKEN_LOGIN;
352851d2d47Smillert
353851d2d47Smillert if (tokendb_putrec(username, &tokenrec))
354851d2d47Smillert return (1);
355851d2d47Smillert
356851d2d47Smillert return (0);
357851d2d47Smillert }
358851d2d47Smillert
359851d2d47Smillert /*
360851d2d47Smillert * Print a database record according to user a specified format
361851d2d47Smillert */
362851d2d47Smillert
363851d2d47Smillert static void
print_record(TOKENDB_Rec * rec,how_t how)364851d2d47Smillert print_record(TOKENDB_Rec *rec, how_t how)
365851d2d47Smillert {
366851d2d47Smillert static int count = 0;
367851d2d47Smillert int i;
368851d2d47Smillert
369851d2d47Smillert if (rec == NULL) {
370851d2d47Smillert if ((count & 3) && (how & (TERSE|ONECOL)) == TERSE)
371851d2d47Smillert printf("\n");
372851d2d47Smillert return;
373851d2d47Smillert }
374851d2d47Smillert
375851d2d47Smillert if (rec->flags & TOKEN_ENABLED) {
376851d2d47Smillert if ((how & ENONLY) == 0)
377851d2d47Smillert return;
378851d2d47Smillert } else {
379851d2d47Smillert if ((how & DISONLY) == 0)
380851d2d47Smillert return;
381851d2d47Smillert }
382851d2d47Smillert
383851d2d47Smillert switch (how & (TERSE|ONECOL)) {
384851d2d47Smillert case 0:
385851d2d47Smillert case ONECOL:
386851d2d47Smillert printf("%-16s %-8s", rec->uname,
387851d2d47Smillert rec->flags & TOKEN_ENABLED ? "enabled" : "disabled");
388851d2d47Smillert
389851d2d47Smillert for (i = 1; i; i <<= 1)
390851d2d47Smillert if (rec->mode & i)
391851d2d47Smillert printf(" %s", token_getmode(i));
392851d2d47Smillert printf("\n");
393851d2d47Smillert break;
394851d2d47Smillert case TERSE:
395851d2d47Smillert if ((count & 3) == 3)
396851d2d47Smillert printf("%s\n", rec->uname);
397851d2d47Smillert else
398851d2d47Smillert printf("%-16s ", rec->uname);
399851d2d47Smillert break;
400851d2d47Smillert case TERSE|ONECOL:
401851d2d47Smillert printf("%s\n", rec->uname);
402851d2d47Smillert break;
403851d2d47Smillert }
404851d2d47Smillert ++count;
405851d2d47Smillert }
406