Print this page
NEX-13644 File access audit logging
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/auditreduce/option.c
+++ new/usr/src/cmd/auditreduce/option.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 + *
25 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
24 26 */
25 27
26 28 /*
27 29 * Command line option processing for auditreduce.
28 30 * The entry point is process_options(), which is called by main().
29 31 * Process_options() is the only function visible outside this module.
30 32 */
31 33
32 34 #include <locale.h>
33 35 #include <sys/zone.h> /* for max zonename length */
34 36 #include "auditr.h"
35 37
36 38 /*
37 39 * Object entry.
38 40 * Maps object strings specified on the command line to a flag
39 41 * used when searching by object type.
40 42 */
41 43
42 44 struct obj_ent {
43 45 char *obj_str; /* string specified on the command line */
44 46 int obj_flag; /* flag used when searching */
45 47 };
46 48
47 49 typedef struct obj_ent obj_ent_t;
48 50
49 51 /*
50 52 * Supports searches by object type.
51 53 */
52 54 static obj_ent_t obj_tbl[] = {
53 55 { "file", OBJ_PATH },
54 56 { "filegroup", OBJ_FGROUP },
55 57 { "fileowner", OBJ_FOWNER },
56 58 { "fmri", OBJ_FMRI },
57 59 { "lp", OBJ_LP },
58 60 { "msgqid", OBJ_MSG },
59 61 { "msgqgroup", OBJ_MSGGROUP },
60 62 { "msgqowner", OBJ_MSGOWNER },
61 63 { "path", OBJ_PATH },
|
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
62 64 { "pid", OBJ_PROC },
63 65 { "procgroup", OBJ_PGROUP },
64 66 { "procowner", OBJ_POWNER },
65 67 { "semid", OBJ_SEM },
66 68 { "semgroup", OBJ_SEMGROUP },
67 69 { "semowner", OBJ_SEMOWNER },
68 70 { "shmid", OBJ_SHM },
69 71 { "shmgroup", OBJ_SHMGROUP },
70 72 { "shmowner", OBJ_SHMOWNER },
71 73 { "sock", OBJ_SOCK },
72 - { "user", OBJ_USER } };
74 + { "user", OBJ_USER },
75 + { "wsid", OBJ_WSID } };
73 76
74 77 extern int derive_date(char *, struct tm *);
75 78 extern int parse_time(char *, int);
76 79 extern char *re_comp2(char *);
77 80 extern time_t tm_to_secs(struct tm *);
78 81
79 82 static int a_isnum(char *, int);
80 83 static int check_file(audit_fcb_t *, int);
81 84 static int gather_dir(char *);
82 85 static audit_pcb_t *get_next_pcb(char *);
83 86 static obj_ent_t *obj_lkup(char *);
84 87 static int proc_class(char *);
85 88 static int proc_date(char *, int);
86 89 static int proc_file(char *, int);
87 90 static int process_fileopt(int, char *argv[], int);
88 91 static int proc_group(char *, gid_t *);
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
89 92 static int proc_id(char *, int);
90 93 static int proc_object(char *);
91 94 static void proc_pcb(audit_pcb_t *, char *, int);
92 95 static int proc_label(char *);
93 96 static int proc_subject(char *);
94 97 static int proc_sid(char *);
95 98 static int proc_type(char *);
96 99 static int proc_user(char *, uid_t *);
97 100 static int proc_zonename(char *);
98 101 static int proc_fmri(char *);
102 +static int proc_wsid(char *);
99 103
100 104 /*
101 105 * .func process_options - process command line options.
102 106 * .desc Process the user's command line options. These are of two types:
103 107 * single letter flags that are denoted by '-', and filenames. Some
104 108 * of the flags have arguments. Getopt() is used to get the flags.
105 109 * When this is done it calls process_fileopt() to handle any filenames
106 110 * that were there.
107 111 * .call ret = process_options(argc, argv).
108 112 * .arg argc - the original value.
109 113 * .arg argv - the original value.
110 114 * .ret 0 - no errors detected.
111 115 * .ret -1 - command line error detected (message already printed).
112 116 */
113 117 int
114 118 process_options(int argc, char **argv)
115 119 {
116 120 int opt;
|
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
117 121 int error = FALSE;
118 122 int error_combo = FALSE;
119 123 extern int optind; /* in getopt() */
120 124 extern char *optarg; /* in getopt() - holds arg to flag */
121 125
122 126 static char *options = "ACD:M:NQR:S:VO:"
123 127 "a:b:c:d:e:g:j:l:m:o:r:s:t:u:z:";
124 128
125 129 error_str = gettext("general error");
126 130
131 + wsid = NULL;
127 132 zonename = NULL;
128 133 /*
129 134 * Big switch to process the flags.
130 135 * Start_over: is for handling the '-' for standard input. Getopt()
131 136 * doesn't recognize it.
132 137 */
133 138 start_over:
134 139 while ((opt = getopt(argc, argv, options)) != EOF) {
135 140 switch (opt) {
136 141 case 'A': /* all records from the files */
137 142 f_all = TRUE;
138 143 break;
139 144 case 'C': /* process only completed files */
140 145 f_complete = TRUE;
141 146 break;
142 147 case 'D': /* delete the files when done */
143 148 /* force 'A' 'C' 'O' to be active */
144 149 f_all = f_complete = TRUE;
145 150 f_outfile = optarg;
146 151 f_delete = TRUE;
147 152 break;
148 153 case 'M': /* only files from a certain machine */
149 154 f_machine = optarg;
150 155 break;
151 156 case 'N': /* new object selection mode */
152 157 new_mode = TRUE;
153 158 break;
154 159 case 'Q': /* no file error reporting */
155 160 f_quiet = TRUE;
156 161 break;
157 162 case 'R': /* from specified root */
158 163 f_root = optarg;
159 164 break;
160 165 case 'S': /* from specified server */
161 166 f_server = optarg;
162 167 break;
163 168 case 'V': /* list all files as they are opened */
164 169 f_verbose = TRUE;
165 170 break;
166 171 case 'O': /* write to outfile */
167 172 f_outfile = optarg;
168 173 break;
169 174 case 'a': /* after 'date' */
170 175 case 'b': /* before 'date' */
171 176 case 'd': /* from 'day' */
172 177 if (proc_date(optarg, opt))
173 178 error = TRUE;
174 179 break;
175 180 case 'j': /* subject */
176 181 if (proc_subject(optarg))
177 182 error = TRUE;
178 183 break;
179 184 case 'm': /* message 'type' */
180 185 if (proc_type(optarg))
181 186 error = TRUE;
182 187 break;
183 188 case 'o': /* object type */
184 189 if (proc_object(optarg))
185 190 error = TRUE;
186 191 break;
187 192 case 'c': /* message class */
188 193 if (proc_class(optarg))
189 194 error = TRUE;
190 195 break;
191 196 case 'u': /* form audit user */
192 197 case 'e': /* form effective user */
193 198 case 'r': /* form real user */
194 199 case 'f': /* form effective group */
195 200 case 'g': /* form real group */
196 201 if (proc_id(optarg, opt))
197 202 error = TRUE;
198 203 break;
199 204 case 'l': /* TX label range */
200 205 if (!is_system_labeled()) {
201 206 (void) fprintf(stderr,
202 207 gettext("%s option 'l' requires "
203 208 "Trusted Extensions.\n"), ar);
204 209 return (-1);
205 210 }
206 211 if (proc_label(optarg))
207 212 error = TRUE;
208 213 break;
209 214 case 's': /* session ID */
210 215 if (proc_sid(optarg))
211 216 error = TRUE;
212 217 break;
213 218 case 'z': /* zone name */
214 219 if (proc_zonename(optarg))
215 220 error = TRUE;
216 221 break;
217 222 case 't': /* termial ID reserved for later */
218 223 default:
219 224 return (-1);
220 225 }
221 226 if (error) {
222 227 (void) fprintf(stderr,
223 228 gettext("%s command line error - %s.\n"),
224 229 ar, error_str);
225 230 return (-1);
226 231 }
227 232 }
228 233 /* catch '-' option for stdin processing - getopt() won't see it */
229 234 if (optind < argc) {
230 235 if (argv[optind][0] == '-' && argv[optind][1] == '\0') {
231 236 optind++;
232 237 f_stdin = TRUE;
233 238 goto start_over;
234 239 }
235 240 }
236 241 /*
237 242 * Give a default value for 'b' option if not specified.
238 243 */
239 244 if (m_before == 0)
240 245 m_before = MAXLONG; /* forever */
241 246 /*
242 247 * Validate combinations of options.
243 248 * The following are done:
244 249 * 1. Can't have 'M' or 'S' or 'R' with filenames.
245 250 * 2. Can't have an after ('a') time after a before ('b') time.
246 251 * 3. Delete ('D') must have 'C' and 'A' and 'O' with it.
247 252 * 4. Input from stdin ('-') can't have filenames too.
248 253 */
249 254 if ((f_machine || f_server || f_root) && (argc != optind)) {
250 255 error_str = gettext(
251 256 "no filenames allowed with 'M' or 'S' or 'R' options");
252 257 error_combo = TRUE;
253 258 }
254 259 if (m_after >= m_before) {
255 260 error_str =
256 261 gettext("'a' parameter must be before 'b' parameter");
257 262 error_combo = TRUE;
258 263 }
259 264 if (f_delete &&
260 265 (!f_complete || !f_all || !f_outfile)) {
261 266 error_str = gettext(
262 267 "'C', 'A', and 'O' must be specified with 'D'");
263 268 error_combo = TRUE;
264 269 }
265 270 if (f_stdin && (argc != optind)) {
266 271 error_str = gettext("no filenames allowed with '-' option");
267 272 error_combo = TRUE;
268 273 }
269 274 /*
270 275 * If error with option combos then print message and exit.
271 276 * If there was an error with just an option then exit.
272 277 */
273 278 if (error_combo) {
274 279 (void) fprintf(stderr,
275 280 gettext("%s command line error - %s.\n"), ar, error_str);
276 281 return (-1);
277 282 }
278 283 if (f_root == NULL)
279 284 f_root = "/etc/security/audit";
280 285 /*
281 286 * Now handle any filenames included in the command line.
282 287 */
283 288 return (process_fileopt(argc, argv, optind));
284 289 }
285 290
286 291 int
287 292 proc_subject(char *optarg)
288 293 {
289 294 if (flags & M_SUBJECT) {
290 295 error_str = gettext("'j' option specified multiple times");
291 296 return (-1);
292 297 }
293 298 flags |= M_SUBJECT;
294 299 subj_id = atol(optarg);
295 300 return (0);
296 301 }
297 302
298 303 int
299 304 proc_sid(char *optarg)
300 305 {
301 306 if (flags & M_SID) {
302 307 error_str = gettext("'s' option specified multiple times");
303 308 return (-1);
304 309 }
305 310 flags |= M_SID;
306 311 m_sid = (au_asid_t)atol(optarg);
307 312 return (0);
308 313 }
309 314
310 315 int
311 316 proc_object(char *optarg)
312 317 {
313 318 char *obj_str;
314 319 char *obj_val;
315 320 char *obj_arg;
316 321 int err;
317 322
318 323 obj_ent_t *oep;
319 324 struct hostent *he;
320 325
321 326 if (flags & M_OBJECT) {
322 327 error_str = gettext("'o' option specified multiple times");
323 328 return (-1);
324 329 }
325 330 flags |= M_OBJECT;
326 331 if ((obj_arg = strdup(optarg)) == (char *)0)
327 332 return (-1);
328 333 if ((obj_str = strtok(optarg, "=")) == (char *)0 ||
329 334 (oep = obj_lkup(obj_str)) == (obj_ent_t *)0 ||
330 335 (obj_val = strtok((char *)0, "=")) == (char *)0) {
331 336 (void) sprintf(errbuf, gettext("invalid object arg (%s)"),
332 337 obj_arg);
333 338 error_str = errbuf;
334 339 return (-1);
335 340 }
336 341
337 342 obj_flag = oep->obj_flag;
338 343
339 344 switch (obj_flag) {
340 345 case OBJ_PATH:
341 346 if ((error_str = re_comp2(obj_val)) != (char *)NULL) {
342 347 return (-1);
343 348 }
344 349 return (0);
345 350 case OBJ_SOCK:
346 351 if (!a_isnum(obj_val, TRUE)) {
347 352 obj_id = atol(obj_val);
348 353 socket_flag = SOCKFLG_PORT;
349 354 return (0);
350 355 }
351 356 if (*obj_val == '0') {
352 357 (void) sscanf(obj_val, "%x", (uint_t *)&obj_id);
353 358 socket_flag = SOCKFLG_PORT;
354 359 return (0);
355 360 }
356 361
357 362 he = getipnodebyname((const void *)obj_val, AF_INET6, 0, &err);
358 363 if (he == 0) {
359 364 he = getipnodebyname((const void *)obj_val, AF_INET,
360 365 0, &err);
361 366 if (he == 0) {
362 367 (void) sprintf(errbuf,
363 368 gettext("invalid machine name (%s)"),
364 369 obj_val);
365 370 error_str = errbuf;
366 371 return (-1);
367 372 }
368 373 }
369 374
370 375 if (he->h_addrtype == AF_INET6) {
371 376 /* LINTED */
372 377 if (IN6_IS_ADDR_V4MAPPED(
373 378 (in6_addr_t *)he->h_addr_list[0])) {
374 379 /* address is IPv4 (32 bits) */
375 380 (void) memcpy(&obj_id,
376 381 he->h_addr_list[0] + 12, 4);
377 382 ip_type = AU_IPv4;
378 383 } else {
379 384 (void) memcpy(ip_ipv6, he->h_addr_list[0], 16);
380 385 ip_type = AU_IPv6;
381 386 }
382 387 } else {
383 388 /* address is IPv4 (32 bits) */
384 389 (void) memcpy(&obj_id, he->h_addr_list[0], 4);
385 390 ip_type = AU_IPv4;
386 391 }
387 392
388 393 freehostent(he);
389 394 socket_flag = SOCKFLG_MACHINE;
390 395 return (0);
391 396 case OBJ_MSG:
392 397 case OBJ_SEM:
393 398 case OBJ_SHM:
394 399 case OBJ_PROC:
395 400 obj_id = atol(obj_val);
396 401 return (0);
397 402 case OBJ_FGROUP:
398 403 case OBJ_MSGGROUP:
399 404 case OBJ_SEMGROUP:
400 405 case OBJ_SHMGROUP:
401 406 case OBJ_PGROUP:
402 407 return (proc_group(obj_val, &obj_group));
|
↓ open down ↓ |
266 lines elided |
↑ open up ↑ |
403 408 case OBJ_FOWNER:
404 409 case OBJ_MSGOWNER:
405 410 case OBJ_SEMOWNER:
406 411 case OBJ_SHMOWNER:
407 412 case OBJ_POWNER:
408 413 return (proc_user(obj_val, &obj_owner));
409 414 case OBJ_FMRI:
410 415 return (proc_fmri(obj_val));
411 416 case OBJ_USER:
412 417 return (proc_user(obj_val, &obj_user));
418 + case OBJ_WSID:
419 + return (proc_wsid(obj_val));
413 420 case OBJ_LP: /* lp objects have not yet been defined */
414 421 default: /* impossible */
415 422 (void) sprintf(errbuf, gettext("invalid object type (%s)"),
416 423 obj_str);
417 424 error_str = errbuf;
418 425 return (-1);
419 426 } /* switch */
420 427 /*NOTREACHED*/
421 428 }
422 429
423 430
424 431 obj_ent_t *
425 432 obj_lkup(char *obj_str)
426 433 {
427 434 int i;
428 435
429 436 for (i = 0; i < sizeof (obj_tbl) / sizeof (obj_ent_t); i++)
430 437 if (strcmp(obj_str, obj_tbl[i].obj_str) == 0)
431 438 return (&obj_tbl[i]);
432 439
433 440 /* not in table */
434 441 return (NULL);
435 442 }
436 443
437 444
438 445 /*
439 446 * .func proc_type - process record type.
440 447 * .desc Process a record type. It is either as a number or a mnemonic.
441 448 * .call ret = proc_type(optstr).
442 449 * .arg optstr - ptr to name or number.
443 450 * .ret 0 - no errors detected.
444 451 * .ret -1 - error detected (error_str contains description).
445 452 */
446 453 int
447 454 proc_type(char *optstr)
448 455 {
449 456 struct au_event_ent *aep;
450 457
451 458 /*
452 459 * Either a number or a name.
453 460 */
454 461
455 462 if (flags & M_TYPE) {
456 463 error_str = gettext("'m' option specified multiple times");
457 464 return (-1);
458 465 }
459 466 flags |= M_TYPE;
460 467 m_type = 0;
461 468 if (a_isnum(optstr, TRUE)) {
462 469 if ((aep = getauevnam(optstr)) != NULL)
463 470 m_type = aep->ae_number;
464 471 } else {
465 472 if ((aep = getauevnum((au_event_t)atoi(optstr))) !=
466 473 (struct au_event_ent *)NULL)
467 474 m_type = aep->ae_number;
468 475 }
469 476 if ((m_type == 0)) {
470 477 (void) sprintf(errbuf, gettext("invalid event (%s)"), optstr);
471 478 error_str = errbuf;
472 479 return (-1);
473 480 }
474 481 return (0);
475 482 }
476 483
477 484
478 485 /*
479 486 * .func a_isnum - is it a number?
480 487 * .desc Determine if a string is a number or a name.
481 488 * A number may have a leading '+' or '-', but then must be
482 489 * all digits.
483 490 * .call ret = a_isnum(str).
484 491 * .arg str - ptr to the string.
485 492 * .arg leading - TRUE if leading '+-' allowed.
486 493 * .ret 0 - is a number.
487 494 * .ret 1 - is not a number.
488 495 */
489 496 int
490 497 a_isnum(char *str, int leading)
491 498 {
492 499 char *strs;
493 500
494 501 if ((leading == TRUE) && (*str == '-' || *str == '+'))
495 502 strs = str + 1;
496 503 else
497 504 strs = str;
498 505
499 506 if (strlen(strs) == strspn(strs, "0123456789"))
500 507 return (0);
501 508 else
502 509 return (1);
503 510 }
504 511
505 512
506 513 /*
507 514 * .func proc_id - process user/group id's/
508 515 * .desc Process either a user number/name or group number/name.
509 516 * For names check to see if the name is active in the system
510 517 * to derive the number. If it is not active then fail. For a number
511 518 * also check to see if it is active, but only print a warning if it
512 519 * is not. An administrator may be looking at activity of a 'phantom'
513 520 * user.
514 521 * .call ret = proc_id(optstr, opt).
515 522 * .arg optstr - ptr to name or number.
516 523 * .arg opt - 'u' - audit user, 'e' - effective user, 'r' - real user,
517 524 * 'g' - group, 'f' - effective group.
518 525 * .ret 0 - no errors detected.
519 526 * .ret -1 - error detected (error_str contains description).
520 527 */
521 528 int
522 529 proc_id(char *optstr, int opt)
523 530 {
524 531 switch (opt) {
525 532 case 'e': /* effective user id */
526 533 if (flags & M_USERE) {
527 534 error_str = gettext(
528 535 "'e' option specified multiple times");
529 536 return (-1);
530 537 }
531 538 flags |= M_USERE;
532 539 return (proc_user(optstr, &m_usere));
533 540 case 'f': /* effective group id */
534 541 if (flags & M_GROUPE) {
535 542 error_str = gettext(
536 543 "'f' option specified multiple times");
537 544 return (-1);
538 545 }
539 546 flags |= M_GROUPE;
540 547 return (proc_group(optstr, &m_groupe));
541 548 case 'r': /* real user id */
542 549 if (flags & M_USERR) {
543 550 error_str = gettext(
544 551 "'r' option specified multiple times");
545 552 return (-1);
546 553 }
547 554 flags |= M_USERR;
548 555 return (proc_user(optstr, &m_userr));
549 556 case 'u': /* audit user id */
550 557 if (flags & M_USERA) {
551 558 error_str = gettext(
552 559 "'u' option specified multiple times");
553 560 return (-1);
554 561 }
555 562 flags |= M_USERA;
556 563 return (proc_user(optstr, &m_usera));
557 564 case 'g': /* real group id */
558 565 if (flags & M_GROUPR) {
559 566 error_str = gettext(
560 567 "'g' option specified multiple times");
561 568 return (-1);
562 569 }
563 570 flags |= M_GROUPR;
564 571 return (proc_group(optstr, &m_groupr));
565 572 default: /* impossible */
566 573 (void) sprintf(errbuf, gettext("'%c' unknown option"), opt);
567 574 error_str = errbuf;
568 575 return (-1);
569 576 }
570 577 /*NOTREACHED*/
571 578 }
572 579
573 580
574 581 int
575 582 proc_group(char *optstr, gid_t *gid)
576 583 {
577 584 struct group *grp;
578 585
579 586 if ((grp = getgrnam(optstr)) == NULL) {
580 587 if (!a_isnum(optstr, TRUE)) {
581 588 *gid = (gid_t)atoi(optstr);
582 589 return (0);
583 590 }
584 591 (void) sprintf(errbuf, gettext("group name invalid (%s)"),
585 592 optstr);
586 593 error_str = errbuf;
587 594 return (-1);
588 595 }
589 596 *gid = grp->gr_gid;
590 597 return (0);
591 598 }
592 599
593 600
594 601 int
595 602 proc_user(char *optstr, uid_t *uid)
596 603 {
597 604 struct passwd *usr;
598 605
599 606 if ((usr = getpwnam(optstr)) == NULL) {
600 607 if (!a_isnum(optstr, TRUE)) {
601 608 *uid = (uid_t)atoi(optstr);
602 609 return (0);
603 610 }
604 611 (void) sprintf(errbuf, gettext("user name invalid (%s)"),
605 612 optstr);
606 613 error_str = errbuf;
607 614 return (-1);
608 615 }
609 616 *uid = usr->pw_uid;
610 617 return (0);
611 618 }
612 619
613 620
614 621 /*
615 622 * .func proc_date - process date argument.
616 623 * .desc Handle a date/time argument. See if the user has erred in combining
617 624 * the types of date arguments. Then parse the string and check for
618 625 * validity of each part.
619 626 * .call ret = proc_date(optstr, opt).
620 627 * .arg optstr - ptr to date/time string.
621 628 * .arg opt - 'd' for day, 'a' for after, or 'b' for before.
622 629 * .ret 0 - no errors detected.
623 630 * .ret -1 - errors detected (error_str knows what it is).
624 631 */
625 632 int
626 633 proc_date(char *optstr, int opt)
627 634 {
628 635 static int m_day = FALSE;
629 636
630 637 if (opt == 'd') {
631 638 if (m_day == TRUE) {
632 639 error_str = gettext(
633 640 "'d' option may not be used with 'a' or 'b'");
634 641 return (-1);
635 642 }
636 643 m_day = TRUE;
637 644 }
638 645 if ((opt == 'd') && (m_before || m_after)) {
639 646 error_str = gettext(
640 647 "'d' option may not be used with 'a' or 'b'");
641 648 return (-1);
642 649 }
643 650 if ((opt == 'a' || opt == 'b') && m_day) {
644 651 error_str = gettext(
645 652 "'a' or 'b' option may not be used with 'd'");
646 653 return (-1);
647 654 }
648 655 if ((opt == 'a') && (m_after != 0)) {
649 656 error_str = gettext("'a' option specified multiple times");
650 657 return (-1);
651 658 }
652 659 if ((opt == 'b') && (m_before != 0)) {
653 660 error_str = gettext("'b' option specified multiple times");
654 661 return (-1);
655 662 }
656 663 if (parse_time(optstr, opt))
657 664 return (-1);
658 665 return (0);
659 666 }
660 667
661 668
662 669 /*
663 670 * .func proc_class - process message class argument.
664 671 * .desc Process class type and see if it is for real.
665 672 * .call ret = proc_class(optstr).
666 673 * .arg optstr - ptr to class.
667 674 * .ret 0 - class has class.
668 675 * .ret -1 - class in no good.
669 676 */
670 677 int
671 678 proc_class(char *optstr)
672 679 {
673 680 if (flags & M_CLASS) {
674 681 error_str = gettext("'c' option specified multiple times");
675 682 return (-1);
676 683 }
677 684 flags |= M_CLASS;
678 685
679 686 if (getauditflagsbin(optstr, &mask) != 0) {
680 687 (void) sprintf(errbuf, gettext("unknown class (%s)"), optstr);
681 688 error_str = errbuf;
682 689 return (-1);
683 690 }
684 691
685 692 if (mask.am_success != mask.am_failure) {
686 693 flags |= M_SORF;
687 694 }
688 695
689 696 return (0);
690 697 }
691 698
692 699
693 700 /*
694 701 * .func process_fileopt - process command line file options.
695 702 * .desc Process the command line file options and gather the specified files
696 703 * together in file groups based upon file name suffix. The user can
697 704 * specify files explicitly on the command line or via a directory.
698 705 * This is called after the command line flags are processed (as
699 706 * denoted by '-').
700 707 * .call ret = process_fileopt(argc, argv, optindex).
701 708 * .arg argc - current value of argc.
702 709 * .arg argv - current value of argv.
703 710 * .arg optindex- current index into argv (as setup by getopt()).
704 711 * .ret 0 - no errors detected.
705 712 * .ret -1 - error detected (message already printed).
706 713 */
707 714 int
708 715 process_fileopt(int argc, char **argv, int optindex)
709 716 {
710 717 int f_mode = FM_ALLDIR;
711 718 char f_dr[MAXNAMLEN+1];
712 719 char *f_dir = f_dr;
713 720 char *fname;
714 721 static char *std = "standard input";
715 722 audit_fcb_t *fcb;
716 723 DIR * dirp;
717 724 struct dirent *dp;
718 725 audit_pcb_t *pcb;
719 726
720 727 /*
721 728 * Take input from stdin, not any files.
722 729 * Use a single fcb to do this.
723 730 */
724 731 if (f_stdin) {
725 732 fcb = (audit_fcb_t *)a_calloc(1, sizeof (*fcb) + strlen(std));
726 733 (void) strcpy(fcb->fcb_file, std);
727 734 fcb->fcb_suffix = fcb->fcb_name = fcb->fcb_file;
728 735 fcb->fcb_next = NULL;
729 736 fcb->fcb_start = 0;
730 737 fcb->fcb_end = MAXLONG; /* forever */
731 738 if ((pcb = get_next_pcb((char *)NULL)) == (audit_pcb_t *)NULL)
732 739 return (-1);
733 740 pcb->pcb_suffix = fcb->fcb_file;
734 741 pcb->pcb_dfirst = pcb->pcb_first = fcb; /* one-item list */
735 742 pcb->pcb_dlast = pcb->pcb_last = fcb;
736 743 pcb->pcb_cur = fcb;
737 744 }
738 745 /*
739 746 * No files specified on the command line.
740 747 * Process a directory of files or subdirectories.
741 748 */
742 749 else if (argc == optindex) {
743 750 /*
744 751 * A specific server directory was requested.
745 752 */
746 753 if (f_server) {
747 754 if (strchr(f_server, '/')) { /* given full path */
748 755 f_dir = f_server;
749 756 f_mode = FM_ALLFILE; /* all files here */
750 757 } else { /* directory off audit root */
751 758 f_dir[0] = '\0';
752 759 (void) strcat(f_dir, f_root);
753 760 (void) strcat(f_dir, "/");
754 761 (void) strcat(f_dir, f_server);
755 762 f_mode = FM_ALLFILE;
756 763 }
757 764 }
758 765 /*
759 766 * Gather all of the files in the directory 'f_dir'.
760 767 */
761 768 if (f_mode == FM_ALLFILE) {
762 769 if (gather_dir(f_dir)) { /* get those files together */
763 770 return (-1);
764 771 }
765 772 } else {
766 773 /*
767 774 * Gather all of the files in all of the
768 775 * directories in 'f_root'.
769 776 */
770 777 if ((dirp = opendir(f_root)) == NULL) {
771 778 (void) sprintf(errbuf, gettext(
772 779 "%s can't open directory %s"), ar, f_root);
773 780 perror(errbuf);
774 781 return (-1);
775 782 }
776 783 /* read the directory and process all of the subs */
777 784 for (dp = readdir(dirp);
778 785 dp != NULL; dp = readdir(dirp)) {
779 786 if (dp->d_name[0] == '.')
780 787 continue;
781 788 f_dir[0] = '\0';
782 789 (void) strcat(f_dir, f_root);
783 790 (void) strcat(f_dir, "/");
784 791 (void) strcat(f_dir, dp->d_name);
785 792 if (gather_dir(f_dir)) /* process a sub */
786 793 return (-1);
787 794 }
788 795 (void) closedir(dirp);
789 796 }
790 797 } else {
791 798 /*
792 799 * User specified filenames on the comm and line.
793 800 */
794 801 f_cmdline = TRUE;
795 802 for (; optindex < argc; optindex++) {
796 803 fname = argv[optindex]; /* get a filename */
797 804 if (proc_file(fname, FALSE))
798 805 return (-1);
799 806 }
800 807 }
801 808 return (0);
802 809 }
803 810
804 811
805 812 /*
806 813 * .func gather_dir - gather a directory's files together.
807 814 * .desc Process all of the files in a specific directory. The files may
808 815 * be checked for adherence to the file name form at.
809 816 * If the directory can't be opened that is ok - just print
810 817 * a message and continue.
811 818 * .call ret = gather_dir(dir).
812 819 * .arg dir - ptr to full pathname of directory.
813 820 * .ret 0 - no errors detected.
814 821 * .ret -1 - error detected (message already printed).
815 822 */
816 823 int
817 824 gather_dir(char *dir)
818 825 {
819 826 char dname[MAXNAMLEN+1];
820 827 char fname[MAXNAMLEN+1];
821 828 DIR * dirp;
822 829 struct dirent *dp;
823 830
824 831 (void) snprintf(dname, sizeof (dname), "%s/files", dir);
825 832
826 833 if ((dirp = opendir(dname)) == NULL) {
827 834 if (errno != ENOTDIR) {
828 835 (void) sprintf(errbuf,
829 836 gettext("%s can't open directory - %s"), ar, dname);
830 837 perror(errbuf);
831 838 }
832 839 return (0);
833 840 }
834 841 for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
835 842 if (dp->d_name[0] == '.') /* can't see hidden files */
836 843 continue;
837 844 fname[0] = '\0';
838 845 (void) strcat(fname, dname); /* create pathname of file */
839 846 (void) strcat(fname, "/");
840 847 (void) strcat(fname, dp->d_name);
841 848 if (proc_file(fname, TRUE))
842 849 return (-1);
843 850 }
844 851 (void) closedir(dirp);
845 852 return (0);
846 853 }
847 854
848 855
849 856 /*
850 857 * .func proc_file - process a single candidate file.
851 858 * .desc Check out a file to see if it should be used in the merge.
852 859 * This includes checking the name (mode is TRUE) against the
853 860 * file format, checking access rights to the file, and thence
854 861 * getting and fcb and installing the fcb into the correct pcb.
855 862 * If the file fails then the fcb is not installed into a pcb
856 863 * and the file dissapears from view.
857 864 * .call proc_file(fname, mode).
858 865 * .arg fname - ptr to full pathna me of file.
859 866 * .arg mode - TRUE if checking adherence to file name format.
860 867 * .ret 0 - no fatal errors detected.
861 868 * .ret -1 - fatal error detected - quit altogether
862 869 * (message already printed).
863 870 */
864 871 int
865 872 proc_file(char *fname, int mode)
866 873 {
867 874 int reject = FALSE;
868 875 size_t len;
869 876 struct stat stat_buf;
870 877 audit_fcb_t *fcb, *fcbp, *fcbprev;
871 878 audit_pcb_t *pcb;
872 879
873 880 /*
874 881 * See if it is a weird file like a directory or
875 882 * character special (around here?).
876 883 */
877 884 if (stat(fname, &stat_buf)) {
878 885 return (0);
879 886 }
880 887 if (!S_ISREG(stat_buf.st_mode))
881 888 return (0);
882 889 /*
883 890 * Allocate a new fcb to hold fcb and full filename.
884 891 */
885 892 len = sizeof (audit_fcb_t) + strlen(fname);
886 893 fcb = (audit_fcb_t *)a_calloc(1, len);
887 894 (void) strcpy(fcb->fcb_file, fname);
888 895 if (check_file(fcb, mode)) { /* check file name */
889 896 if (!f_quiet) {
890 897 (void) fprintf(stderr, "%s %s:\n %s.\n", ar,
891 898 error_str, fname);
892 899 }
893 900 reject = TRUE;
894 901 } else {
895 902 /*
896 903 * Check against file criteria.
897 904 * Check finish-time here, and start-time later on
898 905 * while processing.
899 906 * This is because the start time on a file can be after
900 907 * the first record(s).
901 908 */
902 909 if (f_complete && (fcb->fcb_flags & FF_NOTTERM) && !f_cmdline)
903 910 reject = TRUE;
904 911 if (!f_all && (fcb->fcb_end < m_after))
905 912 reject = TRUE;
906 913 if (f_machine) {
907 914 if (strlen(fcb->fcb_suffix) != strlen(f_machine) ||
908 915 (strcmp(fcb->fcb_suffix, f_machine) != 0)) {
909 916 reject = TRUE;
910 917 }
911 918 }
912 919 }
913 920 if (reject == FALSE) {
914 921 filenum++; /* count of total files to be processed */
915 922 fcb->fcb_next = NULL;
916 923 if ((pcb = get_next_pcb(fcb->fcb_suffix)) == NULL) {
917 924 return (-1);
918 925 }
919 926 /* Place FCB into the PCB in order - oldest first. */
920 927 fcbp = pcb->pcb_first;
921 928 fcbprev = NULL;
922 929 while (fcbp != NULL) {
923 930 if (fcb->fcb_start < fcbp->fcb_start) {
924 931 if (fcbprev)
925 932 fcbprev->fcb_next = fcb;
926 933 else
927 934 pcb->pcb_dfirst = pcb->pcb_first = fcb;
928 935 fcb->fcb_next = fcbp;
929 936 break;
930 937 }
931 938 fcbprev = fcbp;
932 939 fcbp = fcbp->fcb_next;
933 940 }
934 941 /* younger than all || empty list */
935 942 if (!fcb->fcb_next) {
936 943 if (pcb->pcb_first == NULL)
937 944 pcb->pcb_dfirst = pcb->pcb_first = fcb;
938 945 pcb->pcb_dlast = pcb->pcb_last = fcb;
939 946 if (fcbprev)
940 947 fcbprev->fcb_next = fcb;
941 948 }
942 949 } else {
943 950 free((char *)fcb); /* rejected */
944 951 }
945 952 return (0);
946 953 }
947 954
948 955
949 956 /*
950 957 * .func check_file - check filename and setup fcb.
951 958 * .desc Check adherence to the file format (do_check is TRUE) and setup
952 959 * the fcb with useful information.
953 960 * filename format: yyyymmddhhmmss.yyyymmddhhmmss.suffix
954 961 * yyyymmddhhmmss.not_terminated.suffix
955 962 * If do_check is FALSE then still see if the filename does confirm
956 963 * to the format. If it does then extract useful information from
957 964 * it (start time and end time). But if it doesn't then don't print
958 965 * any error messages.
959 966 * .call ret = check_file(fcb, do_check).
960 967 * .arg fcb - ptr to fcb that holds the file.
961 968 * .arg do_check - if TRUE do check adherence to file format.
962 969 * .ret 0 - no errors detected.
963 970 * .ret -1 - file failed somehow (error_str tells why).
964 971 */
965 972 int
966 973 check_file(audit_fcb_t *fcb, int do_check)
967 974 {
968 975 int ret;
969 976 char *namep, *slp;
970 977 char errb[256]; /* build error message */
971 978 struct tm tme;
972 979
973 980 errb[0] = '\0';
974 981 /* get just the filename */
975 982 for (slp = namep = fcb->fcb_file; *namep; namep++) {
976 983 if (*namep == '/')
977 984 slp = namep + 1; /* slp -> the filename itself */
978 985 }
979 986 if (do_check == FALSE) {
980 987 fcb->fcb_end = MAXLONG; /* forever */
981 988 fcb->fcb_suffix = NULL;
982 989 fcb->fcb_name = slp;
983 990 ret = 0;
984 991 } else {
985 992 ret = -1;
986 993 }
987 994 if ((int)strlen(slp) < 31) {
988 995 (void) sprintf(errbuf, gettext("filename too short (%d)"),
989 996 strlen(slp));
990 997 error_str = errbuf;
991 998 return (ret);
992 999 }
993 1000 /*
994 1001 * Get working copy of filename.
995 1002 */
996 1003 namep = (char *)a_calloc(1, strlen(slp) + 1);
997 1004 (void) strcpy(namep, slp);
998 1005 if (namep[14] != '.' || namep[29] != '.') {
999 1006 (void) sprintf(errbuf,
1000 1007 gettext("invalid filename format (%c or %c)"), namep[14],
1001 1008 namep[29]);
1002 1009 error_str = errbuf;
1003 1010 free(namep);
1004 1011 return (ret);
1005 1012 }
1006 1013 namep[14] = '\0'; /* mark off start time */
1007 1014 namep[29] = '\0'; /* mark off finish time */
1008 1015 if (derive_date(namep, &tme)) {
1009 1016 (void) strcat(errb, gettext("starting time-stamp invalid - "));
1010 1017 (void) strcat(errb, error_str);
1011 1018 (void) strcpy(errbuf, errb);
1012 1019 error_str = errbuf;
1013 1020 free(namep);
1014 1021 return (ret);
1015 1022 }
1016 1023 /*
1017 1024 * Keep start time from filename. Use it to order files in
1018 1025 * the file list. Later we will update this when we read
1019 1026 * the first record from the file.
1020 1027 */
1021 1028 fcb->fcb_start = tm_to_secs(&tme);
1022 1029
1023 1030 if (strcmp(&namep[15], "not_terminated") == 0) {
1024 1031 fcb->fcb_end = MAXLONG; /* forever */
1025 1032 /*
1026 1033 * Only treat a 'not_terminated' file as such if
1027 1034 * it is not on the command line.
1028 1035 */
1029 1036 if (do_check == TRUE)
1030 1037 fcb->fcb_flags |= FF_NOTTERM;
1031 1038 } else if (derive_date(&namep[15], &tme)) {
1032 1039 (void) strcat(errb, gettext("ending time-stamp invalid - "));
1033 1040 (void) strcat(errb, error_str);
1034 1041 (void) strcpy(errbuf, errb);
1035 1042 error_str = errbuf;
1036 1043 free(namep);
1037 1044 return (ret);
1038 1045 } else {
1039 1046 fcb->fcb_end = tm_to_secs(&tme);
1040 1047 }
1041 1048 fcb->fcb_name = slp;
1042 1049 fcb->fcb_suffix = &slp[30];
1043 1050 free(namep);
1044 1051 return (0);
1045 1052 }
1046 1053
1047 1054
1048 1055 /*
1049 1056 * .func get_next_pcb - get a pcb to use.
1050 1057 * .desc The pcb's in the array audit_pcbs are used to hold single file
1051 1058 * groups in the form of a linked list. Each pcb holds files that
1052 1059 * are tied together by a common suffix in the file name. Here we
1053 1060 * get either 1. the existing pcb holding a specified sufix or
1054 1061 * 2. a new pcb if we can't find an existing one.
1055 1062 * .call pcb = get_next_pcb(suffix).
1056 1063 * .arg suffix - ptr to suffix we are seeking.
1057 1064 * .ret pcb - ptr to pcb that hold s the sought suffix.
1058 1065 * .ret NULL- serious failure in memory allocation. Quit processing.
1059 1066 */
1060 1067 audit_pcb_t *
1061 1068 get_next_pcb(char *suffix)
1062 1069 {
1063 1070 int i = 0;
1064 1071 int zerosize;
1065 1072 unsigned int size;
1066 1073 audit_pcb_t *pcb;
1067 1074
1068 1075 /* Search through (maybe) entire array. */
1069 1076 while (i < pcbsize) {
1070 1077 pcb = &audit_pcbs[i++];
1071 1078 if (pcb->pcb_first == NULL) {
1072 1079 proc_pcb(pcb, suffix, i);
1073 1080 return (pcb); /* came to an unused one */
1074 1081 }
1075 1082 if (suffix) {
1076 1083 if (strcmp(pcb->pcb_suffix, suffix) == 0)
1077 1084 return (pcb); /* matched one with suffix */
1078 1085 }
1079 1086 }
1080 1087 /*
1081 1088 * Uh-oh, the entire array is used and we haven't gotten one yet.
1082 1089 * Allocate a bigger array.
1083 1090 */
1084 1091 pcbsize += PCB_INC;
1085 1092 size = pcbsize * sizeof (audit_pcb_t);
1086 1093 zerosize = size - ((pcbsize - PCB_INC) * sizeof (audit_pcb_t));
1087 1094 if ((audit_pcbs = (audit_pcb_t *)realloc((char *)audit_pcbs, size)) ==
1088 1095 NULL) {
1089 1096 (void) sprintf(errbuf,
1090 1097 gettext("%s memory reallocation failed (%d bytes)"), ar,
1091 1098 size);
1092 1099 perror(errbuf);
1093 1100 audit_stats(); /* give user statistics on usage */
1094 1101 return (NULL); /* really bad thing to have happen */
1095 1102 }
1096 1103 /*
1097 1104 * Don't know if realloc clears the new memory like calloc would.
1098 1105 */
1099 1106 (void) memset((void *) & audit_pcbs[pcbsize-PCB_INC], 0,
1100 1107 (size_t)zerosize);
1101 1108 pcb = &audit_pcbs[pcbsize-PCB_INC]; /* allocate the first new one */
1102 1109 proc_pcb(pcb, suffix, pcbsize - PCB_INC);
1103 1110 return (pcb);
1104 1111 }
1105 1112
1106 1113
1107 1114 /*
1108 1115 * .func proc_pcb - process pcb.
1109 1116 * .desc Common pcb processing for above routine.
1110 1117 * .call proc_pcb(pcb, suffix, i).
1111 1118 * .arg pcb - ptr to pcb.
1112 1119 * .arg suffix - prt to suffix tha t ties this group together.
1113 1120 * .arg i - index into audit_pcbs[ ].
1114 1121 * .ret void.
1115 1122 */
1116 1123 void
1117 1124 proc_pcb(audit_pcb_t *pcb, char *suffix, int i)
1118 1125 {
1119 1126 if (suffix)
1120 1127 pcb->pcb_suffix = suffix;
1121 1128 pcbnum++; /* one more pcb in use */
1122 1129 pcb->pcb_size = AUDITBUFSIZE;
1123 1130 pcb->pcb_rec = (char *)a_calloc(1, AUDITBUFSIZE);
1124 1131 pcb->pcb_time = -1;
1125 1132 pcb->pcb_flags |= PF_USEFILE; /* note this one controls files */
1126 1133 pcb->pcb_procno = i; /* save index into audit_pcbs [] for id */
1127 1134 }
1128 1135
1129 1136
1130 1137 /*
1131 1138 * .func proc_label - process label range argument.
1132 1139 * .desc Parse label range lower-bound[;upper-bound]
1133 1140 * .call ret = proc_label(optstr).
1134 1141 * .arg opstr - ptr to label range string
1135 1142 * .ret 0 - no errors detected.
1136 1143 * .ret -1 - errors detected (error_str set).
1137 1144 */
1138 1145
1139 1146 int
1140 1147 proc_label(char *optstr)
1141 1148 {
1142 1149 char *p;
1143 1150 int error;
1144 1151
1145 1152 if (flags & M_LABEL) {
1146 1153 error_str = gettext("'l' option specified multiple times");
1147 1154 return (-1);
1148 1155 }
1149 1156 flags |= M_LABEL;
1150 1157
1151 1158 if ((m_label = malloc(sizeof (m_range_t))) == NULL) {
1152 1159 return (-1);
1153 1160 }
1154 1161 m_label->lower_bound = NULL;
1155 1162 m_label->upper_bound = NULL;
1156 1163
1157 1164 p = strchr(optstr, ';');
1158 1165 if (p == NULL) {
1159 1166 /* exact label match, lower and upper range bounds the same */
1160 1167 if (str_to_label(optstr, &m_label->lower_bound, MAC_LABEL,
1161 1168 L_NO_CORRECTION, &error) == -1) {
1162 1169 (void) sprintf(errbuf,
1163 1170 gettext("invalid sensitivity label (%s) err %d"),
1164 1171 optstr, error);
1165 1172 error_str = errbuf;
1166 1173 goto errout;
1167 1174 }
1168 1175 m_label->upper_bound = m_label->lower_bound;
1169 1176 return (0);
1170 1177 }
1171 1178 if (p == optstr) {
1172 1179 /* lower bound is not specified .. default is admin_low */
1173 1180 if (str_to_label(ADMIN_LOW, &m_label->lower_bound, MAC_LABEL,
1174 1181 L_NO_CORRECTION, &error) == -1) {
1175 1182 goto errout;
1176 1183 }
1177 1184
1178 1185 p++;
1179 1186 if (*p == '\0') {
1180 1187 /* upper bound not specified .. default is admin_high */
1181 1188 if (str_to_label(ADMIN_HIGH, &m_label->upper_bound,
1182 1189 MAC_LABEL, L_NO_CORRECTION, &error) == -1) {
1183 1190 goto errout;
1184 1191 }
1185 1192 } else {
1186 1193 if (str_to_label(p, &m_label->upper_bound, MAC_LABEL,
1187 1194 L_NO_CORRECTION, &error) == -1) {
1188 1195 (void) sprintf(errbuf, gettext(
1189 1196 "invalid sensitivity label (%s) err %d"),
1190 1197 p, error);
1191 1198 error_str = errbuf;
1192 1199 goto errout;
1193 1200 }
1194 1201 }
1195 1202 return (0);
1196 1203 }
1197 1204 *p++ = '\0';
1198 1205 if (str_to_label(optstr, &m_label->lower_bound, MAC_LABEL,
1199 1206 L_NO_CORRECTION, &error) == -1) {
1200 1207 (void) sprintf(errbuf,
1201 1208 gettext("invalid sensitivity label (%s) err %d"), optstr,
1202 1209 error);
1203 1210 error_str = errbuf;
1204 1211 goto errout;
1205 1212 }
1206 1213 if (*p == '\0') {
1207 1214 /* upper bound is not specified .. default is admin_high */
1208 1215 if (str_to_label(ADMIN_HIGH, &m_label->upper_bound,
1209 1216 MAC_LABEL, L_NO_CORRECTION, &error) == -1) {
1210 1217 goto errout;
1211 1218 }
1212 1219 } else {
1213 1220 if (str_to_label(p, &m_label->upper_bound, MAC_LABEL,
1214 1221 L_NO_CORRECTION, &error) == -1) {
1215 1222 (void) sprintf(errbuf,
1216 1223 gettext("invalid sensitivity label (%s) err %d"),
1217 1224 p, error);
1218 1225 error_str = errbuf;
1219 1226 goto errout;
1220 1227 }
1221 1228 }
1222 1229 /* make sure that upper bound dominates the lower bound */
1223 1230 if (!bldominates(m_label->upper_bound, m_label->lower_bound)) {
1224 1231 *--p = ';';
1225 1232 (void) sprintf(errbuf,
1226 1233 gettext("invalid sensitivity label range (%s)"), optstr);
1227 1234 error_str = errbuf;
1228 1235 goto errout;
1229 1236 }
1230 1237 return (0);
1231 1238
1232 1239 errout:
1233 1240 m_label_free(m_label->upper_bound);
1234 1241 m_label_free(m_label->lower_bound);
1235 1242 free(m_label);
1236 1243
1237 1244 return (-1);
1238 1245 }
1239 1246
1240 1247 /*
1241 1248 * proc_zonename - pick up zone name.
1242 1249 *
1243 1250 * all non-empty and not-too-long strings are valid since any name
1244 1251 * may be valid.
1245 1252 *
1246 1253 * ret 0: non-empty string
1247 1254 * ret -1: empty string or string is too long.
1248 1255 */
1249 1256 static int
1250 1257 proc_zonename(char *optstr)
1251 1258 {
1252 1259 size_t length = strlen(optstr);
1253 1260 if ((length < 1) || (length > ZONENAME_MAX)) {
1254 1261 (void) sprintf(errbuf,
1255 1262 gettext("invalid zone name: %s"), optstr);
1256 1263 error_str = errbuf;
1257 1264 return (-1);
1258 1265 }
1259 1266 zonename = strdup(optstr);
1260 1267 flags |= M_ZONENAME;
1261 1268 return (0);
1262 1269 }
1263 1270
1264 1271 /*
1265 1272 * proc_frmi - set up frmi for pattern matching.
1266 1273 * Logic ripped off of scf_walk_fmri()
1267 1274 * Thanks to the smf team.
1268 1275 *
1269 1276 * ret 0: OK
1270 1277 * ret -1: error
1271 1278 */
1272 1279 static int
1273 1280 proc_fmri(char *optstr)
1274 1281 {
1275 1282 if (strpbrk(optstr, "*?[") != NULL) {
1276 1283 /* have a pattern to glob for */
1277 1284
1278 1285 fmri.sp_type = PATTERN_GLOB;
1279 1286 if (optstr[0] == '*' ||
1280 1287 (strlen(optstr) >= 4 && optstr[3] == ':')) {
1281 1288 fmri.sp_arg = strdup(optstr);
1282 1289 } else if ((fmri.sp_arg = malloc(strlen(optstr) + 6)) != NULL) {
1283 1290 (void) snprintf(fmri.sp_arg, strlen(optstr) + 6,
1284 1291 "svc:/%s", optstr);
|
↓ open down ↓ |
862 lines elided |
↑ open up ↑ |
1285 1292 }
1286 1293 } else {
1287 1294 fmri.sp_type = PATTERN_PARTIAL;
1288 1295 fmri.sp_arg = strdup(optstr);
1289 1296 }
1290 1297 if (fmri.sp_arg == NULL)
1291 1298 return (-1);
1292 1299
1293 1300 return (0);
1294 1301 }
1302 +
1303 +/*
1304 + * proc_wsid - pick up Windows SID.
1305 + *
1306 + * ret 0: non-empty string
1307 + * ret -1: empty string or string is too long.
1308 + */
1309 +static int
1310 +proc_wsid(char *optstr)
1311 +{
1312 + size_t length = strlen(optstr);
1313 + if ((length < 1) || (length > 256) ||
1314 + strncmp(optstr, "S-1-", 4) != 0) { /* SMB_SID_STRSZ */
1315 + (void) snprintf(errbuf, ERRBUF_SZ,
1316 + gettext("bad Windows SID: %s"), optstr);
1317 + error_str = errbuf;
1318 + return (-1);
1319 + }
1320 + wsid = strdup(optstr);
1321 + return (0);
1322 +}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX