static void update_lpd(int onoff) /* - 1 = turn on, 0 = turn off */ { if (!LPDConfigFile) return; #ifdef __APPLE__ /* * Allow /etc/hostconfig CUPS_LPD service setting to override cupsd.conf * setting for backwards-compatibility. */ if (onoff && !get_hostconfig("CUPS_LPD")) onoff = 0; #endif /* __APPLE__ */ if (!strncmp(LPDConfigFile, "xinetd:///", 10)) { /* * Enable/disable LPD via the xinetd.d config file for cups-lpd... */ char newfile[1024]; /* New cups-lpd.N file */ cups_file_t *ofp, /* Original file pointer */ *nfp; /* New file pointer */ char line[1024]; /* Line from file */ snprintf(newfile, sizeof(newfile), "%s.N", LPDConfigFile + 9); if ((ofp = cupsFileOpen(LPDConfigFile + 9, "r")) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to open \"%s\" - %s", LPDConfigFile + 9, strerror(errno)); return; } if ((nfp = cupsFileOpen(newfile, "w")) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create \"%s\" - %s", newfile, strerror(errno)); cupsFileClose(ofp); return; } /* * Copy all of the lines from the cups-lpd file... */ while (cupsFileGets(ofp, line, sizeof(line))) { if (line[0] == '{') { cupsFilePrintf(nfp, "%s\n", line); snprintf(line, sizeof(line), "\tdisable = %s", onoff ? "no" : "yes"); } else if (!strstr(line, "disable =")) cupsFilePrintf(nfp, "%s\n", line); } cupsFileClose(nfp); cupsFileClose(ofp); rename(newfile, LPDConfigFile + 9); } #ifdef __APPLE__ else if (!strncmp(LPDConfigFile, "launchd:///", 11)) { /* * Enable/disable LPD via the launchctl command... */ char *argv[5], /* Arguments for command */ *envp[MAX_ENV]; /* Environment for command */ int pid; /* Process ID */ cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0]))); argv[0] = (char *)"launchctl"; argv[1] = (char *)(onoff ? "load" : "unload"); argv[2] = (char *)"-w"; argv[3] = LPDConfigFile + 10; argv[4] = NULL; cupsdStartProcess("/bin/launchctl", argv, envp, -1, -1, -1, -1, -1, 1, NULL, NULL, &pid); } #endif /* __APPLE__ */ else cupsdLogMessage(CUPSD_LOG_INFO, "Unknown LPDConfigFile scheme!"); }
static int /* O - 1 on success, 0 on failure */ make_certificate(cupsd_client_t *con) /* I - Client connection */ { # ifdef HAVE_SECGENERATESELFSIGNEDCERTIFICATE int status = 0; /* Return status */ OSStatus err; /* Error code (if any) */ # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) char localname[1024];/* Local hostname */ # endif /* HAVE_DNSSD || HAVE_AVAHI */ const char *servername; /* Name of server in cert */ CFStringRef cfservername = NULL; /* CF string for server name */ SecIdentityRef ident = NULL; /* Identity */ SecKeyRef publicKey = NULL, /* Public key */ privateKey = NULL; /* Private key */ CFMutableDictionaryRef keyParams = NULL; /* Key generation parameters */ cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key and certificate."); # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName) { snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); servername = localname; } else # endif /* HAVE_DNSSD || HAVE_AVAHI */ servername = con->servername; cfservername = CFStringCreateWithCString(kCFAllocatorDefault, servername, kCFStringEncodingUTF8); if (!cfservername) goto cleanup; /* * Create a public/private key pair... */ keyParams = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!keyParams) goto cleanup; CFDictionaryAddValue(keyParams, kSecAttrKeyType, kSecAttrKeyTypeRSA); CFDictionaryAddValue(keyParams, kSecAttrKeySizeInBits, CFSTR("2048")); CFDictionaryAddValue(keyParams, kSecAttrLabel, CFSTR("CUPS Self-Signed Certificate")); err = SecKeyGeneratePair(keyParams, &publicKey, &privateKey); if (err != noErr) { cupsdLogMessage(CUPSD_LOG_DEBUG, "SecKeyGeneratePair returned %ld.", (long)err); goto cleanup; } /* * Create a self-signed certificate using the public/private key pair... */ CFIndex usageInt = kSecKeyUsageAll; CFNumberRef usage = CFNumberCreate(alloc, kCFNumberCFIndexType, &usageInt); CFDictionaryRef certParams = CFDictionaryCreateMutable(kCFAllocatorDefault, kSecCSRBasicContraintsPathLen, CFINT(0), kSecSubjectAltName, cfservername, kSecCertificateKeyUsage, usage, NULL, NULL); CFRelease(usage); const void *ca_o[] = { kSecOidOrganization, CFSTR("") }; const void *ca_cn[] = { kSecOidCommonName, cfservername }; CFArrayRef ca_o_dn = CFArrayCreate(kCFAllocatorDefault, ca_o, 2, NULL); CFArrayRef ca_cn_dn = CFArrayCreate(kCFAllocatorDefault, ca_cn, 2, NULL); const void *ca_dn_array[2]; ca_dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_o_dn, 1, NULL); ca_dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_cn_dn, 1, NULL); CFArrayRef subject = CFArrayCreate(kCFAllocatorDefault, ca_dn_array, 2, NULL); SecCertificateRef cert = SecGenerateSelfSignedCertificate(subject, certParams, publicKey, privateKey); CFRelease(subject); CFRelease(certParams); if (!cert) { cupsdLogMessage(CUPSD_LOG_DEBUG, "SecGenerateSelfSignedCertificate failed."); goto cleanup; } ident = SecIdentityCreate(kCFAllocatorDefault, cert, privateKey); if (ident) cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server certificate file \"%s\".", ServerCertificate); /* * Cleanup and return... */ cleanup: if (cfservername) CFRelease(cfservername); if (keyParams) CFRelease(keyParams); if (ident) CFRelease(ident); if (cert) CFRelease(cert); if (publicKey) CFRelease(publicKey); if (privateKey) CFRelease(publicKey); if (!status) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create SSL server key and certificate."); return (status); # else /* !HAVE_SECGENERATESELFSIGNEDCERTIFICATE */ int pid, /* Process ID of command */ status; /* Status of command */ char command[1024], /* Command */ *argv[4], /* Command-line arguments */ *envp[MAX_ENV + 1], /* Environment variables */ keychain[1024], /* Keychain argument */ infofile[1024], /* Type-in information for cert */ # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) localname[1024], /* Local hostname */ # endif /* HAVE_DNSSD || HAVE_AVAHI */ *servername; /* Name of server in cert */ cups_file_t *fp; /* Seed/info file */ int infofd; /* Info file descriptor */ # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName) { snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); servername = localname; } else # endif /* HAVE_DNSSD || HAVE_AVAHI */ servername = con->servername; /* * Run the "certtool" command to generate a self-signed certificate... */ if (!cupsFileFind("certtool", getenv("PATH"), 1, command, sizeof(command))) { cupsdLogMessage(CUPSD_LOG_ERROR, "No SSL certificate and certtool command not found."); return (0); } /* * Create a file with the certificate information fields... * * Note: This assumes that the default questions are asked by the certtool * command... */ if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create certificate information file %s - %s", infofile, strerror(errno)); return (0); } cupsFilePrintf(fp, "%s\n" /* Enter key and certificate label */ "r\n" /* Generate RSA key pair */ "2048\n" /* Key size in bits */ "y\n" /* OK (y = yes) */ "b\n" /* Usage (b=signing/encryption) */ "s\n" /* Sign with SHA1 */ "y\n" /* OK (y = yes) */ "%s\n" /* Common name */ "\n" /* Country (default) */ "\n" /* Organization (default) */ "\n" /* Organizational unit (default) */ "\n" /* State/Province (default) */ "%s\n" /* Email address */ "y\n", /* OK (y = yes) */ servername, servername, ServerAdmin); cupsFileClose(fp); cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key and certificate."); snprintf(keychain, sizeof(keychain), "k=%s", ServerCertificate); argv[0] = "certtool"; argv[1] = "c"; argv[2] = keychain; argv[3] = NULL; cupsdLoadEnv(envp, MAX_ENV); infofd = open(infofile, O_RDONLY); if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL, NULL, &pid)) { close(infofd); unlink(infofile); return (0); } close(infofd); unlink(infofile); while (waitpid(pid, &status, 0) < 0) if (errno != EINTR) { status = 1; break; } cupsdFinishProcess(pid, command, sizeof(command), NULL); if (status) { if (WIFEXITED(status)) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create SSL server key and certificate - " "the certtool command stopped with status %d.", WEXITSTATUS(status)); else cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create SSL server key and certificate - " "the certtool command crashed on signal %d.", WTERMSIG(status)); } else { cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server certificate file \"%s\".", ServerCertificate); } return (!status); # endif /* HAVE_SECGENERATESELFSIGNEDCERTIFICATE */ }
static void cupsd_start_notifier( cupsd_subscription_t *sub) /* I - Subscription object */ { int pid; /* Notifier process ID */ int fds[2]; /* Pipe file descriptors */ char *argv[4], /* Command-line arguments */ *envp[MAX_ENV], /* Environment variables */ user_data[128], /* Base-64 encoded user data */ scheme[256], /* notify-recipient-uri scheme */ *ptr, /* Pointer into scheme */ command[1024]; /* Notifier command */ /* * Extract the scheme name from the recipient URI and point to the * notifier program... */ strlcpy(scheme, sub->recipient, sizeof(scheme)); if ((ptr = strchr(scheme, ':')) != NULL) *ptr = '\0'; snprintf(command, sizeof(command), "%s/notifier/%s", ServerBin, scheme); /* * Base-64 encode the user data... */ httpEncode64_2(user_data, sizeof(user_data), (char *)sub->user_data, sub->user_data_len); /* * Setup the argument array... */ argv[0] = command; argv[1] = sub->recipient; argv[2] = user_data; argv[3] = NULL; /* * Setup the environment... */ cupsdLoadEnv(envp, (int)(sizeof(envp) / sizeof(envp[0]))); /* * Create pipes as needed... */ if (!NotifierStatusBuffer) { /* * Create the status pipe... */ if (cupsdOpenPipe(NotifierPipes)) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create pipes for notifier status - %s", strerror(errno)); return; } NotifierStatusBuffer = cupsdStatBufNew(NotifierPipes[0], "[Notifier]"); cupsdAddSelect(NotifierPipes[0], (cupsd_selfunc_t)cupsd_update_notifier, NULL, NULL); } if (cupsdOpenPipe(fds)) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create pipes for notifier %s - %s", scheme, strerror(errno)); return; } /* * Make sure the delivery pipe is non-blocking... */ fcntl(fds[1], F_SETFL, fcntl(fds[1], F_GETFL) | O_NONBLOCK); /* * Create the notifier process... */ if (cupsdStartProcess(command, argv, envp, fds[0], -1, NotifierPipes[1], -1, -1, 0, DefaultProfile, NULL, &pid) < 0) { /* * Error - can't fork! */ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork for notifier %s - %s", scheme, strerror(errno)); cupsdClosePipe(fds); } else { /* * Fork successful - return the PID... */ cupsdLogMessage(CUPSD_LOG_DEBUG, "Notifier %s started - PID = %d", scheme, pid); sub->pid = pid; sub->pipe = fds[1]; sub->status = 0; close(fds[0]); } }
static int /* O - 1 on success, 0 on failure */ make_certificate(cupsd_client_t *con) /* I - Client connection */ { int pid, /* Process ID of command */ status; /* Status of command */ char command[1024], /* Command */ *argv[4], /* Command-line arguments */ *envp[MAX_ENV + 1], /* Environment variables */ keychain[1024], /* Keychain argument */ infofile[1024], /* Type-in information for cert */ # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) localname[1024], /* Local hostname */ # endif /* HAVE_DNSSD || HAVE_AVAHI */ *servername; /* Name of server in cert */ cups_file_t *fp; /* Seed/info file */ int infofd; /* Info file descriptor */ # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName) { snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); servername = localname; } else # endif /* HAVE_DNSSD || HAVE_AVAHI */ servername = con->servername; /* * Run the "certtool" command to generate a self-signed certificate... */ if (!cupsFileFind("certtool", getenv("PATH"), 1, command, sizeof(command))) { cupsdLogMessage(CUPSD_LOG_ERROR, "No SSL certificate and certtool command not found!"); return (0); } /* * Create a file with the certificate information fields... * * Note: This assumes that the default questions are asked by the certtool * command... */ if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create certificate information file %s - %s", infofile, strerror(errno)); return (0); } cupsFilePrintf(fp, "%s\n" /* Enter key and certificate label */ "r\n" /* Generate RSA key pair */ "2048\n" /* Key size in bits */ "y\n" /* OK (y = yes) */ "b\n" /* Usage (b=signing/encryption) */ "s\n" /* Sign with SHA1 */ "y\n" /* OK (y = yes) */ "%s\n" /* Common name */ "\n" /* Country (default) */ "\n" /* Organization (default) */ "\n" /* Organizational unit (default) */ "\n" /* State/Province (default) */ "%s\n" /* Email address */ "y\n", /* OK (y = yes) */ servername, servername, ServerAdmin); cupsFileClose(fp); cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key and certificate..."); snprintf(keychain, sizeof(keychain), "k=%s", ServerCertificate); argv[0] = "certtool"; argv[1] = "c"; argv[2] = keychain; argv[3] = NULL; cupsdLoadEnv(envp, MAX_ENV); infofd = open(infofile, O_RDONLY); if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL, NULL, &pid)) { close(infofd); unlink(infofile); return (0); } close(infofd); unlink(infofile); while (waitpid(pid, &status, 0) < 0) if (errno != EINTR) { status = 1; break; } cupsdFinishProcess(pid, command, sizeof(command), NULL); if (status) { if (WIFEXITED(status)) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create SSL server key and certificate - " "the certtool command stopped with status %d!", WEXITSTATUS(status)); else cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create SSL server key and certificate - " "the certtool command crashed on signal %d!", WTERMSIG(status)); } else { cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server certificate file \"%s\"...", ServerCertificate); } return (!status); }