lpr.c (241015) | lpr.c (241852) |
---|---|
1/* 2 * Copyright (c) 1983, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. --- 36 unchanged lines hidden (view full) --- 45 46#if 0 47#ifndef lint 48static char sccsid[] = "@(#)lpr.c 8.4 (Berkeley) 4/28/95"; 49#endif /* not lint */ 50#endif 51 52#include "lp.cdefs.h" /* A cross-platform version of <sys/cdefs.h> */ | 1/* 2 * Copyright (c) 1983, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. --- 36 unchanged lines hidden (view full) --- 45 46#if 0 47#ifndef lint 48static char sccsid[] = "@(#)lpr.c 8.4 (Berkeley) 4/28/95"; 49#endif /* not lint */ 50#endif 51 52#include "lp.cdefs.h" /* A cross-platform version of <sys/cdefs.h> */ |
53__FBSDID("$FreeBSD: head/usr.sbin/lpr/lpr/lpr.c 241015 2012-09-27 23:31:19Z mdf $"); | 53__FBSDID("$FreeBSD: head/usr.sbin/lpr/lpr/lpr.c 241852 2012-10-22 03:31:22Z eadler $"); |
54 55/* 56 * lpr -- off line print 57 * 58 * Allows multiple printers and printers on remote machines by 59 * using information from a printer data base. 60 */ 61 --- 78 unchanged lines hidden (view full) --- 140 int ret, didlink; 141 struct stat stb; 142 struct stat statb1, statb2; 143 struct printer myprinter, *pp = &myprinter; 144 145 printer = NULL; 146 euid = geteuid(); 147 uid = getuid(); | 54 55/* 56 * lpr -- off line print 57 * 58 * Allows multiple printers and printers on remote machines by 59 * using information from a printer data base. 60 */ 61 --- 78 unchanged lines hidden (view full) --- 140 int ret, didlink; 141 struct stat stb; 142 struct stat statb1, statb2; 143 struct printer myprinter, *pp = &myprinter; 144 145 printer = NULL; 146 euid = geteuid(); 147 uid = getuid(); |
148 seteuid(uid); | 148 PRIV_END |
149 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 150 signal(SIGHUP, cleanup); 151 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 152 signal(SIGINT, cleanup); 153 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 154 signal(SIGQUIT, cleanup); 155 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 156 signal(SIGTERM, cleanup); --- 164 unchanged lines hidden (view full) --- 321 lock_file_name(pp, buf, sizeof buf); 322 if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS)) 323 errx(1, "Printer queue is disabled"); 324 /* 325 * Initialize the control file. 326 */ 327 mktemps(pp); 328 tfd = nfile(tfname); | 149 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 150 signal(SIGHUP, cleanup); 151 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 152 signal(SIGINT, cleanup); 153 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 154 signal(SIGQUIT, cleanup); 155 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 156 signal(SIGTERM, cleanup); --- 164 unchanged lines hidden (view full) --- 321 lock_file_name(pp, buf, sizeof buf); 322 if (userid && stat(buf, &stb) == 0 && (stb.st_mode & LFM_QUEUE_DIS)) 323 errx(1, "Printer queue is disabled"); 324 /* 325 * Initialize the control file. 326 */ 327 mktemps(pp); 328 tfd = nfile(tfname); |
329 seteuid(euid); | 329 PRIV_START |
330 (void) fchown(tfd, pp->daemon_user, -1); 331 /* owned by daemon for protection */ | 330 (void) fchown(tfd, pp->daemon_user, -1); 331 /* owned by daemon for protection */ |
332 seteuid(uid); | 332 PRIV_END |
333 card('H', local_host); 334 card('P', lpr_username); 335 card('C', class); 336 if (hdr && !pp->no_header) { 337 if (jobname == NULL) { 338 if (argc == 0) 339 jobname = "stdin"; 340 else --- 69 unchanged lines hidden (view full) --- 410 /* 411 * The user wants the file removed after it is copied 412 * to the spool area, so see if the file can be moved 413 * instead of copy/unlink'ed. This is much faster and 414 * uses less spool space than copying the file. This 415 * can be very significant when running services like 416 * samba, pcnfs, CAP, et al. 417 */ | 333 card('H', local_host); 334 card('P', lpr_username); 335 card('C', class); 336 if (hdr && !pp->no_header) { 337 if (jobname == NULL) { 338 if (argc == 0) 339 jobname = "stdin"; 340 else --- 69 unchanged lines hidden (view full) --- 410 /* 411 * The user wants the file removed after it is copied 412 * to the spool area, so see if the file can be moved 413 * instead of copy/unlink'ed. This is much faster and 414 * uses less spool space than copying the file. This 415 * can be very significant when running services like 416 * samba, pcnfs, CAP, et al. 417 */ |
418 seteuid(euid); | 418 PRIV_START |
419 didlink = 0; 420 /* 421 * There are several things to check to avoid any 422 * security issues. Some of these are redundant 423 * under BSD's, but are necessary when lpr is built 424 * under some other OS's (which I do do...) 425 */ 426 if (lstat(arg, &statb1) < 0) --- 21 unchanged lines hidden (view full) --- 448 if (statb2.st_nlink > 2) 449 goto nohardlink; 450 /* 451 * If we can access and remove the original file 452 * without special setuid-ness then this method is 453 * safe. Otherwise, abandon the move and fall back 454 * to the (usual) copy method. 455 */ | 419 didlink = 0; 420 /* 421 * There are several things to check to avoid any 422 * security issues. Some of these are redundant 423 * under BSD's, but are necessary when lpr is built 424 * under some other OS's (which I do do...) 425 */ 426 if (lstat(arg, &statb1) < 0) --- 21 unchanged lines hidden (view full) --- 448 if (statb2.st_nlink > 2) 449 goto nohardlink; 450 /* 451 * If we can access and remove the original file 452 * without special setuid-ness then this method is 453 * safe. Otherwise, abandon the move and fall back 454 * to the (usual) copy method. 455 */ |
456 seteuid(uid); | 456 PRIV_END |
457 ret = access(dfname, R_OK); 458 if (ret == 0) 459 ret = unlink(arg); | 457 ret = access(dfname, R_OK); 458 if (ret == 0) 459 ret = unlink(arg); |
460 seteuid(euid); | 460 PRIV_START |
461 if (ret != 0) 462 goto nohardlink; 463 /* 464 * Unlink of user file was successful. Change the 465 * owner and permissions, add entries to the control 466 * file, and skip the file copying step. 467 */ 468 chown(dfname, pp->daemon_user, getegid()); 469 chmod(dfname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); | 461 if (ret != 0) 462 goto nohardlink; 463 /* 464 * Unlink of user file was successful. Change the 465 * owner and permissions, add entries to the control 466 * file, and skip the file copying step. 467 */ 468 chown(dfname, pp->daemon_user, getegid()); 469 chmod(dfname, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); |
470 seteuid(uid); | 470 PRIV_END |
471 if (format == 'p') 472 card('T', title ? title : arg); 473 for (i = 0; i < ncopies; i++) 474 card(format, &dfname[inchar-2]); 475 card('U', &dfname[inchar-2]); 476 card('N', arg); 477 nact++; 478 continue; 479 nohardlink: 480 if (didlink) 481 unlink(dfname); | 471 if (format == 'p') 472 card('T', title ? title : arg); 473 for (i = 0; i < ncopies; i++) 474 card(format, &dfname[inchar-2]); 475 card('U', &dfname[inchar-2]); 476 card('N', arg); 477 nact++; 478 continue; 479 nohardlink: 480 if (didlink) 481 unlink(dfname); |
482 seteuid(uid); /* restore old uid */ | 482 PRIV_END /* restore old uid */ |
483 } /* end: if (f) */ 484 485 if ((i = open(arg, O_RDONLY)) < 0) { 486 printf("%s: cannot open %s\n", progname, arg); 487 } else { 488 copy(pp, i, arg); 489 (void) close(i); 490 if (f && unlink(arg) < 0) 491 printf("%s: %s: not removed\n", progname, arg); 492 } 493 } 494 495 if (nact) { 496 (void) close(tfd); 497 tfname[inchar]--; 498 /* 499 * Touch the control file to fix position in the queue. 500 */ | 483 } /* end: if (f) */ 484 485 if ((i = open(arg, O_RDONLY)) < 0) { 486 printf("%s: cannot open %s\n", progname, arg); 487 } else { 488 copy(pp, i, arg); 489 (void) close(i); 490 if (f && unlink(arg) < 0) 491 printf("%s: %s: not removed\n", progname, arg); 492 } 493 } 494 495 if (nact) { 496 (void) close(tfd); 497 tfname[inchar]--; 498 /* 499 * Touch the control file to fix position in the queue. 500 */ |
501 seteuid(euid); | 501 PRIV_START |
502 if ((tfd = open(tfname, O_RDWR)) >= 0) { 503 char touch_c; 504 505 if (read(tfd, &touch_c, 1) == 1 && 506 lseek(tfd, (off_t)0, 0) == 0 && 507 write(tfd, &touch_c, 1) != 1) { 508 printf("%s: cannot touch %s\n", progname, 509 tfname); 510 tfname[inchar]++; 511 cleanup(0); 512 } 513 (void) close(tfd); 514 } 515 if (link(tfname, cfname) < 0) { 516 printf("%s: cannot rename %s\n", progname, cfname); 517 tfname[inchar]++; 518 cleanup(0); 519 } 520 unlink(tfname); | 502 if ((tfd = open(tfname, O_RDWR)) >= 0) { 503 char touch_c; 504 505 if (read(tfd, &touch_c, 1) == 1 && 506 lseek(tfd, (off_t)0, 0) == 0 && 507 write(tfd, &touch_c, 1) != 1) { 508 printf("%s: cannot touch %s\n", progname, 509 tfname); 510 tfname[inchar]++; 511 cleanup(0); 512 } 513 (void) close(tfd); 514 } 515 if (link(tfname, cfname) < 0) { 516 printf("%s: cannot rename %s\n", progname, cfname); 517 tfname[inchar]++; 518 cleanup(0); 519 } 520 unlink(tfname); |
521 seteuid(uid); | 521 PRIV_END |
522 if (qflag) /* just q things up */ 523 exit(0); 524 if (!startdaemon(pp)) 525 printf("jobs queued, but cannot start daemon.\n"); 526 exit(0); 527 } 528 cleanup(0); 529 return (1); --- 69 unchanged lines hidden (view full) --- 599 } 600 } 601 break; 602 } 603 strncat(buf, "/", sizeof(buf) - strlen(buf) - 1); 604 strncat(buf, file, sizeof(buf) - strlen(buf) - 1); 605 file = buf; 606 } | 522 if (qflag) /* just q things up */ 523 exit(0); 524 if (!startdaemon(pp)) 525 printf("jobs queued, but cannot start daemon.\n"); 526 exit(0); 527 } 528 cleanup(0); 529 return (1); --- 69 unchanged lines hidden (view full) --- 599 } 600 } 601 break; 602 } 603 strncat(buf, "/", sizeof(buf) - strlen(buf) - 1); 604 strncat(buf, file, sizeof(buf) - strlen(buf) - 1); 605 file = buf; 606 } |
607 seteuid(euid); | 607 PRIV_START |
608 ret = symlink(file, dfname); | 608 ret = symlink(file, dfname); |
609 seteuid(uid); | 609 PRIV_END |
610 return(ret ? NULL : file); 611} 612 613/* 614 * Put a line into the control file. 615 */ 616static void 617card(int c, const char *p2) --- 15 unchanged lines hidden (view full) --- 633 * Create a new file in the spool directory. 634 */ 635static int 636nfile(char *n) 637{ 638 register int f; 639 int oldumask = umask(0); /* should block signals */ 640 | 610 return(ret ? NULL : file); 611} 612 613/* 614 * Put a line into the control file. 615 */ 616static void 617card(int c, const char *p2) --- 15 unchanged lines hidden (view full) --- 633 * Create a new file in the spool directory. 634 */ 635static int 636nfile(char *n) 637{ 638 register int f; 639 int oldumask = umask(0); /* should block signals */ 640 |
641 seteuid(euid); | 641 PRIV_START |
642 f = open(n, O_WRONLY | O_EXCL | O_CREAT, FILMOD); 643 (void) umask(oldumask); 644 if (f < 0) { 645 printf("%s: cannot create %s\n", progname, n); 646 cleanup(0); 647 } 648 if (fchown(f, userid, -1) < 0) { 649 printf("%s: cannot chown %s\n", progname, n); 650 cleanup(0); /* cleanup does exit */ 651 } | 642 f = open(n, O_WRONLY | O_EXCL | O_CREAT, FILMOD); 643 (void) umask(oldumask); 644 if (f < 0) { 645 printf("%s: cannot create %s\n", progname, n); 646 cleanup(0); 647 } 648 if (fchown(f, userid, -1) < 0) { 649 printf("%s: cannot chown %s\n", progname, n); 650 cleanup(0); /* cleanup does exit */ 651 } |
652 seteuid(uid); | 652 PRIV_END |
653 if (++n[inchar] > 'z') { 654 if (++n[inchar-2] == 't') { 655 printf("too many files - break up the job\n"); 656 cleanup(0); 657 } 658 n[inchar] = 'A'; 659 } else if (n[inchar] == '[') 660 n[inchar] = 'a'; --- 8 unchanged lines hidden (view full) --- 669{ 670 register int i; 671 672 signal(SIGHUP, SIG_IGN); 673 signal(SIGINT, SIG_IGN); 674 signal(SIGQUIT, SIG_IGN); 675 signal(SIGTERM, SIG_IGN); 676 i = inchar; | 653 if (++n[inchar] > 'z') { 654 if (++n[inchar-2] == 't') { 655 printf("too many files - break up the job\n"); 656 cleanup(0); 657 } 658 n[inchar] = 'A'; 659 } else if (n[inchar] == '[') 660 n[inchar] = 'a'; --- 8 unchanged lines hidden (view full) --- 669{ 670 register int i; 671 672 signal(SIGHUP, SIG_IGN); 673 signal(SIGINT, SIG_IGN); 674 signal(SIGQUIT, SIG_IGN); 675 signal(SIGTERM, SIG_IGN); 676 i = inchar; |
677 seteuid(euid); | 677 PRIV_START |
678 if (tfname) 679 do 680 unlink(tfname); 681 while (tfname[i]-- != 'A'); 682 if (cfname) 683 do 684 unlink(cfname); 685 while (cfname[i]-- != 'A'); --- 155 unchanged lines hidden (view full) --- 841static void 842mktemps(const struct printer *pp) 843{ 844 register int len, fd, n; 845 register char *cp; 846 char buf[BUFSIZ]; 847 848 (void) snprintf(buf, sizeof(buf), "%s/.seq", pp->spool_dir); | 678 if (tfname) 679 do 680 unlink(tfname); 681 while (tfname[i]-- != 'A'); 682 if (cfname) 683 do 684 unlink(cfname); 685 while (cfname[i]-- != 'A'); --- 155 unchanged lines hidden (view full) --- 841static void 842mktemps(const struct printer *pp) 843{ 844 register int len, fd, n; 845 register char *cp; 846 char buf[BUFSIZ]; 847 848 (void) snprintf(buf, sizeof(buf), "%s/.seq", pp->spool_dir); |
849 seteuid(euid); | 849 PRIV_START |
850 if ((fd = open(buf, O_RDWR|O_CREAT, 0664)) < 0) { 851 printf("%s: cannot create %s\n", progname, buf); 852 exit(1); 853 } 854 if (flock(fd, LOCK_EX)) { 855 printf("%s: cannot lock %s\n", progname, buf); 856 exit(1); 857 } | 850 if ((fd = open(buf, O_RDWR|O_CREAT, 0664)) < 0) { 851 printf("%s: cannot create %s\n", progname, buf); 852 exit(1); 853 } 854 if (flock(fd, LOCK_EX)) { 855 printf("%s: cannot lock %s\n", progname, buf); 856 exit(1); 857 } |
858 seteuid(uid); | 858 PRIV_END |
859 n = 0; 860 if ((len = read(fd, buf, sizeof(buf))) > 0) { 861 for (cp = buf; len--; ) { 862 if (*cp < '0' || *cp > '9') 863 break; 864 n = n * 10 + (*cp++ - '0'); 865 } 866 } --- 26 unchanged lines hidden --- | 859 n = 0; 860 if ((len = read(fd, buf, sizeof(buf))) > 0) { 861 for (cp = buf; len--; ) { 862 if (*cp < '0' || *cp > '9') 863 break; 864 n = n * 10 + (*cp++ - '0'); 865 } 866 } --- 26 unchanged lines hidden --- |