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 } 406