1 /* $OpenBSD: tokenadm.c,v 1.1 2000/12/20 02:08:09 millert 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, "BDERT1bdem:ru")) != EOF) 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)) == NULL) 157 errx(1, "%s: unknown mode", optarg+1); 158 dmode |= c; 159 } else { 160 if ((c = token_mode(optarg)) == NULL) 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 [-BDERT1 | -d | -e | -r] [-m mode] user [...]\n", 209 tt->name); 210 exit(1); 211 } 212 213 214 argv += optind - 1; 215 while (*++argv) 216 switch(what) { 217 case LIST: 218 if (tokendb_getrec(*argv, &tokenrec)) { 219 printf("%s: no such user\n", *argv); 220 break; 221 } 222 print_record(&tokenrec, how); 223 break; 224 case REMOVE: 225 if (tokendb_delrec(*argv)) { 226 warnx("%s: could not remove", *argv); 227 errors++; 228 } 229 break; 230 case DISABLE: 231 if (process_record(*argv, ~TOKEN_ENABLED, 0)) { 232 warnx("%s: could not disable", *argv); 233 ++errors; 234 } 235 if (emode || dmode) 236 goto modech; 237 break; 238 case ENABLE: 239 if (process_record(*argv, ~TOKEN_ENABLED, 0)) { 240 warnx("%s: could not enable", *argv); 241 ++errors; 242 } 243 if (emode || dmode) 244 goto modech; 245 break; 246 modech: 247 case MODECH: 248 if (process_modes(*argv, ~dmode, emode)) { 249 warnx("%s: could not change modes", *argv); 250 ++errors; 251 } 252 break; 253 } 254 255 if (what == LIST) 256 print_record(NULL, how); 257 258 exit(errors); 259 } 260 261 /* 262 * Process a user record 263 */ 264 265 static int 266 process_record(char *username, unsigned and_mask, unsigned or_mask) 267 { 268 int count = 0; 269 TOKENDB_Rec tokenrec; 270 271 retry: 272 switch (tokendb_lockrec(username, &tokenrec, TOKEN_LOCKED)) { 273 case 0: 274 tokenrec.flags &= and_mask; 275 tokenrec.flags |= or_mask; 276 tokenrec.flags &= ~TOKEN_LOCKED; 277 if (!tokendb_putrec(username, &tokenrec)) 278 return (0); 279 else 280 return (-1); 281 case 1: 282 sleep(1); 283 if (count++ < 60) 284 goto retry; 285 if (force_unlock(username)) 286 return (1); 287 goto retry; 288 289 case ENOENT: 290 warnx("%s: nonexistent user", username); 291 return (1); 292 default: 293 return (-1); 294 } 295 } 296 297 static int 298 process_modes(char *username, unsigned and_mask, unsigned or_mask) 299 { 300 int count = 0; 301 TOKENDB_Rec tokenrec; 302 303 retry: 304 switch (tokendb_lockrec(username, &tokenrec, TOKEN_LOCKED)) { 305 case 0: 306 tokenrec.mode &= and_mask; 307 tokenrec.mode |= or_mask; 308 /* 309 * When ever we set up for rim mode (even if we are 310 * already set up for it) reset the rim key 311 */ 312 if (or_mask & TOKEN_RIM) 313 memset(tokenrec.rim, 0, sizeof(tokenrec.rim)); 314 tokenrec.flags &= ~TOKEN_LOCKED; 315 if (!tokendb_putrec(username, &tokenrec)) 316 return (0); 317 else 318 return (-1); 319 case 1: 320 sleep(1); 321 if (count++ < 60) 322 goto retry; 323 if (force_unlock(username)) 324 return (1); 325 goto retry; 326 327 case ENOENT: 328 warnx("%s: nonexistent user", username); 329 return (1); 330 default: 331 return (-1); 332 } 333 } 334 335 /* 336 * Force remove a user record-level lock. 337 */ 338 339 static int 340 force_unlock(char *username) 341 { 342 TOKENDB_Rec tokenrec; 343 344 if (tokendb_getrec(username, &tokenrec)) 345 return (-1); 346 347 tokenrec.flags &= ~TOKEN_LOCKED; 348 tokenrec.flags &= ~TOKEN_LOGIN; 349 350 if (tokendb_putrec(username, &tokenrec)) 351 return (1); 352 353 return (0); 354 } 355 356 /* 357 * Print a database record according to user a specified format 358 */ 359 360 static void 361 print_record(TOKENDB_Rec *rec, how_t how) 362 { 363 static int count = 0; 364 int i; 365 366 if (rec == NULL) { 367 if ((count & 3) && (how & (TERSE|ONECOL)) == TERSE) 368 printf("\n"); 369 return; 370 } 371 372 if (rec->flags & TOKEN_ENABLED) { 373 if ((how & ENONLY) == 0) 374 return; 375 } else { 376 if ((how & DISONLY) == 0) 377 return; 378 } 379 380 switch (how & (TERSE|ONECOL)) { 381 case 0: 382 case ONECOL: 383 printf("%-16s %-8s", rec->uname, 384 rec->flags & TOKEN_ENABLED ? "enabled" : "disabled"); 385 386 for (i = 1; i; i <<= 1) 387 if (rec->mode & i) 388 printf(" %s", token_getmode(i)); 389 printf("\n"); 390 break; 391 case TERSE: 392 if ((count & 3) == 3) 393 printf("%s\n", rec->uname); 394 else 395 printf("%-16s ", rec->uname); 396 break; 397 case TERSE|ONECOL: 398 printf("%s\n", rec->uname); 399 break; 400 } 401 ++count; 402 } 403