- cupsdSetString(&con->command, CUPS_PHP);
-
- if (options)
- cupsdSetStringf(&con->options, " %s %s", filename, options);
- else
- cupsdSetStringf(&con->options, " %s", filename);
-
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "is_cgi(con=%p(%d), filename=\"%s\", filestats=%p, "
- "type=%s/%s) = 1", con, con->http.fd, filename, filestats,
- type ? type->super : "unknown",
- type ? type->type : "unknown");
- return (1);
- }
-#endif /* HAVE_PHP */
-#ifdef HAVE_PYTHON
- else if (!strcasecmp(type->type, "x-httpd-python"))
- {
- /*
- * "application/x-httpd-python" is a Python page.
- */
-
- cupsdSetString(&con->command, CUPS_PYTHON);
-
- if (options)
- cupsdSetStringf(&con->options, " %s %s", filename, options);
- else
- cupsdSetStringf(&con->options, " %s", filename);
-
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "is_cgi(con=%p(%d), filename=\"%s\", filestats=%p, "
- "type=%s/%s) = 1", con, con->http.fd, filename, filestats,
- type ? type->super : "unknown",
- type ? type->type : "unknown");
- return (1);
- }
-#endif /* HAVE_PYTHON */
-
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "is_cgi(con=%p(%d), filename=\"%s\", filestats=%p, "
- "type=%s/%s) = 0", con, con->http.fd, filename, filestats,
- type ? type->super : "unknown",
- type ? type->type : "unknown");
- return (0);
-}
-
-
-/*
- * 'is_path_absolute()' - Is a path absolute and free of relative elements (i.e. "..").
- */
-
-static int /* O - 0 if relative, 1 if absolute */
-is_path_absolute(const char *path) /* I - Input path */
-{
- /*
- * Check for a leading slash...
- */
-
- if (path[0] != '/')
- return (0);
-
- /*
- * Check for "/.." in the path...
- */
-
- while ((path = strstr(path, "/..")) != NULL)
- {
- if (!path[3] || path[3] == '/')
- return (0);
-
- path ++;
- }
-
- /*
- * If we haven't found any relative paths, return 1 indicating an
- * absolute path...
- */
-
- return (1);
-}
-
-
-#ifdef HAVE_SSL
-/*
- * 'make_certificate()' - Make a self-signed SSL/TLS certificate.
- */
-
-static int /* O - 1 on success, 0 on failure */
-make_certificate(cupsd_client_t *con) /* I - Client connection */
-{
-#if defined(HAVE_LIBSSL) && defined(HAVE_WAITPID)
- int pid, /* Process ID of command */
- status; /* Status of command */
- char command[1024], /* Command */
- *argv[12], /* Command-line arguments */
- *envp[MAX_ENV + 1], /* Environment variables */
- home[1024], /* HOME environment variable */
- infofile[1024], /* Type-in information for cert */
- seedfile[1024]; /* Random number seed file */
- int envc, /* Number of environment variables */
- bytes; /* Bytes written */
- cups_file_t *fp; /* Seed/info file */
- int infofd; /* Info file descriptor */
-
-
- /*
- * Run the "openssl" command to seed the random number generator and
- * generate a self-signed certificate that is good for 10 years:
- *
- * openssl rand -rand seedfile 1
- *
- * openssl req -new -x509 -keyout ServerKey \
- * -out ServerCertificate -days 3650 -nodes
- *
- * The seeding step is crucial in ensuring that the openssl command
- * does not block on systems without sufficient entropy...
- */
-
- if (!cupsFileFind("openssl", getenv("PATH"), 1, command, sizeof(command)))
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "No SSL certificate and openssl command not found!");
- return (0);
- }
-
- if (access("/dev/urandom", 0))
- {
- /*
- * If the system doesn't provide /dev/urandom, then any random source
- * will probably be blocking-style, so generate some random data to
- * use as a seed for the certificate. Note that we have already
- * seeded the random number generator in cupsdInitCerts()...
- */
-
- cupsdLogMessage(CUPSD_LOG_INFO,
- "Seeding the random number generator...");
-
- snprintf(home, sizeof(home), "HOME=%s", TempDir);
-
- /*
- * Write the seed file...
- */
-
- if ((fp = cupsTempFile2(seedfile, sizeof(seedfile))) == NULL)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create seed file %s - %s",
- seedfile, strerror(errno));
- return (0);
- }
-
- for (bytes = 0; bytes < 262144; bytes ++)
- cupsFilePutChar(fp, random());
-
- cupsFileClose(fp);
-
- /*
- * Run the openssl command to seed its random number generator...
- */
-
- argv[0] = "openssl";
- argv[1] = "rand";
- argv[2] = "-rand";
- argv[3] = seedfile;
- argv[4] = "1";
- argv[5] = NULL;
-
- envc = cupsdLoadEnv(envp, MAX_ENV);
- envp[envc++] = home;
- envp[envc] = NULL;
-
- if (!cupsdStartProcess(command, argv, envp, -1, -1, -1, -1, -1, 1, NULL, 0,
- &pid))
- {
- unlink(seedfile);
- return (0);
- }
-
- while (waitpid(pid, &status, 0) < 0)
- if (errno != EINTR)
- {
- status = 1;
- break;
- }
-
- cupsdFinishProcess(pid, command, sizeof(command), NULL);
-
- /*
- * Remove the seed file, as it is no longer needed...
- */
-
- unlink(seedfile);
-
- if (status)
- {
- if (WIFEXITED(status))
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to seed random number generator - "
- "the openssl command stopped with status %d!",
- WEXITSTATUS(status));
- else
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to seed random number generator - "
- "the openssl command crashed on signal %d!",
- WTERMSIG(status));
-
- return (0);
- }
- }
-
- /*
- * Create a file with the certificate information fields...
- *
- * Note: This assumes that the default questions are asked by the openssl
- * 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, ".\n.\n.\n%s\n.\n%s\n%s\n",
- ServerName, ServerName, ServerAdmin);
- cupsFileClose(fp);
-
- cupsdLogMessage(CUPSD_LOG_INFO,
- "Generating SSL server key and certificate...");
-
- argv[0] = "openssl";
- argv[1] = "req";
- argv[2] = "-new";
- argv[3] = "-x509";
- argv[4] = "-keyout";
- argv[5] = ServerKey;
- argv[6] = "-out";
- argv[7] = ServerCertificate;
- argv[8] = "-days";
- argv[9] = "3650";
- argv[10] = "-nodes";
- argv[11] = NULL;
-
- cupsdLoadEnv(envp, MAX_ENV);
-
- infofd = open(infofile, O_RDONLY);
-
- if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL,
- 0, &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 openssl command stopped with status %d!",
- WEXITSTATUS(status));
- else
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to create SSL server key and certificate - "
- "the openssl command crashed on signal %d!",
- WTERMSIG(status));
- }
- else
- {
- cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...",
- ServerKey);
- cupsdLogMessage(CUPSD_LOG_INFO,
- "Created SSL server certificate file \"%s\"...",
- ServerCertificate);
- }
-
- return (!status);
-
-#elif defined(HAVE_GNUTLS)
- gnutls_x509_crt crt; /* Self-signed certificate */
- gnutls_x509_privkey key; /* Encryption key */
- cups_lang_t *language; /* Default language info */
- cups_file_t *fp; /* Key/cert file */
- unsigned char buffer[8192]; /* Buffer for x509 data */
- size_t bytes; /* Number of bytes of data */
- unsigned char serial[4]; /* Serial number buffer */
- time_t curtime; /* Current time */
- int result; /* Result of GNU TLS calls */
-
-
- /*
- * Create the encryption key...
- */
-
- cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key...");
-
- gnutls_x509_privkey_init(&key);
- gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0);
-
- /*
- * Save it...
- */
-
- bytes = sizeof(buffer);
-
- if ((result = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM,
- buffer, &bytes)) < 0)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to export SSL server key - %s",
- gnutls_strerror(result));
- gnutls_x509_privkey_deinit(key);
- return (0);
- }
- else if ((fp = cupsFileOpen(ServerKey, "w")) != NULL)
- {
- cupsFileWrite(fp, (char *)buffer, bytes);
- cupsFileClose(fp);
-
- cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...",
- ServerKey);
- }
- else
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "Unable to create SSL server key file \"%s\" - %s",
- ServerKey, strerror(errno));
- gnutls_x509_privkey_deinit(key);
- return (0);
- }
-
- /*
- * Create the self-signed certificate...
- */
-
- cupsdLogMessage(CUPSD_LOG_INFO, "Generating self-signed SSL certificate...");
-
- language = cupsLangDefault();
- curtime = time(NULL);
- serial[0] = curtime >> 24;
- serial[1] = curtime >> 16;
- serial[2] = curtime >> 8;
- serial[3] = curtime;
-
- gnutls_x509_crt_init(&crt);
- if (strlen(language->language) == 5)
- gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
- language->language + 3, 2);
- else
- gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
- "US", 2);
- gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0,
- ServerName, strlen(ServerName));
- gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0,
- ServerName, strlen(ServerName));
- gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME,
- 0, "Unknown", 7);
- gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0,
- "Unknown", 7);
- gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0,
- "Unknown", 7);
- gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0,
- ServerAdmin, strlen(ServerAdmin));
- gnutls_x509_crt_set_key(crt, key);
- gnutls_x509_crt_set_serial(crt, serial, sizeof(serial));
- gnutls_x509_crt_set_activation_time(crt, curtime);
- gnutls_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400);
- gnutls_x509_crt_set_ca_status(crt, 0);
- gnutls_x509_crt_set_subject_alternative_name(crt, GNUTLS_SAN_DNSNAME,
- ServerName);
- gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0);
- gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_KEY_ENCIPHERMENT);
- gnutls_x509_crt_set_version(crt, 3);
-
- bytes = sizeof(buffer);
- if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0)
- gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes);
-
- gnutls_x509_crt_sign(crt, crt, key);