1 /* $OpenBSD: tokenadm.c,v 1.9 2007/03/15 22:31:14 jmc 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/param.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 <string.h> 48 49 #include "token.h" 50 #include "tokendb.h" 51 52 53 typedef enum { LIST, ENABLE, DISABLE, REMOVE, MODECH } what_t; 54 typedef enum { 55 NOBANNER = 0x01, 56 TERSE = 0x02, 57 ENONLY = 0x04, 58 DISONLY = 0x08, 59 ONECOL = 0x10, 60 REVERSE = 0x20 61 } how_t; 62 63 static int force_unlock(char *); 64 static int process_record(char *, unsigned, unsigned); 65 static int process_modes(char *, unsigned, unsigned); 66 static void print_record(TOKENDB_Rec *, how_t); 67 68 extern int 69 main(int argc, char **argv) 70 { 71 int c, errors; 72 u_int emode, dmode, pmode; 73 struct rlimit cds; 74 what_t what; 75 how_t how; 76 TOKENDB_Rec tokenrec; 77 78 what = LIST; 79 emode = dmode = 0; 80 pmode = 0; 81 errors = 0; 82 how = 0; 83 84 (void)signal(SIGQUIT, SIG_IGN); 85 (void)signal(SIGINT, SIG_IGN); 86 (void)setpriority(PRIO_PROCESS, 0, 0); 87 88 openlog(NULL, LOG_ODELAY, LOG_AUTH); 89 90 if (token_init(argv[0]) < 0) { 91 syslog(LOG_ERR, "unknown token type"); 92 errx(1, "unknown token type"); 93 } 94 95 /* 96 * Make sure we never dump core as we might have a 97 * valid user shared-secret in memory. 98 */ 99 100 cds.rlim_cur = 0; 101 cds.rlim_max = 0; 102 if (setrlimit(RLIMIT_CORE, &cds) < 0) 103 syslog(LOG_ERR, "couldn't set core dump size to 0: %m"); 104 105 while ((c = getopt(argc, argv, "BDERT1dem:r")) != -1) 106 switch (c) { 107 case 'B': 108 if (what != LIST) 109 goto usage; 110 how |= NOBANNER; 111 break; 112 case 'T': 113 if (what != LIST) 114 goto usage; 115 how |= TERSE; 116 break; 117 case '1': 118 if (what != LIST) 119 goto usage; 120 how |= ONECOL; 121 break; 122 case 'D': 123 if (what != LIST) 124 goto usage; 125 how |= DISONLY; 126 break; 127 case 'E': 128 if (what != LIST) 129 goto usage; 130 how |= ENONLY; 131 break; 132 case 'R': 133 if (what != LIST) 134 goto usage; 135 how |= REVERSE; 136 break; 137 case 'd': 138 if (what != LIST || how) 139 goto usage; 140 what = DISABLE; 141 break; 142 case 'e': 143 if (what != LIST || how) 144 goto usage; 145 what = ENABLE; 146 break; 147 case 'r': 148 if (what != LIST || emode || dmode || how) 149 goto usage; 150 what = REMOVE; 151 break; 152 case 'm': 153 if (what == REMOVE || how) 154 goto usage; 155 if (*optarg == '-') { 156 if ((c = token_mode(optarg+1)) == 0) 157 errx(1, "%s: unknown mode", optarg+1); 158 dmode |= c; 159 } else { 160 if ((c = token_mode(optarg)) == 0) 161 errx(1, "%s: unknown mode", optarg); 162 emode |= c; 163 } 164 break; 165 default: 166 goto usage; 167 } 168 169 if (what == LIST && (dmode || emode)) 170 what = MODECH; 171 172 if (what == LIST) { 173 if ((how & (ENONLY|DISONLY)) == 0) 174 how |= ENONLY|DISONLY; 175 if (!(how & NOBANNER)) { 176 if ((how & (TERSE|ONECOL)) == (TERSE|ONECOL)) { 177 printf("User\n"); 178 printf("----------------\n"); 179 } else if (how & (TERSE)) { 180 printf("User "); 181 printf("User "); 182 printf("User "); 183 printf("User\n"); 184 printf("---------------- "); 185 printf("---------------- "); 186 printf("---------------- "); 187 printf("----------------\n"); 188 } else { 189 printf("User Status Modes\n"); 190 printf("---------------- -------- -----\n"); 191 } 192 } 193 194 if (optind >= argc) { 195 if (tokendb_firstrec(how & REVERSE, &tokenrec)) 196 exit(0); 197 do 198 print_record(&tokenrec, how); 199 while (tokendb_nextrec(how & REVERSE, &tokenrec) == 0); 200 print_record(NULL, how); 201 exit(0); 202 } 203 } 204 205 if (optind >= argc) { 206 usage: 207 fprintf(stderr, 208 "usage: %sadm [-1BDdEeRrT] [-m [-]mode] [user ...]\n", 209 tt->name); 210 exit(1); 211 } 212 213 argv += optind - 1; 214 while (*++argv) 215 switch (what) { 216 case LIST: 217 if (tokendb_getrec(*argv, &tokenrec)) { 218 printf("%s: no such user\n", *argv); 219 break; 220 } 221 print_record(&tokenrec, how); 222 break; 223 case REMOVE: 224 if (tokendb_delrec(*argv)) { 225 warnx("%s: could not remove", *argv); 226 errors++; 227 } 228 break; 229 case DISABLE: 230 if (process_record(*argv, ~TOKEN_ENABLED, 0)) { 231 warnx("%s: could not disable", *argv); 232 ++errors; 233 } 234 if (emode || dmode) 235 goto modech; 236 break; 237 case ENABLE: 238 if (process_record(*argv, ~TOKEN_ENABLED, TOKEN_ENABLED)) { 239 warnx("%s: could not enable", *argv); 240 ++errors; 241 } 242 if (emode || dmode) 243 goto modech; 244 break; 245 modech: 246 case MODECH: 247 if (process_modes(*argv, ~dmode, emode)) { 248 warnx("%s: could not change modes", *argv); 249 ++errors; 250 } 251 break; 252 } 253 254 if (what == LIST) 255 print_record(NULL, how); 256 257 exit(errors); 258 } 259 260 /* 261 * Process a user record 262 */ 263 264 static int 265 process_record(char *username, unsigned and_mask, unsigned or_mask) 266 { 267 int count = 0; 268 TOKENDB_Rec tokenrec; 269 270 retry: 271 switch (tokendb_lockrec(username, &tokenrec, TOKEN_LOCKED)) { 272 case 0: 273 tokenrec.flags &= and_mask; 274 tokenrec.flags |= or_mask; 275 tokenrec.flags &= ~TOKEN_LOCKED; 276 if (!tokendb_putrec(username, &tokenrec)) 277 return (0); 278 else 279 return (-1); 280 case 1: 281 sleep(1); 282 if (count++ < 60) 283 goto retry; 284 if (force_unlock(username)) 285 return (1); 286 goto retry; 287 288 case ENOENT: 289 warnx("%s: nonexistent user", username); 290 return (1); 291 default: 292 return (-1); 293 } 294 } 295 296 static int 297 process_modes(char *username, unsigned and_mask, unsigned or_mask) 298 { 299 int count = 0; 300 TOKENDB_Rec tokenrec; 301 302 retry: 303 switch (tokendb_lockrec(username, &tokenrec, TOKEN_LOCKED)) { 304 case 0: 305 tokenrec.mode &= and_mask; 306 tokenrec.mode |= or_mask; 307 /* 308 * When ever we set up for rim mode (even if we are 309 * already set up for it) reset the rim key 310 */ 311 if (or_mask & TOKEN_RIM) 312 memset(tokenrec.rim, 0, sizeof(tokenrec.rim)); 313 tokenrec.flags &= ~TOKEN_LOCKED; 314 if (!tokendb_putrec(username, &tokenrec)) 315 return (0); 316 else 317 return (-1); 318 case 1: 319 sleep(1); 320 if (count++ < 60) 321 goto retry; 322 if (force_unlock(username)) 323 return (1); 324 goto retry; 325 326 case ENOENT: 327 warnx("%s: nonexistent user", username); 328 return (1); 329 default: 330 return (-1); 331 } 332 } 333 334 /* 335 * Force remove a user record-level lock. 336 */ 337 338 static int 339 force_unlock(char *username) 340 { 341 TOKENDB_Rec tokenrec; 342 343 if (tokendb_getrec(username, &tokenrec)) 344 return (-1); 345 346 tokenrec.flags &= ~TOKEN_LOCKED; 347 tokenrec.flags &= ~TOKEN_LOGIN; 348 349 if (tokendb_putrec(username, &tokenrec)) 350 return (1); 351 352 return (0); 353 } 354 355 /* 356 * Print a database record according to user a specified format 357 */ 358 359 static void 360 print_record(TOKENDB_Rec *rec, how_t how) 361 { 362 static int count = 0; 363 int i; 364 365 if (rec == NULL) { 366 if ((count & 3) && (how & (TERSE|ONECOL)) == TERSE) 367 printf("\n"); 368 return; 369 } 370 371 if (rec->flags & TOKEN_ENABLED) { 372 if ((how & ENONLY) == 0) 373 return; 374 } else { 375 if ((how & DISONLY) == 0) 376 return; 377 } 378 379 switch (how & (TERSE|ONECOL)) { 380 case 0: 381 case ONECOL: 382 printf("%-16s %-8s", rec->uname, 383 rec->flags & TOKEN_ENABLED ? "enabled" : "disabled"); 384 385 for (i = 1; i; i <<= 1) 386 if (rec->mode & i) 387 printf(" %s", token_getmode(i)); 388 printf("\n"); 389 break; 390 case TERSE: 391 if ((count & 3) == 3) 392 printf("%s\n", rec->uname); 393 else 394 printf("%-16s ", rec->uname); 395 break; 396 case TERSE|ONECOL: 397 printf("%s\n", rec->uname); 398 break; 399 } 400 ++count; 401 } 402