1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <stdio.h> 31 #include <string.h> 32 #include <malloc.h> 33 #include <bsm/devices.h> 34 35 #define MAXINT 0x7fffffff; 36 #ifdef SunOS_CMW 37 extern char *calloc(); 38 #endif 39 40 static struct _dabuff { 41 devalloc_t _NULLDA; 42 FILE *_daf; /* pointer into /etc/security/device_allocate */ 43 devalloc_t _interpdevalloc; 44 char _interpline[BUFSIZ + 1]; 45 char *_DEVALLOC; 46 } *__dabuff; 47 48 #define NULLDA (_da->_NULLDA) 49 #define daf (_da->_daf) 50 #define interpdevalloc (_da->_interpdevalloc) 51 #define interpline (_da->_interpline) 52 #define DEVALLOC (_da->_DEVALLOC) 53 static devalloc_t *interpret(); 54 static int matchname(); 55 56 /* 57 * trim_white(ptr) trims off leading and trailing white space from a NULL 58 * terminated string pointed to by "ptr". The leading white space is skipped 59 * by moving the pointer forward. The trailing white space is removed by 60 * nulling the white space characters. The pointer is returned to the white 61 * string. If the resulting string is null in length then a NULL pointer is 62 * returned. If "ptr" is NULL then a NULL pointer is returned. 63 */ 64 static char * 65 trim_white(ptr) 66 char *ptr; 67 { 68 register char *tptr; 69 register int cnt; 70 if (ptr == NULL) 71 return (NULL); 72 while ((*ptr == ' ') || (*ptr == '\t')) { 73 ptr++; 74 } 75 cnt = strlen(ptr); 76 if (cnt != 0) { 77 tptr = ptr + cnt - 1; 78 while ((*tptr == ' ') || (*tptr == '\t')) { 79 *tptr = '\0'; 80 tptr--; 81 } 82 } 83 if (*ptr == NULL) 84 return (NULL); 85 return (ptr); 86 } 87 88 89 /* 90 * scan string pointed to by pointer "p" 91 * find next colin or end of line. Null it and 92 * return pointer to next char. 93 */ 94 static char * 95 daskip(p) 96 register char *p; 97 { 98 while (*p && *p != ';' && *p != '\n') 99 ++p; 100 if (*p == '\n') 101 *p = '\0'; 102 else if (*p != '\0') 103 *p++ = '\0'; 104 return (p); 105 } 106 107 108 /* 109 * scan string pointed to by pointer "p" 110 * find next colin or end of line. Null it and 111 * return pointer to next char. 112 */ 113 static char * 114 dadskip(p) 115 register char *p; 116 { 117 while (*p && *p != ' ' && *p != '\n') 118 ++p; 119 if (*p != '\0') 120 *p++ = '\0'; 121 return (p); 122 } 123 124 125 /* 126 * _daalloc() allocates common buffers and structures used by the device 127 * allocate library routines. Then returns a pointer to a structure. The 128 * returned pointer will be null if there is an error condition. 129 */ 130 static struct _dabuff * 131 _daalloc() 132 { 133 register struct _dabuff *_da = __dabuff; 134 135 if (_da == 0) { 136 _da = (struct _dabuff *) 137 calloc((size_t)1, sizeof (*__dabuff)); 138 if (_da == 0) 139 return (0); 140 DEVALLOC = "/etc/security/device_allocate"; 141 __dabuff = _da; 142 } 143 return (__dabuff); 144 } 145 146 147 /* 148 * getdaline(buff,len,stream) reads one device allocate line from "stream" into 149 * "buff" on "len" bytes. Continued lines from "stream" are concatinated 150 * into one line in "buff". Comments are removed from "buff". The number of 151 * characters in "buff" is returned. If no characters are read or an err or 152 * occured then "0" is returned 153 */ 154 static int 155 getdaline(buff, len, stream) 156 char *buff; 157 int len; 158 FILE *stream; 159 { 160 register struct _dabuff *_da = _daalloc(); 161 char *cp; 162 char *ccp; 163 int tmpcnt; 164 int charcnt = 0; 165 int fileerr = 0; 166 int contline; 167 if (_da == 0) 168 return (0); 169 do { 170 cp = buff; 171 *cp = NULL; 172 do { 173 if (fgets(cp, len - charcnt, stream) == NULL) { 174 fileerr = 1; 175 break; 176 } 177 ccp = strpbrk(cp, "\\\n"); 178 if (ccp != NULL) { 179 if (*ccp == '\\') 180 contline = 1; 181 else 182 contline = 0; 183 *ccp = NULL; 184 } 185 tmpcnt = strlen(cp); 186 if (tmpcnt != 0) { 187 cp += tmpcnt; 188 charcnt += tmpcnt; 189 } 190 } while ((contline) || (charcnt == 0)); 191 ccp = strpbrk(buff, "#"); 192 if (ccp != NULL) 193 *ccp = NULL; 194 charcnt = strlen(buff); 195 } while ((fileerr == 0) && (charcnt == 0)); 196 if (fileerr) 197 return (0); 198 else 199 return (charcnt); 200 } 201 202 char * 203 getdafield(ptr) 204 char *ptr; 205 { 206 static char *tptr; 207 if (ptr == NULL) 208 ptr = tptr; 209 if (ptr == NULL) 210 return (NULL); 211 tptr = daskip(ptr); 212 ptr = trim_white(ptr); 213 if (ptr == NULL) 214 return (NULL); 215 if (*ptr == NULL) 216 return (NULL); 217 return (ptr); 218 } 219 220 char * 221 getdadfield(ptr) 222 char *ptr; 223 { 224 static char *tptr; 225 if (ptr != NULL) { 226 ptr = trim_white(ptr); 227 } else { 228 ptr = tptr; 229 } 230 if (ptr == NULL) 231 return (NULL); 232 tptr = dadskip(ptr); 233 if (ptr == NULL) 234 return (NULL); 235 if (*ptr == NULL) 236 return (NULL); 237 return (ptr); 238 } 239 240 /* 241 * getdadev(dev) searches from the beginning of the file until a logical 242 * device matching "dev" is found and returns a pointer to the particular 243 * structure in which it was found. If an EOF or an error is encountered on 244 * reading, these functions return a NULL pointer. 245 */ 246 #ifdef NOTDEF 247 devalloc_t * 248 getdadev(name) 249 register char *name; 250 { 251 register struct _dabuff *_da = _daalloc(); 252 devalloc_t *da; 253 char line[BUFSIZ + 1]; 254 255 if (_da == 0) 256 return (0); 257 setdaent(); 258 if (!daf) 259 return ((devalloc_t *)NULL); 260 while (getdaline(line, sizeof (line), daf) != 0) { 261 if ((da = interpret(line)) == NULL) 262 continue; 263 if (matchdev(&da, name)) { 264 enddaent(); 265 return (da); 266 } 267 } 268 enddaent(); 269 return ((devalloc_t *)NULL); 270 } 271 272 273 #endif /* NOTDEF */ 274 275 /* 276 * getdanam(name) searches from the beginning of the file until a audit-name 277 * matching "name" is found and returns a pointer to the particular structure 278 * in which it was found. If an EOF or an error is encountered on reading, 279 * these functions return a NULL pointer. 280 */ 281 devalloc_t * 282 getdanam(name) 283 register char *name; 284 { 285 register struct _dabuff *_da = _daalloc(); 286 devalloc_t *da; 287 char line[BUFSIZ + 1]; 288 289 if (_da == 0) 290 return (0); 291 setdaent(); 292 if (!daf) 293 return ((devalloc_t *)NULL); 294 while (getdaline(line, (int)sizeof (line), daf) != 0) { 295 if ((da = interpret(line)) == NULL) 296 continue; 297 if (matchname(&da, name)) { 298 enddaent(); 299 return (da); 300 } 301 } 302 enddaent(); 303 return ((devalloc_t *)NULL); 304 } 305 306 307 /* 308 * setdaent() essentially rewinds the device_allocate file to the begining. 309 */ 310 311 void 312 setdaent() 313 { 314 register struct _dabuff *_da = _daalloc(); 315 316 if (_da == 0) 317 return; 318 if (daf == NULL) { 319 daf = fopen(DEVALLOC, "r"); 320 } else 321 rewind(daf); 322 } 323 324 325 /* 326 * enddaent() may be called to close the device_allocate file when processing 327 * is complete. 328 */ 329 330 void 331 enddaent() 332 { 333 register struct _dabuff *_da = _daalloc(); 334 335 if (_da == 0) 336 return; 337 if (daf != NULL) { 338 (void) fclose(daf); 339 daf = NULL; 340 } 341 } 342 343 344 /* 345 * setdafile(name) changes the default device_allocate file to "name" thus 346 * allowing alternate device_allocate files to be used. Note: it does not 347 * close the previous file . If this is desired, enddaent should be called 348 * prior to it. 349 */ 350 void 351 setdafile(file) 352 char *file; 353 { 354 register struct _dabuff *_da = _daalloc(); 355 356 if (_da == 0) 357 return; 358 if (daf != NULL) { 359 (void) fclose(daf); 360 daf = NULL; 361 } 362 DEVALLOC = file; 363 } 364 365 366 /* 367 * getdatype(tp) When first called, returns a pointer to the 368 * first devalloc_t structure in the file with device-type matching 369 * "tp"; thereafter, it returns a pointer to the next devalloc_t 370 * structure in the file with device-type matching "tp". 371 * Thus successive calls can be used to search the 372 * entire file for entries having device-type matching "tp". 373 * A null pointer is returned on error. 374 */ 375 devalloc_t * 376 getdatype(tp) 377 char *tp; 378 { 379 register struct _dabuff *_da = _daalloc(); 380 char line1[BUFSIZ + 1]; 381 devalloc_t *da; 382 383 if (_da == 0) 384 return (0); 385 if (daf == NULL && (daf = fopen(DEVALLOC, "r")) == NULL) { 386 return (NULL); 387 } 388 do { 389 if (getdaline(line1, (int)sizeof (line1), daf) == 0) 390 return (NULL); 391 392 if ((da = interpret(line1)) == NULL) 393 return (NULL); 394 } while (strcmp(tp, da->da_devtype) != 0); 395 return (da); 396 } 397 398 399 /* 400 * getdaent() When first called, returns a pointer to the first devalloc_t 401 * structure in the file; thereafter, it returns a pointer to the next 402 * devalloc_t structure in the file. Thus successive calls can be used to 403 * search the entire file. A null pointer is returned on error. 404 */ 405 devalloc_t * 406 getdaent() 407 { 408 register struct _dabuff *_da = _daalloc(); 409 char line1[BUFSIZ + 1]; 410 devalloc_t *da; 411 412 if (_da == 0) 413 return (0); 414 if (daf == NULL && (daf = fopen(DEVALLOC, "r")) == NULL) { 415 return (NULL); 416 } 417 if (getdaline(line1, (int)sizeof (line1), daf) == 0) 418 return (NULL); 419 420 if ((da = interpret(line1)) == NULL) 421 return (NULL); 422 return (da); 423 } 424 425 426 /* 427 * matchdev(dap,dev) The dev_list in the structure pointed to by "dap" is 428 * searched for string "dev". If a match occures then a "1" is returned 429 * otherwise a "0" is returned. 430 */ 431 #ifdef NOTDEF 432 static 433 matchdev(dap, dev) 434 devalloc_t **dap; 435 char *dev; 436 { 437 register struct _dabuff *_da = _daalloc(); 438 devalloc_t *da = *dap; 439 char tmpdev[BUFSIZ + 1]; 440 int charcnt; 441 int tmpcnt; 442 char *cp; 443 char *tcp; 444 char *last; 445 446 charcnt = strlen(dev); 447 if (_da == 0) 448 return (0); 449 if (da->da_devlist == NULL) 450 return (0); 451 (void) strcpy(tmpdev, da->da_devlist); 452 tcp = tmpdev; 453 while ((cp = strtok_r(tcp, " ", &last)) != NULL) { 454 tcp = NULL; 455 tmpcnt = strlen(cp); 456 if (tmpcnt != charcnt) 457 continue; 458 if (strcmp(cp, dev) == 0) 459 return (1); 460 } 461 return (0); 462 } 463 464 #endif /* NOTDEF */ 465 /* 466 * matchname(dap,name) The audit-name in the structure pointed to by "dap" is 467 * searched for string "name". If a match occures then a "1" is returned 468 * otherwise a "0" is returned. 469 */ 470 static int 471 matchname(dap, name) 472 devalloc_t **dap; 473 char *name; 474 { 475 register struct _dabuff *_da = _daalloc(); 476 devalloc_t *da = *dap; 477 478 if (_da == 0) 479 return (0); 480 if (da->da_devname == NULL) 481 return (0); 482 if (strlen(da->da_devname) != strlen(name)) 483 return (0); 484 if (strcmp(da->da_devname, name) == 0) 485 return (1); 486 return (0); 487 } 488 489 490 /* 491 * interpret(val) string "val" is parsed and the pointers in a devalloc_t 492 * structure are initialized to point to fields in "val". A pointer to this 493 * structure is returned. 494 */ 495 static devalloc_t * 496 interpret(val) 497 char *val; 498 { 499 register struct _dabuff *_da = _daalloc(); 500 501 if (_da == 0) 502 return (0); 503 (void) strcpy(interpline, val); 504 interpdevalloc.da_devname = getdafield(interpline); 505 interpdevalloc.da_devtype = getdafield((char *)NULL); 506 interpdevalloc.da_devmin = getdafield((char *)NULL); 507 interpdevalloc.da_devmax = getdafield((char *)NULL); 508 interpdevalloc.da_devauth = getdafield((char *)NULL); 509 interpdevalloc.da_devexec = getdafield((char *)NULL); 510 511 return (&interpdevalloc); 512 } 513