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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30
31 #include <stdio.h>
32 #include <limits.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <sys/stat.h> /* mkdir declaration is here? */
36 #include <unistd.h>
37 #include <errno.h>
38 #include <utmpx.h>
39 #include <dirent.h>
40 #include <sys/types.h>
41 #include <locale.h>
42 #include <libintl.h>
43 #include <pkgstrct.h>
44 #include <pkglocs.h>
45 #include "install.h"
46 #include <pkglib.h>
47 #include "libadm.h"
48 #include "libinst.h"
49 #include "pkginstall.h"
50
51 extern struct admin adm;
52 extern struct cfextra **extlist;
53 extern int ckquit, nocnflct, nosetuid, rprcflag;
54 extern char ilockfile[], rlockfile[], instdir[], savlog[],
55 tmpdir[], pkgloc[], pkgloc_sav[], pkgbin[], pkgsav[],
56 *pkginst, *msgtext;
57 extern char saveSpoolInstallDir[];
58
59 static boolean_t preinstallCheck = B_FALSE;
60 static char *zoneName = (char *)NULL;
61
62 static char ask_cont[100];
63
64 #define DISPSIZ 20 /* number of items to display on one page */
65
66 #define MSG_RUNLEVEL "\\nThe current run-level of this machine is <%s>, " \
67 "which is not a run-level suggested for installation " \
68 "of this package. Suggested run-levels (in order of " \
69 "preference) include:"
70 #define HLP_RUNLEVEL "If this package is not installed in a run-level " \
71 "which has been suggested, it is possible that the " \
72 "package may not install or operate properly. If " \
73 "you wish to follow the run-level suggestions, " \
74 "answer 'n' to stop installation of the package."
75 #define MSG_STATECHG "\\nTo change states, execute\\n\\tshutdown -y " \
76 "-i%s -g0\\nafter exiting the installation process. " \
77 "Please note that after changing states you " \
78 "may have to mount appropriate filesystem(s) " \
79 "in order to install this package."
80
81 #define ASK_CONFLICT "Do you want to install these conflicting files"
82 #define MSG_CONFLICT "\\nThe following files are already installed on the " \
83 "system and are being used by another package:"
84 #define MSG_ROGUE "\\n* - conflict with a file which does not " \
85 "belong to any package."
86 #define HLP_CONFLICT "If you choose to install conflicting files, the " \
87 "files listed above will be overwritten and/or have " \
88 "their access permissions changed. If you choose " \
89 "not to install these files, installation will " \
90 "proceed but these specific files will not be " \
91 "installed. Note that sane operation of the " \
92 "software being installed may require these files " \
93 "be installed; thus choosing to not to do so may " \
94 "cause inapropriate operation. If you wish to stop " \
95 "installation of this package, enter 'q' to quit."
96
97 #define ASK_SETUID "Do you want to install these as setuid/setgid files"
98 #define MSG_SETUID "\\nThe following files are being installed with " \
99 "setuid and/or setgid permissions:"
100 #define MSG_OVERWR "\\n* - overwriting a file which is also " \
101 "setuid/setgid."
102 #define HLP_SETUID "The package being installed appears to contain " \
103 "processes which will have their effective user or " \
104 "group ids set upon execution. History has shown " \
105 "that these types of processes can be a source of " \
106 "security problems on your system. If you choose " \
107 "not to install these as setuid files, installation " \
108 "will proceed but these specific files will be " \
109 "installed as regular files with setuid and/or " \
110 "setgid permissions reset. Note that sane " \
111 "operation of the software being installed may " \
112 "require that these files be installed with setuid " \
113 "or setgid permissions as delivered; thus choosing " \
114 "to install them as regular files may cause " \
115 "inapropriate operation. If you wish to stop " \
116 "installation of this package, enter 'q' to quit."
117 #define MSG_PARTINST "\\nThe installation of this package was previously " \
118 "terminated and installation was never successfully " \
119 "completed."
120 #define MSG_PARTREM "\\nThe removal of this package was terminated at " \
121 "some point in time, and package removal was only " \
122 "partially completed."
123 #define HLP_PARTIAL "Installation of partially installed packages is " \
124 "normally allowable, but some packages providers " \
125 "may suggest that a partially installed package be " \
126 "completely removed before re-attempting " \
127 "installation. Check the documentation provided " \
128 "with this package, and then answer 'y' if you feel " \
129 "it is advisable to continue the installation process."
130
131 #define HLP_SPACE "It appears that there is not enough free space on " \
132 "your system in which to install this package. It " \
133 "is possible that one or more filesystems are not " \
134 "properly mounted. Neither installation of the " \
135 "package nor its operation can be guaranteed under " \
136 "these conditions. If you choose to disregard this " \
137 "warning, enter 'y' to continue the installation " \
138 "process."
139 #define HLP_DEPEND "The package being installed has indicated a " \
140 "dependency on the existence (or non-existence) " \
141 "of another software package. If this dependency is " \
142 "not met before continuing, the package may not " \
143 "install or operate properly. If you wish to " \
144 "disregard this dependency, answer 'y' to continue " \
145 "the installation process."
146
147 #define MSG_PRIV "\\nThis package contains scripts which will be " \
148 "executed with super-user permission during the " \
149 "process of installing this package."
150 #define HLP_PRIV "During the installation of this package, certain " \
151 "scripts provided with the package will execute with " \
152 "super-user permission. These scripts may modify or " \
153 "otherwise change your system without your " \
154 "knowledge. If you are certain of the origin and " \
155 "trustworthiness of the package being installed, " \
156 "answer 'y' to continue the installation process."
157
158 #define ASK_CONT "Do you want to continue with the installation of <%s>"
159 #define HLP_CONT "If you choose 'y', installation of this package " \
160 "will continue. If you want to stop installation " \
161 "of this package, choose 'n'."
162
163 #define MSG_MKPKGDIR "unable to make packaging directory <%s>"
164
165 #define MSG_CKCONFL_GZ "## Checking for conflicts with packages already " \
166 "installed."
167 #define MSG_CKCONFL_LZ "## Checking for conflicts with packages already " \
168 "installed in zone <%s>."
169 #define MSG_CKDEPEND_GZ "## Verifying package dependencies."
170 #define MSG_CKDEPEND_LZ "## Verifying package dependencies in zone <%s>."
171 #define MSG_CKSPACE_GZ "## Verifying disk space requirements."
172 #define MSG_CKSPACE_LZ "## Verifying disk space requirements in zone <%s>."
173 #define MSG_CKUID_GZ "## Checking for setuid/setgid programs."
174 #define MSG_CKUID_LZ "## Checking for setuid/setgid programs in zone <%s>."
175
176 #define MSG_SCRFND "Package scripts were found."
177 #define MSG_UIDFND "Setuid/setgid processes detected."
178 #define MSG_ATTRONLY "!%s %s <attribute change only>"
179
180 #define MSG_CONTDISP "[Hit <RETURN> to continue display]"
181
182 #define ERR_NO_RUNST "unable to determine current run-state"
183 #define ERR_DEPFAILED "Dependency checking failed."
184 #define ERR_SPCFAILED "Space checking failed."
185 #define ERR_CNFFAILED "Conflict checking failed."
186 #define ERR_BADFILE "packaging file <%s> is corrupt"
187
188 /*
189 * Return value: int
190 * 0 - success
191 * 1 - end of file
192 * 2 - undefined error
193 * 3 - answer was not "y"/was "q"
194 * 4 - quit action taken
195 * 5 - interactive mode required
196 * If "preinstallcheck" is set to B_TRUE:
197 * 8 - partial install detected
198 * 9 - partial removal detected
199 */
200
201 int
ckpartial(void)202 ckpartial(void)
203 {
204 char ans[MAX_INPUT];
205 int n;
206
207 if (ADM(partial, "nocheck")) {
208 return (0);
209 }
210
211 if (access(ilockfile, F_OK) == 0) {
212 if (preinstallCheck == B_TRUE) {
213 return (8); /* partial install detected */
214 }
215
216 (void) snprintf(ask_cont, sizeof (ask_cont),
217 gettext(ASK_CONT), pkginst);
218
219 msgtext = gettext(MSG_PARTINST);
220 ptext(stderr, msgtext);
221
222 if (ADM(partial, "quit")) {
223 return (4);
224 }
225
226 if (echoGetFlag() == B_FALSE) {
227 return (5);
228 }
229
230 msgtext = NULL;
231
232 ckquit = 0;
233 if (n = ckyorn(ans, NULL, NULL, gettext(HLP_PARTIAL),
234 ask_cont)) {
235 return (n);
236 }
237
238 if (strchr("yY", *ans) == NULL) {
239 return (3);
240 }
241 ckquit = 1;
242 }
243
244 if (access(rlockfile, F_OK) == 0) {
245 if (preinstallCheck == B_TRUE) {
246 return (9); /* partial removal detected */
247 }
248
249 (void) snprintf(ask_cont, sizeof (ask_cont),
250 gettext(ASK_CONT), pkginst);
251
252
253 msgtext = gettext(MSG_PARTREM);
254 ptext(stderr, msgtext);
255
256 if (ADM(partial, "quit")) {
257 return (4);
258 }
259
260 if (echoGetFlag() == B_FALSE) {
261 return (5);
262 }
263
264 msgtext = NULL;
265
266 ckquit = 0;
267 if (n = ckyorn(ans, NULL, NULL, gettext(HLP_PARTIAL),
268 ask_cont)) {
269 return (n);
270 }
271
272 if (strchr("yY", *ans) == NULL) {
273 return (3);
274 }
275 ckquit = 1;
276 }
277
278 return (0);
279 }
280
281 /*
282 * Return value: int
283 * 0 - success
284 * 1 - end of file
285 * 2 - undefined error
286 * 3 - answer was not "y"/was "q"
287 * 4 - quit action taken
288 * 5 - interactive mode required
289 * 99 - fatal error
290 */
291
292 int
ckrunlevel(void)293 ckrunlevel(void)
294 {
295 struct utmpx utmpx;
296 struct utmpx *putmpx;
297 char ans[MAX_INPUT], *pt, *istates, *pstate;
298 int n;
299 char *uxstate;
300
301 if (ADM(runlevel, "nocheck")) {
302 return (0);
303 }
304
305 pt = getenv("ISTATES");
306 if (pt == NULL) {
307 return (0);
308 }
309
310 utmpx.ut_type = RUN_LVL;
311 putmpx = getutxid(&utmpx);
312 if (putmpx == NULL) {
313 progerr(gettext(ERR_NO_RUNST));
314 return (99);
315 }
316
317 (void) snprintf(ask_cont, sizeof (ask_cont),
318 gettext(ASK_CONT), pkginst);
319
320 /*
321 * this cryptic code is trying to pull the run level
322 * out of the utmpx entry...the level starts in column
323 * 11 - looks like "run-level %c"
324 */
325 uxstate = strtok(&putmpx->ut_line[10], " \t\n");
326
327 istates = qstrdup(pt);
328 if ((pt = strtok(pt, " \t\n, ")) == NULL) {
329 return (0); /* no list is no list */
330 }
331
332 pstate = pt;
333 do {
334 if (strcmp(pt, uxstate) == 0) {
335 free(istates);
336 return (0);
337 }
338 } while (pt = strtok(NULL, " \t\n, "));
339
340 if (preinstallCheck == B_FALSE) {
341 msgtext = gettext(MSG_RUNLEVEL);
342 ptext(stderr, msgtext, uxstate);
343 } else {
344 (void) fprintf(stdout, "runlevel=%s", uxstate);
345 }
346
347 pt = strtok(istates, " \t\n, ");
348 do {
349 if (preinstallCheck == B_FALSE) {
350 ptext(stderr, "\\t%s", pt);
351 } else {
352 (void) fprintf(stdout, ":%s", pt);
353 }
354 } while (pt = strtok(NULL, " \t\n, "));
355
356 if (preinstallCheck == B_TRUE) {
357 (void) fprintf(stdout, "\n");
358 }
359
360 free(istates);
361
362 if (preinstallCheck == B_TRUE) {
363 return (4);
364 }
365
366 if (ADM(runlevel, "quit")) {
367 return (4);
368 }
369
370 if (echoGetFlag() == B_FALSE) {
371 return (5);
372 }
373
374 msgtext = NULL;
375
376 ckquit = 0;
377 if (n = ckyorn(ans, NULL, NULL, gettext(HLP_RUNLEVEL),
378 ask_cont)) {
379 return (n);
380 }
381
382 ckquit = 1;
383
384 if (strchr("yY", *ans) != NULL) {
385 return (0);
386 } else {
387 if (preinstallCheck == B_FALSE) {
388 ptext(stderr, gettext(MSG_STATECHG), pstate);
389 }
390 return (3);
391 }
392 }
393
394 /*
395 * Return value: int
396 * 0 - success
397 * 1 - end of file
398 * 2 - undefined error
399 * 3 - answer was not "y"/was "q"
400 * 4 - quit action taken
401 * 5 - interactive mode required
402 */
403
404 int
ckdepend(void)405 ckdepend(void)
406 {
407 int n;
408 char ans[MAX_INPUT];
409 char path[PATH_MAX];
410
411 if (ADM(idepend, "nocheck")) {
412 return (0);
413 }
414
415 (void) snprintf(path, sizeof (path), "%s/%s", instdir, DEPEND_FILE);
416 if (access(path, F_OK) != 0) {
417 return (0); /* no dependency file provided by package */
418 }
419
420 if (zoneName == (char *)NULL) {
421 echo(gettext(MSG_CKDEPEND_GZ));
422 } else {
423 echo(gettext(MSG_CKDEPEND_LZ), zoneName);
424 }
425
426 if (dockdeps(path, 0, preinstallCheck)) {
427 (void) snprintf(ask_cont, sizeof (ask_cont),
428 gettext(ASK_CONT), pkginst);
429 msgtext = gettext(ERR_DEPFAILED);
430
431 if (preinstallCheck == B_TRUE) {
432 return (4);
433 }
434
435 if (ADM(idepend, "quit")) {
436 return (4);
437 }
438
439 if (echoGetFlag() == B_FALSE) {
440 return (5);
441 }
442
443 msgtext = NULL;
444
445 ckquit = 0;
446 if (n = ckyorn(ans, NULL, NULL, gettext(HLP_DEPEND),
447 ask_cont)) {
448 return (n);
449 }
450
451 if (strchr("yY", *ans) == NULL) {
452 return (3);
453 }
454
455 ckquit = 1;
456 }
457
458 return (0);
459 }
460
461 void
cksetZoneName(char * a_zoneName)462 cksetZoneName(char *a_zoneName)
463 {
464 zoneName = a_zoneName;
465 }
466
467 void
cksetPreinstallCheck(boolean_t a_preinstallCheck)468 cksetPreinstallCheck(boolean_t a_preinstallCheck)
469 {
470 preinstallCheck = a_preinstallCheck;
471 }
472
473 /*
474 * Return value: int
475 * 0 - success
476 * 1 - end of file
477 * 2 - undefined error
478 * 3 - answer was not "y"/was "q"
479 * 4 - quit action taken
480 * 5 - interactive mode required
481 */
482 int
ckspace(void)483 ckspace(void)
484 {
485 int n;
486 char ans[MAX_INPUT];
487 char path[PATH_MAX];
488
489 if (ADM(space, "nocheck")) {
490 return (0);
491 }
492
493 if (zoneName == (char *)NULL) {
494 echo(gettext(MSG_CKSPACE_GZ));
495 } else {
496 echo(gettext(MSG_CKSPACE_LZ), zoneName);
497 }
498
499 (void) snprintf(path, sizeof (path), "%s/install/space", instdir);
500 if (access(path, F_OK) == 0) {
501 n = dockspace(path);
502 } else {
503 n = dockspace(NULL);
504 }
505
506 if (n) {
507 msgtext = gettext(ERR_SPCFAILED);
508 (void) snprintf(ask_cont, sizeof (ask_cont),
509 gettext(ASK_CONT), pkginst);
510
511 if (preinstallCheck == B_TRUE) {
512 return (4);
513 }
514
515 if (ADM(space, "quit")) {
516 return (4);
517 }
518
519 if (echoGetFlag() == B_FALSE) {
520 return (5);
521 }
522
523 msgtext = NULL;
524
525 ckquit = 0;
526 n = ckyorn(ans, NULL, NULL, gettext(HLP_SPACE), ask_cont);
527 if (n != 0) {
528 return (n);
529 }
530
531 if (strchr("yY", *ans) == NULL) {
532 return (3);
533 }
534
535 ckquit = 1;
536 }
537 return (0);
538 }
539
540 void
ckdirs(void)541 ckdirs(void)
542 {
543 char path[PATH_MAX];
544
545 if (mkpath(get_PKGADM())) {
546 if (preinstallCheck == B_TRUE) {
547 (void) fprintf(stdout, "ckdirs=%s\n", get_PKGADM());
548 } else {
549 progerr(gettext(MSG_MKPKGDIR), get_PKGADM());
550 }
551 quit(99);
552 }
553
554 (void) snprintf(path, sizeof (path), "%s/admin", get_PKGADM());
555
556 if (mkpath(path)) {
557 if (preinstallCheck == B_TRUE) {
558 (void) fprintf(stdout, "ckdirs=%s\n", path);
559 } else {
560 progerr(gettext(MSG_MKPKGDIR), path);
561 }
562 quit(99);
563 }
564
565 (void) snprintf(path, sizeof (path), "%s/logs", get_PKGADM());
566
567 if (mkpath(path)) {
568 if (preinstallCheck == B_TRUE) {
569 (void) fprintf(stdout, "ckdirs=%s\n", path);
570 } else {
571 progerr(gettext(MSG_MKPKGDIR), path);
572 }
573 quit(99);
574 }
575
576 if (mkpath(PKGSCR)) {
577 if (preinstallCheck == B_TRUE) {
578 (void) fprintf(stdout, "ckdirs=%s\n", PKGSCR);
579 } else {
580 progerr(gettext(MSG_MKPKGDIR), PKGSCR);
581 }
582 quit(99);
583 }
584
585 if (mkpath(get_PKGLOC())) {
586 if (preinstallCheck == B_TRUE) {
587 (void) fprintf(stdout, "ckdirs=%s\n", get_PKGLOC());
588 } else {
589 progerr(gettext(MSG_MKPKGDIR), get_PKGLOC());
590 }
591 quit(99);
592 }
593 }
594
595 /*
596 * Return value: int
597 * 0 - success
598 * 99 - failure
599 */
600
601 int
ckpkgdirs(void)602 ckpkgdirs(void)
603 {
604 boolean_t nonExistentPkgloc = B_FALSE;
605
606 /*
607 * If pkgloc doesn't exist make sure it gets removed after creating
608 * it if this is a preinstall check. All dryrun and preinstallation
609 * checks must not modify the file system.
610 */
611
612 if (access(pkgloc, F_OK) != 0) {
613 nonExistentPkgloc = B_TRUE;
614 }
615
616 if (mkpath(pkgloc)) {
617 if (preinstallCheck == B_TRUE) {
618 (void) fprintf(stdout, "ckdirs=%s\n", pkgloc);
619 } else {
620 progerr(gettext(MSG_MKPKGDIR), pkgloc);
621 }
622 return (99);
623 }
624
625 if (mkpath(pkgbin)) {
626 if (preinstallCheck == B_TRUE) {
627 (void) fprintf(stdout, "ckdirs=%s\n", pkgbin);
628 } else {
629 progerr(gettext(MSG_MKPKGDIR), pkgbin);
630 }
631 return (99);
632 }
633
634 if (mkpath(pkgsav)) {
635 if (preinstallCheck == B_TRUE) {
636 (void) fprintf(stdout, "ckdirs=%s\n", pkgsav);
637 } else {
638 progerr(gettext(MSG_MKPKGDIR), pkgsav);
639 }
640 return (99);
641 }
642
643 if (!is_spool_create() && mkpath(saveSpoolInstallDir)) {
644 if (preinstallCheck == B_TRUE) {
645 (void) fprintf(stdout, "ckdirs=%s\n", pkgsav);
646 } else {
647 progerr(gettext(MSG_MKPKGDIR), pkgsav);
648 }
649 return (99);
650 }
651
652 if (preinstallCheck && nonExistentPkgloc) {
653 rrmdir(pkgloc);
654 }
655
656 return (0);
657 }
658
659 /*
660 * Return value: int
661 * 0 - success
662 * 1 - end of file
663 * 2 - undefined error
664 * 3 - answer was not "y"/was "q"
665 * 4 - quit action taken
666 * 5 - interactive mode required
667 */
668
669 int
ckconflct(void)670 ckconflct(void)
671 {
672 int i, n, count, has_a_rogue = 0;
673 char ans[MAX_INPUT];
674
675 if (ADM(conflict, "nochange")) {
676 nocnflct++;
677 return (0);
678 }
679
680 if (ADM(conflict, "nocheck")) {
681 return (0);
682 }
683
684 if (zoneName == (char *)NULL) {
685 echo(gettext(MSG_CKCONFL_GZ));
686 } else {
687 echo(gettext(MSG_CKCONFL_LZ), zoneName);
688 }
689
690 count = 0;
691 for (i = 0; extlist[i]; i++) {
692 struct cfent *ept;
693 struct mergstat *mstat;
694
695 if (extlist[i]->cf_ent.ftype == 'i') {
696 continue;
697 }
698
699 ept = &(extlist[i]->cf_ent);
700 mstat = &(extlist[i]->mstat);
701
702 if (is_remote_fs(ept->path, &(extlist[i]->fsys_value)) &&
703 !is_fs_writeable(ept->path,
704 &(extlist[i]->fsys_value))) {
705 continue;
706 }
707
708 /*
709 * If no other package claims it or it's from a continuation
710 * file, skip it.
711 */
712 if (!mstat->shared || mstat->preloaded) {
713 continue;
714 }
715
716 if (ept->ftype == 'e') {
717 continue;
718 }
719
720 if (mstat->rogue) {
721 has_a_rogue = 1;
722 }
723
724 if (mstat->contchg) {
725 if (!count++) {
726 if (preinstallCheck == B_FALSE) {
727 ptext(stderr, gettext(MSG_CONFLICT));
728 }
729 } else if ((echoGetFlag() == B_TRUE) &&
730 ((count % DISPSIZ) == 0)) {
731 echo(gettext(MSG_CONTDISP));
732 (void) getc(stdin);
733 }
734 /*
735 * NOTE : The leading "!" in this string forces
736 * puttext() to print leading white space.
737 */
738
739 if (preinstallCheck == B_FALSE) {
740 ptext(stderr, "!%s %s",
741 (mstat->rogue) ? "*" : " ", ept->path);
742 } else {
743 (void) fprintf(stdout,
744 "conflict-contents=%s\n", ept->path);
745 }
746 } else if (mstat->attrchg) {
747 if (!count++) {
748 if (preinstallCheck == B_FALSE) {
749 ptext(stderr, gettext(MSG_CONFLICT));
750 }
751 } else if ((echoGetFlag() == B_TRUE) &&
752 ((count % DISPSIZ) == 0)) {
753 echo(gettext(MSG_CONTDISP));
754 (void) getc(stdin);
755 }
756 if (preinstallCheck == B_FALSE) {
757 ptext(stderr, gettext(MSG_ATTRONLY),
758 (mstat->rogue) ? "*" : " ", ept->path);
759 } else {
760 (void) fprintf(stdout,
761 "conflict-attributes=%s\n", ept->path);
762 }
763 }
764 }
765
766 if (count) {
767 if (has_a_rogue) {
768 if (preinstallCheck == B_FALSE) {
769 ptext(stderr, gettext(MSG_ROGUE));
770 }
771 }
772
773 msgtext = gettext(ERR_CNFFAILED);
774
775 if (preinstallCheck == B_TRUE) {
776 return (4);
777 }
778
779 if (ADM(conflict, "quit")) {
780 return (4);
781 }
782
783 if (echoGetFlag() == B_FALSE) {
784 return (5);
785 }
786
787 msgtext = NULL;
788
789 if (n = ckyorn(ans, NULL, NULL, gettext(HLP_CONFLICT),
790 gettext(ASK_CONFLICT))) {
791 return (n);
792 }
793
794 if (strchr("yY", *ans) == NULL) {
795 ckquit = 0;
796 (void) snprintf(ask_cont, sizeof (ask_cont),
797 gettext(ASK_CONT), pkginst);
798
799 if (n = ckyorn(ans, NULL, NULL, gettext(HLP_CONT),
800 ask_cont)) {
801 return (n);
802 }
803
804 if (strchr("yY", *ans) == NULL) {
805 return (3);
806 }
807 ckquit = 1;
808 nocnflct++;
809 rprcflag++;
810 }
811 }
812 return (0);
813 }
814
815 /*
816 * Return value: int
817 * 0 - success
818 * 1 - end of file
819 * 2 - undefined error
820 * 3 - answer was not "y"/was "q"
821 * 4 - quit action taken
822 * 5 - interactive mode required
823 */
824
825 int
cksetuid(void)826 cksetuid(void)
827 {
828 int i, n, count, overwriting = 0;
829 char ans[MAX_INPUT];
830
831 /* See if the administrative defaults already resolve this check. */
832 if (ADM(setuid, "nocheck")) {
833 return (0);
834 }
835
836 if (ADM(setuid, "nochange")) {
837 nosetuid++; /* Do not install processes as setuid/gid. */
838 return (0);
839 }
840
841 /* The administrative defaults require review of the package. */
842
843 if (zoneName == (char *)NULL) {
844 echo(gettext(MSG_CKUID_GZ));
845 } else {
846 echo(gettext(MSG_CKUID_LZ), zoneName);
847 }
848
849 count = 0;
850 for (i = 0; extlist[i]; i++) {
851 int overwr;
852 struct mergstat *mstat = &(extlist[i]->mstat);
853
854 /*
855 * Provide the administrator with info as to whether there is
856 * already a setuid process in place. This is only necessary
857 * to help the administrator decide whether or not to lay
858 * down the process, it doesn't have anything to do with the
859 * administrative defaults.
860 */
861 if (mstat->osetuid || mstat->osetgid) {
862 overwr = 1;
863 overwriting = 1;
864 } else
865 overwr = 0;
866
867 if (mstat->setuid || mstat->setgid) {
868 if (!count++) {
869 if (preinstallCheck == B_FALSE) {
870 ptext(stderr, gettext(MSG_SETUID));
871 }
872 } else if ((echoGetFlag() == B_TRUE) &&
873 ((count % DISPSIZ) == 0)) {
874 echo(gettext(MSG_CONTDISP));
875 (void) getc(stdin);
876 }
877 /*
878 * NOTE : The leading "!" in these strings forces
879 * puttext() to print leading white space.
880 */
881
882 if (mstat->setuid && mstat->setgid) {
883 if (preinstallCheck == B_FALSE) {
884 ptext(stderr, gettext(
885 "!%s %s <setuid %s setgid %s>"),
886 (overwr) ? "*" : " ",
887 extlist[i]->cf_ent.path,
888 extlist[i]->cf_ent.ainfo.owner,
889 extlist[i]->cf_ent.ainfo.group);
890 } else {
891 (void) fprintf(stdout, "setuid=%s:%s\n",
892 extlist[i]->cf_ent.path,
893 extlist[i]->cf_ent.ainfo.owner);
894 (void) fprintf(stdout, "setgid=%s:%s\n",
895 extlist[i]->cf_ent.path,
896 extlist[i]->cf_ent.ainfo.group);
897 }
898 } else if (mstat->setuid) {
899 if (preinstallCheck == B_FALSE) {
900 ptext(stderr, gettext(
901 "!%s %s <setuid %s>"),
902 (overwr) ? "*" : " ",
903 extlist[i]->cf_ent.path,
904 extlist[i]->cf_ent.ainfo.owner);
905 } else {
906 (void) fprintf(stdout, "setuid=%s:%s\n",
907 extlist[i]->cf_ent.path,
908 extlist[i]->cf_ent.ainfo.owner);
909 }
910 } else if (mstat->setgid) {
911 if (preinstallCheck == B_FALSE) {
912 ptext(stderr, gettext(
913 "!%s%s <setgid %s>"),
914 (overwr) ? "*" : " ",
915 extlist[i]->cf_ent.path,
916 extlist[i]->cf_ent.ainfo.group);
917 } else {
918 (void) fprintf(stdout, "setgid=%s:%s\n",
919 extlist[i]->cf_ent.path,
920 extlist[i]->cf_ent.ainfo.group);
921 }
922 }
923 }
924 }
925
926 if (count) {
927 if (overwriting) {
928 if (preinstallCheck == B_FALSE) {
929 ptext(stderr, gettext(MSG_OVERWR));
930 } else {
931 (void) fprintf(stdout,
932 "setuid-overwrite=true\n");
933 }
934 }
935
936 msgtext = gettext(MSG_UIDFND);
937
938 if (preinstallCheck == B_TRUE) {
939 return (4);
940 }
941
942 if (ADM(setuid, "quit")) {
943 return (4);
944 }
945 if (echoGetFlag() == B_FALSE) {
946 return (5);
947 }
948 msgtext = NULL;
949
950 if (n = ckyorn(ans, NULL, NULL, gettext(HLP_SETUID),
951 gettext(ASK_SETUID))) {
952 return (n);
953 }
954 if (strchr("yY", *ans) == NULL) {
955 ckquit = 0;
956 (void) snprintf(ask_cont, sizeof (ask_cont),
957 gettext(ASK_CONT), pkginst);
958 if (n = ckyorn(ans, NULL, NULL, gettext(HLP_CONT),
959 ask_cont)) {
960 return (n);
961 }
962 if (strchr("yY", *ans) == NULL) {
963 return (3);
964 }
965 ckquit = 1;
966 nosetuid++;
967 rprcflag++;
968 }
969 }
970
971 return (0);
972 }
973
974 /*
975 * Return value: int
976 * 0 - success
977 * 1 - end of file
978 * 2 - undefined error
979 * 3 - answer was not "y"/was "q"
980 * 4 - quit action taken
981 * 5 - interactive mode required
982 */
983
984 int
ckpriv(void)985 ckpriv(void)
986 {
987 struct dirent *dp;
988 DIR *dirfp;
989 int n, found;
990 char ans[MAX_INPUT], path[PATH_MAX];
991
992 if (ADM(action, "nocheck")) {
993 return (0);
994 }
995
996 (void) snprintf(path, sizeof (path), "%s/install", instdir);
997 if ((dirfp = opendir(path)) == NULL) {
998 return (0);
999 }
1000
1001 found = 0;
1002 while ((dp = readdir(dirfp)) != NULL) {
1003 if (strcmp(dp->d_name, "preinstall") == 0 ||
1004 strcmp(dp->d_name, "postinstall") == 0 ||
1005 strncmp(dp->d_name, "i.", 2) == 0) {
1006 found++;
1007 break;
1008 }
1009 }
1010 (void) closedir(dirfp);
1011
1012 if (found) {
1013 if (preinstallCheck == B_FALSE) {
1014 ptext(stderr, gettext(MSG_PRIV));
1015 msgtext = gettext(MSG_SCRFND);
1016 }
1017 (void) snprintf(ask_cont, sizeof (ask_cont),
1018 gettext(ASK_CONT), pkginst);
1019
1020 if (preinstallCheck == B_TRUE) {
1021 return (4);
1022 }
1023
1024 if (ADM(action, "quit")) {
1025 return (4);
1026 }
1027
1028 if (echoGetFlag() == B_FALSE) {
1029 return (5);
1030 }
1031
1032 msgtext = NULL;
1033
1034 ckquit = 0;
1035 if (n = ckyorn(ans, NULL, NULL, gettext(HLP_PRIV),
1036 ask_cont)) {
1037 return (n);
1038 }
1039
1040 if (strchr("yY", *ans) == NULL) {
1041 return (3);
1042 }
1043 ckquit = 1;
1044 }
1045
1046 return (0);
1047 }
1048
1049 /*
1050 * Return value: int
1051 * 0 - success
1052 * 99 - failure
1053 */
1054
1055 int
ckpkgfiles(void)1056 ckpkgfiles(void)
1057 {
1058 register int i;
1059 struct cfent *ept;
1060 int errflg;
1061 char source[PATH_MAX];
1062
1063 errflg = 0;
1064 for (i = 0; extlist[i]; i++) {
1065 ept = &(extlist[i]->cf_ent);
1066 if (ept->ftype != 'i') {
1067 continue;
1068 }
1069
1070 if (ept->ainfo.local) {
1071 (void) snprintf(source, sizeof (source),
1072 "%s/%s", instdir, ept->ainfo.local);
1073 } else if (strcmp(ept->path, PKGINFO) == 0) {
1074 (void) snprintf(source, sizeof (source),
1075 "%s/%s", instdir, ept->path);
1076 } else {
1077 (void) snprintf(source, sizeof (source),
1078 "%s/install/%s", instdir, ept->path);
1079 }
1080 if (cverify(0, &ept->ftype, source, &ept->cinfo, 1)) {
1081 errflg++;
1082 if (preinstallCheck == B_FALSE) {
1083 progerr(gettext(ERR_BADFILE), source);
1084 logerr(getErrbufAddr());
1085 } else {
1086 (void) fprintf(stdout, "ckpkgfilebad=%s",
1087 source);
1088 }
1089 }
1090 }
1091
1092 if (errflg) {
1093 return (99);
1094 } else {
1095 return (0);
1096 }
1097 }
1098