File: [local] / src / usr.sbin / tokenadm / tokenadm.c (download)
Revision 1.12, Tue Mar 22 00:06:55 2016 UTC (8 years, 2 months ago) by bluhm
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, OPENBSD_7_0_BASE, OPENBSD_7_0, OPENBSD_6_9_BASE, OPENBSD_6_9, OPENBSD_6_8_BASE, OPENBSD_6_8, OPENBSD_6_7_BASE, OPENBSD_6_7, OPENBSD_6_6_BASE, OPENBSD_6_6, OPENBSD_6_5_BASE, OPENBSD_6_5, OPENBSD_6_4_BASE, OPENBSD_6_4, OPENBSD_6_3_BASE, OPENBSD_6_3, OPENBSD_6_2_BASE, OPENBSD_6_2, OPENBSD_6_1_BASE, OPENBSD_6_1, OPENBSD_6_0_BASE, OPENBSD_6_0, HEAD Changes since 1.11: +6 -6 lines
tokenadm(8) is already pledged, do the same for tokeninit(8).
- bring comment in both programms in line
- tokeninit(8) needs "tty" for readpassphrase(3)
- call token_init() after pledge(2)
- fix whitespace
OK millert@
|
/* $OpenBSD: tokenadm.c,v 1.12 2016/03/22 00:06:55 bluhm Exp $ */
/*-
* Copyright (c) 1995 Migration Associates Corp. All Rights Reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Berkeley Software Design,
* Inc.
* 4. The name of Berkeley Software Design, Inc. may not be used to endorse
* or promote products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN, INC. ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN, INC. BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* BSDI $From: tokenadm.c,v 1.2 1996/10/17 00:54:28 prb Exp $
*/
#include <sys/signal.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <syslog.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include "token.h"
#include "tokendb.h"
typedef enum { LIST, ENABLE, DISABLE, REMOVE, MODECH } what_t;
typedef enum {
NOBANNER = 0x01,
TERSE = 0x02,
ENONLY = 0x04,
DISONLY = 0x08,
ONECOL = 0x10,
REVERSE = 0x20
} how_t;
static int force_unlock(char *);
static int process_record(char *, unsigned, unsigned);
static int process_modes(char *, unsigned, unsigned);
static void print_record(TOKENDB_Rec *, how_t);
extern int
main(int argc, char **argv)
{
int c, errors;
u_int emode, dmode, pmode;
struct rlimit cds;
what_t what;
how_t how;
TOKENDB_Rec tokenrec;
what = LIST;
emode = dmode = 0;
pmode = 0;
errors = 0;
how = 0;
(void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
(void)setpriority(PRIO_PROCESS, 0, 0);
openlog(NULL, LOG_ODELAY, LOG_AUTH);
/*
* Make sure we never dump core as we might have a
* valid user shared-secret in memory.
*/
cds.rlim_cur = 0;
cds.rlim_max = 0;
if (setrlimit(RLIMIT_CORE, &cds) < 0)
syslog(LOG_ERR, "couldn't set core dump size to 0: %m");
if (pledge("stdio rpath wpath cpath fattr flock getpw", NULL) == -1)
err(1, "pledge");
if (token_init(argv[0]) < 0) {
syslog(LOG_ERR, "unknown token type");
errx(1, "unknown token type");
}
while ((c = getopt(argc, argv, "BDERT1dem:r")) != -1)
switch (c) {
case 'B':
if (what != LIST)
goto usage;
how |= NOBANNER;
break;
case 'T':
if (what != LIST)
goto usage;
how |= TERSE;
break;
case '1':
if (what != LIST)
goto usage;
how |= ONECOL;
break;
case 'D':
if (what != LIST)
goto usage;
how |= DISONLY;
break;
case 'E':
if (what != LIST)
goto usage;
how |= ENONLY;
break;
case 'R':
if (what != LIST)
goto usage;
how |= REVERSE;
break;
case 'd':
if (what != LIST || how)
goto usage;
what = DISABLE;
break;
case 'e':
if (what != LIST || how)
goto usage;
what = ENABLE;
break;
case 'r':
if (what != LIST || emode || dmode || how)
goto usage;
what = REMOVE;
break;
case 'm':
if (what == REMOVE || how)
goto usage;
if (*optarg == '-') {
if ((c = token_mode(optarg+1)) == 0)
errx(1, "%s: unknown mode", optarg+1);
dmode |= c;
} else {
if ((c = token_mode(optarg)) == 0)
errx(1, "%s: unknown mode", optarg);
emode |= c;
}
break;
default:
goto usage;
}
if (what == LIST && (dmode || emode))
what = MODECH;
if (what == LIST) {
if ((how & (ENONLY|DISONLY)) == 0)
how |= ENONLY|DISONLY;
if (!(how & NOBANNER)) {
if ((how & (TERSE|ONECOL)) == (TERSE|ONECOL)) {
printf("User\n");
printf("----------------\n");
} else if (how & (TERSE)) {
printf("User ");
printf("User ");
printf("User ");
printf("User\n");
printf("---------------- ");
printf("---------------- ");
printf("---------------- ");
printf("----------------\n");
} else {
printf("User Status Modes\n");
printf("---------------- -------- -----\n");
}
}
if (optind >= argc) {
if (tokendb_firstrec(how & REVERSE, &tokenrec))
exit(0);
do
print_record(&tokenrec, how);
while (tokendb_nextrec(how & REVERSE, &tokenrec) == 0);
print_record(NULL, how);
exit(0);
}
}
if (optind >= argc) {
usage:
fprintf(stderr,
"usage: %sadm [-1BDdEeRrT] [-m [-]mode] [user ...]\n",
tt->name);
exit(1);
}
argv += optind - 1;
while (*++argv)
switch (what) {
case LIST:
if (tokendb_getrec(*argv, &tokenrec)) {
printf("%s: no such user\n", *argv);
break;
}
print_record(&tokenrec, how);
break;
case REMOVE:
if (tokendb_delrec(*argv)) {
warnx("%s: could not remove", *argv);
errors++;
}
break;
case DISABLE:
if (process_record(*argv, ~TOKEN_ENABLED, 0)) {
warnx("%s: could not disable", *argv);
++errors;
}
if (emode || dmode)
goto modech;
break;
case ENABLE:
if (process_record(*argv, ~TOKEN_ENABLED, TOKEN_ENABLED)) {
warnx("%s: could not enable", *argv);
++errors;
}
if (emode || dmode)
goto modech;
break;
modech:
case MODECH:
if (process_modes(*argv, ~dmode, emode)) {
warnx("%s: could not change modes", *argv);
++errors;
}
break;
}
if (what == LIST)
print_record(NULL, how);
exit(errors);
}
/*
* Process a user record
*/
static int
process_record(char *username, unsigned and_mask, unsigned or_mask)
{
int count = 0;
TOKENDB_Rec tokenrec;
retry:
switch (tokendb_lockrec(username, &tokenrec, TOKEN_LOCKED)) {
case 0:
tokenrec.flags &= and_mask;
tokenrec.flags |= or_mask;
tokenrec.flags &= ~TOKEN_LOCKED;
if (!tokendb_putrec(username, &tokenrec))
return (0);
else
return (-1);
case 1:
sleep(1);
if (count++ < 60)
goto retry;
if (force_unlock(username))
return (1);
goto retry;
case ENOENT:
warnx("%s: nonexistent user", username);
return (1);
default:
return (-1);
}
}
static int
process_modes(char *username, unsigned and_mask, unsigned or_mask)
{
int count = 0;
TOKENDB_Rec tokenrec;
retry:
switch (tokendb_lockrec(username, &tokenrec, TOKEN_LOCKED)) {
case 0:
tokenrec.mode &= and_mask;
tokenrec.mode |= or_mask;
/*
* When ever we set up for rim mode (even if we are
* already set up for it) reset the rim key
*/
if (or_mask & TOKEN_RIM)
memset(tokenrec.rim, 0, sizeof(tokenrec.rim));
tokenrec.flags &= ~TOKEN_LOCKED;
if (!tokendb_putrec(username, &tokenrec))
return (0);
else
return (-1);
case 1:
sleep(1);
if (count++ < 60)
goto retry;
if (force_unlock(username))
return (1);
goto retry;
case ENOENT:
warnx("%s: nonexistent user", username);
return (1);
default:
return (-1);
}
}
/*
* Force remove a user record-level lock.
*/
static int
force_unlock(char *username)
{
TOKENDB_Rec tokenrec;
if (tokendb_getrec(username, &tokenrec))
return (-1);
tokenrec.flags &= ~TOKEN_LOCKED;
tokenrec.flags &= ~TOKEN_LOGIN;
if (tokendb_putrec(username, &tokenrec))
return (1);
return (0);
}
/*
* Print a database record according to user a specified format
*/
static void
print_record(TOKENDB_Rec *rec, how_t how)
{
static int count = 0;
int i;
if (rec == NULL) {
if ((count & 3) && (how & (TERSE|ONECOL)) == TERSE)
printf("\n");
return;
}
if (rec->flags & TOKEN_ENABLED) {
if ((how & ENONLY) == 0)
return;
} else {
if ((how & DISONLY) == 0)
return;
}
switch (how & (TERSE|ONECOL)) {
case 0:
case ONECOL:
printf("%-16s %-8s", rec->uname,
rec->flags & TOKEN_ENABLED ? "enabled" : "disabled");
for (i = 1; i; i <<= 1)
if (rec->mode & i)
printf(" %s", token_getmode(i));
printf("\n");
break;
case TERSE:
if ((count & 3) == 3)
printf("%s\n", rec->uname);
else
printf("%-16s ", rec->uname);
break;
case TERSE|ONECOL:
printf("%s\n", rec->uname);
break;
}
++count;
}