/*
* "$Id: client.c 7950 2008-09-17 00:21:59Z mike $"
*
- * Client routines for the Common UNIX Printing System (CUPS) scheduler.
+ * Client routines for the CUPS scheduler.
*
- * Copyright 2007-2009 by Apple Inc.
+ * Copyright 2007-2010 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* This file contains Kerberos support code, copyright 2006 by
#include "cupsd.h"
-#ifdef HAVE_CDSASSL
-# include <Security/Security.h>
-# ifdef HAVE_SECIDENTITYSEARCHPRIV_H
-# include <Security/SecIdentitySearchPriv.h>
-# else /* Declare prototype for function in that header... */
-extern OSStatus SecIdentitySearchCreateWithPolicy(SecPolicyRef policy,
- CFStringRef idString, CSSM_KEYUSE keyUsage,
- CFTypeRef keychainOrArray,
- Boolean returnOnlyValidIdentities,
- SecIdentitySearchRef* searchRef);
-# endif /* HAVE_SECIDENTITYSEARCHPRIV_H */
-# ifdef HAVE_SECPOLICYPRIV_H
-# include <Security/SecPolicyPriv.h>
-# else /* Declare prototype for function in that header... */
-extern OSStatus SecPolicySetValue(SecPolicyRef policyRef,
- const CSSM_DATA *value);
-# endif /* HAVE_SECPOLICYPRIV_H */
-# ifdef HAVE_SECBASEPRIV_H
-# include <Security/SecBasePriv.h>
-# else /* Declare prototype for function in that header... */
-extern const char *cssmErrorString(int error);
-# endif /* HAVE_SECBASEPRIV_H */
-#endif /* HAVE_CDSASSL */
-
-#ifdef HAVE_GNUTLS
-# include <gnutls/x509.h>
-#endif /* HAVE_GNUTLS */
-
#ifdef HAVE_TCPD_H
# include <tcpd.h>
#endif /* HAVE_TCPD_H */
int partial; /* Do partial close for SSL? */
#ifdef HAVE_LIBSSL
SSL_CTX *context; /* Context for encryption */
- SSL *conn; /* Connection for encryption */
unsigned long error; /* Error code */
#elif defined(HAVE_GNUTLS)
- http_tls_t *conn; /* TLS connection information */
int error; /* Error code */
gnutls_certificate_server_credentials *credentials;
/* TLS credentials */
# elif defined(HAVE_CDSASSL)
- http_tls_t *conn; /* CDSA connection information */
#endif /* HAVE_LIBSSL */
partial = 1;
# ifdef HAVE_LIBSSL
- conn = (SSL *)(con->http.tls);
- context = SSL_get_SSL_CTX(conn);
+ context = SSL_get_SSL_CTX(con->http.tls);
- switch (SSL_shutdown(conn))
+ switch (SSL_shutdown(con->http.tls))
{
case 1 :
cupsdLogMessage(CUPSD_LOG_DEBUG,
}
SSL_CTX_free(context);
- SSL_free(conn);
+ SSL_free(con->http.tls);
# elif defined(HAVE_GNUTLS)
- conn = (http_tls_t *)(con->http.tls);
- credentials = (gnutls_certificate_server_credentials *)(conn->credentials);
+ credentials = (gnutls_certificate_server_credentials *)(con->http.tls_credentials);
- error = gnutls_bye(conn->session, GNUTLS_SHUT_WR);
+ error = gnutls_bye(con->http.tls, GNUTLS_SHUT_WR);
switch (error)
{
case GNUTLS_E_SUCCESS:
break;
}
- gnutls_deinit(conn->session);
+ gnutls_deinit(con->http.tls);
gnutls_certificate_free_credentials(*credentials);
free(credentials);
- free(conn);
# elif defined(HAVE_CDSASSL)
- conn = (http_tls_t *)(con->http.tls);
-
- while (SSLClose(conn->session) == errSSLWouldBlock)
+ while (SSLClose(con->http.tls) == errSSLWouldBlock)
usleep(1000);
- SSLDisposeContext(conn->session);
+ SSLDisposeContext(con->http.tls);
- if (conn->certsArray)
- CFRelease(conn->certsArray);
+ if (con->http.tls_credentials)
+ CFRelease(con->http.tls_credentials);
- free(conn);
# endif /* HAVE_LIBSSL */
con->http.tls = NULL;
*ptr = '\0';
}
else
- snprintf(locale, sizeof(locale), "%s.%s",
- con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], DefaultCharset);
+ snprintf(locale, sizeof(locale), "%s.UTF-8",
+ con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE]);
con->language = cupsLangGet(locale);
}
break;
}
}
+ else if ((!strncmp(con->uri, "/printers/", 10) ||
+ !strncmp(con->uri, "/classes/", 9)) &&
+ !strcmp(con->uri + strlen(con->uri) - 4, ".png"))
+ {
+ /*
+ * Send icon file - get the real queue name since queue names are
+ * not case sensitive but filenames can be...
+ */
- if ((!strncmp(con->uri, "/admin", 6) &&
- strncmp(con->uri, "/admin/conf/", 12) &&
- strncmp(con->uri, "/admin/log/", 11)) ||
- !strncmp(con->uri, "/printers", 9) ||
- !strncmp(con->uri, "/classes", 8) ||
- !strncmp(con->uri, "/help", 5) ||
- !strncmp(con->uri, "/jobs", 5))
+ con->uri[strlen(con->uri) - 4] = '\0'; /* Drop ".png" */
+
+ if (!strncmp(con->uri, "/printers/", 10))
+ p = cupsdFindPrinter(con->uri + 10);
+ else
+ p = cupsdFindClass(con->uri + 9);
+
+ if (p)
+ snprintf(con->uri, sizeof(con->uri), "/icons/%s.png", p->name);
+ else
+ {
+ if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE))
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+
+ break;
+ }
+ }
+
+ if (!WebInterface)
+ {
+ /*
+ * Web interface is disabled. Show an appropriate message...
+ */
+
+ if (!cupsdSendError(con, HTTP_WEBIF_DISABLED, CUPSD_AUTH_NONE))
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+
+ break;
+ }
+ else if ((!strncmp(con->uri, "/admin", 6) &&
+ strncmp(con->uri, "/admin/conf/", 12) &&
+ strncmp(con->uri, "/admin/log/", 11)) ||
+ !strncmp(con->uri, "/printers", 9) ||
+ !strncmp(con->uri, "/classes", 8) ||
+ !strncmp(con->uri, "/help", 5) ||
+ !strncmp(con->uri, "/jobs", 5))
{
/*
* Send CGI output...
if (!strcmp(con->http.fields[HTTP_FIELD_CONTENT_TYPE],
"application/ipp"))
con->request = ippNew();
+ else if (!WebInterface)
+ {
+ /*
+ * Web interface is disabled. Show an appropriate message...
+ */
+
+ if (!cupsdSendError(con, HTTP_WEBIF_DISABLED, CUPSD_AUTH_NONE))
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+
+ break;
+ }
else if ((!strncmp(con->uri, "/admin", 6) &&
strncmp(con->uri, "/admin/conf/", 12) &&
strncmp(con->uri, "/admin/log/", 11)) ||
break;
}
}
+ else if (!strncmp(con->uri, "/printers/", 10) &&
+ !strcmp(con->uri + strlen(con->uri) - 4, ".png"))
+ {
+ /*
+ * Send PNG file - get the real printer name since printer
+ * names are not case sensitive but filenames can be...
+ */
+
+ con->uri[strlen(con->uri) - 4] = '\0'; /* Drop ".ppd" */
+
+ if ((p = cupsdFindPrinter(con->uri + 10)) != NULL)
+ snprintf(con->uri, sizeof(con->uri), "/icons/%s.png", p->name);
+ else
+ {
+ if (!cupsdSendError(con, HTTP_NOT_FOUND, CUPSD_AUTH_NONE))
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+
+ break;
+ }
+ }
+ else if (!WebInterface)
+ {
+ if (!cupsdSendHeader(con, HTTP_OK, line, CUPSD_AUTH_NONE))
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+
+ if (httpPrintf(HTTP(con), "\r\n") < 0)
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+
+ if (cupsdFlushHeader(con) < 0)
+ {
+ cupsdCloseClient(con);
+ return;
+ }
+
+ con->http.state = HTTP_WAITING;
+ break;
+ }
if ((!strncmp(con->uri, "/admin", 6) &&
strncmp(con->uri, "/admin/conf/", 12) &&
return;
}
}
+ else if (filestats.st_size == 0)
+ {
+ /*
+ * Don't allow empty file...
+ */
+
+ unlink(con->filename);
+ cupsdClearString(&con->filename);
+ }
if (con->command)
{
"CONTENT=\"3;URL=https://%s:%d%s\">\n",
con->servername, con->serverport, con->uri);
}
+ else if (code == HTTP_WEBIF_DISABLED)
+ text = _cupsLangString(con->language,
+ _("The web interface is currently disabled. Run "
+ "\"cupsctl WebInterface=yes\" to enable it."));
else
text = "";
"<HEAD>\n"
"\t<META HTTP-EQUIV=\"Content-Type\" "
"CONTENT=\"text/html; charset=utf-8\">\n"
- "\t<TITLE>%d %s</TITLE>\n"
+ "\t<TITLE>%s - " CUPS_SVERSION "</TITLE>\n"
"\t<LINK REL=\"STYLESHEET\" TYPE=\"text/css\" "
"HREF=\"/cups.css\">\n"
"%s"
"</HEAD>\n"
"<BODY>\n"
- "<H1>%d %s</H1>\n"
+ "<H1>%s</H1>\n"
"<P>%s</P>\n"
"</BODY>\n"
"</HTML>\n",
- code, httpStatus(code), redirect, code, httpStatus(code), text);
+ httpStatus(code), redirect, httpStatus(code), text);
if (httpPrintf(HTTP(con), "Content-Type: text/html; charset=utf-8\r\n") < 0)
return (0);
return (httpPrintf(HTTP(con), "HTTP/%d.%d 100 Continue\r\n\r\n",
con->http.version / 100, con->http.version % 100) > 0);
}
+ else if (code == HTTP_WEBIF_DISABLED)
+ {
+ /*
+ * Treat our special "web interface is disabled" status as "200 OK" for web
+ * browsers.
+ */
+
+ code = HTTP_OK;
+ }
httpFlushWrite(HTTP(con));
* parameter as needed...
*/
- int i; /* Looping var */
- char *auth_key; /* Auth key buffer */
+ char *name, /* Current user name */
+ *auth_key; /* Auth key buffer */
size_t auth_size; /* Size of remaining buffer */
auth_key = auth_str + strlen(auth_str);
auth_size = sizeof(auth_str) - (auth_key - auth_str);
- for (i = 0; i < con->best->num_names; i ++)
+ for (name = (char *)cupsArrayFirst(con->best->names);
+ name;
+ name = (char *)cupsArrayNext(con->best->names))
{
#ifdef HAVE_AUTHORIZATION_H
- if (!strncasecmp(con->best->names[i], "@AUTHKEY(", 9))
+ if (!strncasecmp(name, "@AUTHKEY(", 9))
{
- snprintf(auth_key, auth_size, ", authkey=\"%s\"",
- con->best->names[i] + 9);
+ snprintf(auth_key, auth_size, ", authkey=\"%s\"", name + 9);
/* end parenthesis is stripped in conf.c */
break;
}
else
#endif /* HAVE_AUTHORIZATION_H */
- if (!strcasecmp(con->best->names[i], "@SYSTEM"))
+ if (!strcasecmp(name, "@SYSTEM"))
{
#ifdef HAVE_AUTHORIZATION_H
if (SystemGroupAuthKey)
if (SSL_pending((SSL *)(con->http.tls)))
return (1);
# elif defined(HAVE_GNUTLS)
- if (gnutls_record_check_pending(((http_tls_t *)(con->http.tls))->session))
+ if (gnutls_record_check_pending(con->http.tls))
return (1);
# elif defined(HAVE_CDSASSL)
size_t bytes; /* Bytes that are available */
- if (!SSLGetBufferedReadSize(((http_tls_t *)(con->http.tls))->session,
- &bytes) && bytes > 0)
+ if (!SSLGetBufferedReadSize(con->http.tls, &bytes) && bytes > 0)
return (1);
# endif /* HAVE_LIBSSL */
}
{
# ifdef HAVE_LIBSSL
SSL_CTX *context; /* Context for encryption */
- SSL *conn; /* Connection for encryption */
BIO *bio; /* BIO data */
unsigned long error; /* Error code */
bio = BIO_new(_httpBIOMethods());
BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)HTTP(con));
- conn = SSL_new(context);
- SSL_set_bio(conn, bio, bio);
+ con->http.tls = SSL_new(context);
+ SSL_set_bio(con->http.tls, bio, bio);
- if (SSL_accept(conn) != 1)
+ if (SSL_accept(con->http.tls) != 1)
{
cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to encrypt connection from %s!",
con->http.hostname);
cupsdLogMessage(CUPSD_LOG_ERROR, "%s", ERR_error_string(error, NULL));
SSL_CTX_free(context);
- SSL_free(conn);
+ SSL_free(con->http.tls);
+ con->http.tls = NULL;
return (0);
}
cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
con->http.hostname);
- con->http.tls = conn;
return (1);
# elif defined(HAVE_GNUTLS)
- http_tls_t *conn; /* TLS session object */
int error; /* Error code */
gnutls_certificate_server_credentials *credentials;
/* TLS credentials */
* Create the SSL object and perform the SSL handshake...
*/
- conn = (http_tls_t *)malloc(sizeof(http_tls_t));
-
- if (conn == NULL)
- return (0);
-
credentials = (gnutls_certificate_server_credentials *)
malloc(sizeof(gnutls_certificate_server_credentials));
if (credentials == NULL)
"Unable to encrypt connection from %s - %s",
con->http.hostname, strerror(errno));
- free(conn);
return (0);
}
gnutls_certificate_set_x509_key_file(*credentials, ServerCertificate,
ServerKey, GNUTLS_X509_FMT_PEM);
- gnutls_init(&(conn->session), GNUTLS_SERVER);
- gnutls_set_default_priority(conn->session);
- gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
- gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr)HTTP(con));
- gnutls_transport_set_pull_function(conn->session, _httpReadGNUTLS);
- gnutls_transport_set_push_function(conn->session, _httpWriteGNUTLS);
+ gnutls_init(&con->http.tls), GNUTLS_SERVER);
+ gnutls_set_default_priority(con->http.tls);
+ gnutls_credentials_set(con->http.tls, GNUTLS_CRD_CERTIFICATE, *credentials);
+ gnutls_transport_set_ptr(con->http.tls, (gnutls_transport_ptr)HTTP(con));
+ gnutls_transport_set_pull_function(con->http.tls, _httpReadGNUTLS);
+ gnutls_transport_set_push_function(con->http.tls, _httpWriteGNUTLS);
- error = gnutls_handshake(conn->session);
+ error = gnutls_handshake(con->http.tls);
if (error != GNUTLS_E_SUCCESS)
{
"Unable to encrypt connection from %s - %s",
con->http.hostname, gnutls_strerror(error));
- gnutls_deinit(conn->session);
+ gnutls_deinit(con->http.tls);
gnutls_certificate_free_credentials(*credentials);
- free(conn);
+ con->http.tls = NULL;
free(credentials);
return (0);
}
cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
con->http.hostname);
- conn->credentials = credentials;
- con->http.tls = conn;
+ con->http.tls_credentials = credentials;
return (1);
# elif defined(HAVE_CDSASSL)
OSStatus error; /* Error code */
- http_tls_t *conn; /* CDSA connection information */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "encrypt_client(con=%p(%d))", con,
con->http.fd);
- if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
- return (0);
-
- error = 0;
- conn->session = NULL;
- conn->certsArray = get_cdsa_certificate(con);
+ error = 0;
+ con->http.tls_credentials = get_cdsa_certificate(con);
- if (!conn->certsArray)
+ if (!con->http.tls_credentials)
{
/*
* No keychain (yet), make a self-signed certificate...
*/
if (make_certificate(con))
- conn->certsArray = get_cdsa_certificate(con);
+ con->http.tls_credentials = get_cdsa_certificate(con);
}
- if (!conn->certsArray)
+ if (!con->http.tls_credentials)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Could not find signing key in keychain \"%s\"",
}
if (!error)
- error = SSLNewContext(true, &conn->session);
+ error = SSLNewContext(true, &con->http.tls);
if (!error)
- error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
+ error = SSLSetIOFuncs(con->http.tls, _httpReadCDSA, _httpWriteCDSA);
if (!error)
- error = SSLSetProtocolVersionEnabled(conn->session, kSSLProtocol2, false);
+ error = SSLSetProtocolVersionEnabled(con->http.tls, kSSLProtocol2, false);
if (!error)
- error = SSLSetConnection(conn->session, HTTP(con));
+ error = SSLSetConnection(con->http.tls, HTTP(con));
if (!error)
- error = SSLSetAllowsExpiredCerts(conn->session, true);
+ error = SSLSetAllowsExpiredCerts(con->http.tls, true);
if (!error)
- error = SSLSetAllowsAnyRoot(conn->session, true);
+ error = SSLSetAllowsAnyRoot(con->http.tls, true);
if (!error)
- error = SSLSetCertificate(conn->session, conn->certsArray);
+ error = SSLSetCertificate(con->http.tls, con->http.tls_credentials);
if (!error)
{
* Perform SSL/TLS handshake
*/
- while ((error = SSLHandshake(conn->session)) == errSSLWouldBlock)
+ while ((error = SSLHandshake(con->http.tls)) == errSSLWouldBlock)
usleep(1000);
}
con->http.error = error;
con->http.status = HTTP_ERROR;
- if (conn->session)
- SSLDisposeContext(conn->session);
-
- if (conn->certsArray)
- CFRelease(conn->certsArray);
+ if (con->http.tls)
+ {
+ SSLDisposeContext(con->http.tls);
+ con->http.tls = NULL;
+ }
- free(conn);
+ if (con->http.tls_credentials)
+ {
+ CFRelease(con->http.tls_credentials);
+ con->http.tls_credentials = NULL;
+ }
return (0);
}
cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
con->http.hostname);
- con->http.tls = conn;
+ CFArrayRef peerCerts; /* Peer certificates */
+
+ if (!(error = SSLCopyPeerCertificates(con->http.tls, &peerCerts)) && peerCerts)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates!",
+ (int)CFArrayGetCount(peerCerts));
+ }
+ else
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates!");
+
return (1);
# endif /* HAVE_LIBSSL */
*/
static CFArrayRef /* O - Array of certificates */
-get_cdsa_certificate(cupsd_client_t *con) /* I - Client connection */
+get_cdsa_certificate(
+ cupsd_client_t *con) /* I - Client connection */
{
OSStatus err; /* Error info */
- SecKeychainRef keychain; /* Keychain reference */
- SecIdentitySearchRef search; /* Search reference */
- SecIdentityRef identity; /* Identity */
+ SecKeychainRef keychain = NULL;/* Keychain reference */
+ SecIdentitySearchRef search = NULL; /* Search reference */
+ SecIdentityRef identity = NULL;/* Identity */
CFArrayRef certificates = NULL;
/* Certificate array */
+# if HAVE_SECPOLICYCREATESSL
+ SecPolicyRef policy = NULL; /* Policy ref */
+ CFStringRef servername = NULL;
+ /* Server name */
+ CFMutableDictionaryRef query = NULL; /* Query qualifiers */
+ char localname[1024];/* Local hostname */
+# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
+ SecPolicyRef policy = NULL; /* Policy ref */
+ SecPolicySearchRef policy_search = NULL;
+ /* Policy search ref */
+ CSSM_DATA options; /* Policy options */
+ CSSM_APPLE_TP_SSL_OPTIONS
+ ssl_options; /* SSL Option for hostname */
+ char localname[1024];/* Local hostname */
+# endif /* HAVE_SECPOLICYCREATESSL */
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "get_cdsa_certificate: Looking for certs for \"%s\"...",
+ con->servername);
if ((err = SecKeychainOpen(ServerCertificate, &keychain)))
{
cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\" - %s (%d)",
ServerCertificate, cssmErrorString(err), (int)err);
- return (NULL);
+ goto cleanup;
+ }
+
+# if HAVE_SECPOLICYCREATESSL
+ servername = CFStringCreateWithCString(kCFAllocatorDefault, con->servername,
+ kCFStringEncodingUTF8);
+
+ if ((policy = SecPolicyCreateSSL(1, servername)) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference");
+ goto cleanup;
+ }
+
+ if (servername)
+ CFRelease(servername);
+
+ if (!(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks)))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create query dictionary");
+ goto cleanup;
+ }
+
+ CFDictionaryAddValue(query, kSecClass, kSecClassIdentity);
+ CFDictionaryAddValue(query, kSecMatchPolicy, policy);
+ CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue);
+ CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitOne);
+
+ err = SecItemCopyMatching(query, (CFTypeRef *)&identity);
+
+ if (err && DNSSDHostName)
+ {
+ /*
+ * Search for the connection server name failed; try the DNS-SD .local
+ * hostname instead...
+ */
+
+ snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "get_cdsa_certificate: Looking for certs for \"%s\"...",
+ localname);
+
+ servername = CFStringCreateWithCString(kCFAllocatorDefault, localname,
+ kCFStringEncodingUTF8);
+
+ CFRelease(policy);
+
+ if ((policy = SecPolicyCreateSSL(1, servername)) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference");
+ goto cleanup;
+ }
+
+ if (servername)
+ CFRelease(servername);
+
+ CFDictionarySetValue(query, kSecMatchPolicy, policy);
+
+ err = SecItemCopyMatching(query, (CFTypeRef *)&identity);
+ }
+
+ if (err)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Cannot find signing key in keychain \"%s\": %s (%d)",
+ ServerCertificate, cssmErrorString(err), (int)err);
+ goto cleanup;
}
-# if HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY
+# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
/*
- * Use a policy to search for valid certificates who's common name matches the
+ * Use a policy to search for valid certificates whose common name matches the
* servername...
*/
- SecPolicySearchRef policy_search; /* Policy search ref */
- SecPolicyRef policy; /* Policy ref */
- CSSM_DATA options; /* Policy options */
- CSSM_APPLE_TP_SSL_OPTIONS
- ssl_options; /* SSL Option for hostname */
-
-
- if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL,
+ if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL,
NULL, &policy_search))
{
cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create a policy search reference");
- CFRelease(keychain);
- return (NULL);
+ goto cleanup;
}
if (SecPolicySearchCopyNext(policy_search, &policy))
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Cannot find a policy to use for searching");
- CFRelease(keychain);
- CFRelease(policy_search);
- return (NULL);
+ goto cleanup;
}
memset(&ssl_options, 0, sizeof(ssl_options));
ssl_options.ServerName = con->servername;
ssl_options.ServerNameLen = strlen(con->servername);
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "get_cdsa_certificate: Looking for certs for \"%s\"...",
- con->servername);
-
options.Data = (uint8 *)&ssl_options;
options.Length = sizeof(ssl_options);
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"Cannot set policy value to use for searching");
- CFRelease(keychain);
- CFRelease(policy_search);
- return (NULL);
+ goto cleanup;
+ }
+
+ if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN,
+ keychain, FALSE, &search)))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Cannot create identity search reference: %s (%d)",
+ cssmErrorString(err), (int)err);
+ goto cleanup;
+ }
+
+ err = SecIdentitySearchCopyNext(search, &identity);
+
+ if (err && DNSSDHostName)
+ {
+ /*
+ * Search for the connection server name failed; try the DNS-SD .local
+ * hostname instead...
+ */
+
+ snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
+
+ ssl_options.ServerName = localname;
+ ssl_options.ServerNameLen = strlen(localname);
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "get_cdsa_certificate: Looking for certs for \"%s\"...",
+ localname);
+
+ if (SecPolicySetValue(policy, &options))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Cannot set policy value to use for searching");
+ goto cleanup;
+ }
+
+ CFRelease(search);
+ search = NULL;
+ if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN,
+ keychain, FALSE, &search)))
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "Cannot create identity search reference: %s (%d)",
+ cssmErrorString(err), (int)err);
+ goto cleanup;
+ }
+
+ err = SecIdentitySearchCopyNext(search, &identity);
+
+ }
+
+ if (err)
+ {
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Cannot find signing key in keychain \"%s\": %s (%d)",
+ ServerCertificate, cssmErrorString(err), (int)err);
+ goto cleanup;
}
- err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN,
- keychain, FALSE, &search);
# else
/*
* Assume there is exactly one SecIdentity in the keychain...
*/
- err = SecIdentitySearchCreate(keychain, CSSM_KEYUSE_SIGN, &search);
-# endif /* HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY */
-
- if (err)
+ if ((err = SecIdentitySearchCreate(keychain, CSSM_KEYUSE_SIGN, &search)))
+ {
cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Cannot create keychain search reference: %s (%d)",
- cssmErrorString(err), (int)err);
- else
+ "Cannot create identity search reference (%d)", (int)err);
+ goto cleanup;
+ }
+
+ if ((err = SecIdentitySearchCopyNext(search, &identity)))
{
- if ((err = SecIdentitySearchCopyNext(search, &identity)))
- {
- cupsdLogMessage(CUPSD_LOG_DEBUG,
- "Cannot find signing key in keychain \"%s\": %s (%d)",
- ServerCertificate, cssmErrorString(err), (int)err);
- }
- else
- {
- if (CFGetTypeID(identity) != SecIdentityGetTypeID())
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "SecIdentitySearchCopyNext CFTypeID failure!");
- else
- {
- if ((certificates = CFArrayCreate(NULL, (const void **)&identity,
- 1, &kCFTypeArrayCallBacks)) == NULL)
- cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array");
- }
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "Cannot find signing key in keychain \"%s\": %s (%d)",
+ ServerCertificate, cssmErrorString(err), (int)err);
+ goto cleanup;
+ }
+# endif /* HAVE_SECPOLICYCREATESSL */
- CFRelease(identity);
- }
+ if (CFGetTypeID(identity) != SecIdentityGetTypeID())
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure!");
+ goto cleanup;
+ }
- CFRelease(search);
+ if ((certificates = CFArrayCreate(NULL, (const void **)&identity,
+ 1, &kCFTypeArrayCallBacks)) == NULL)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array");
+ goto cleanup;
}
-# if HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY
- CFRelease(policy);
- CFRelease(policy_search);
-# endif /* HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY */
+ cleanup :
+
+ if (keychain)
+ CFRelease(keychain);
+ if (search)
+ CFRelease(search);
+ if (identity)
+ CFRelease(identity);
+
+# if HAVE_SECPOLICYCREATESSL
+ if (policy)
+ CFRelease(policy);
+ if (query)
+ CFRelease(query);
+# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
+ if (policy)
+ CFRelease(policy);
+ if (policy_search)
+ CFRelease(policy_search);
+# endif /* HAVE_SECPOLICYCREATESSL */
return (certificates);
}
language[0] = '\0';
- if (!strncmp(con->uri, "/ppd/", 5))
+ if (!strncmp(con->uri, "/ppd/", 5) && !strchr(con->uri + 5, '/'))
snprintf(filename, len, "%s%s", ServerRoot, con->uri);
+ else if (!strncmp(con->uri, "/icons/", 7) && !strchr(con->uri + 7, '/'))
+ {
+ snprintf(filename, len, "%s/%s", CacheDir, con->uri + 7);
+ if (access(filename, F_OK) < 0)
+ snprintf(filename, len, "%s/images/generic.png", DocumentRoot);
+ }
else if (!strncmp(con->uri, "/rss/", 5) && !strchr(con->uri + 5, '/'))
snprintf(filename, len, "%s/rss/%s", CacheDir, con->uri + 5);
else if (!strncmp(con->uri, "/admin/conf/", 12))
*/
if ((status = stat(filename, filestats)) != 0 && language[0] &&
+ strncmp(con->uri, "/icons/", 7) &&
strncmp(con->uri, "/ppd/", 5) &&
+ strncmp(con->uri, "/rss/", 5) &&
strncmp(con->uri, "/admin/conf/", 12) &&
strncmp(con->uri, "/admin/log/", 11))
{
*argv[4], /* Command-line arguments */
*envp[MAX_ENV + 1], /* Environment variables */
keychain[1024], /* Keychain argument */
- infofile[1024]; /* Type-in information for cert */
+ infofile[1024], /* Type-in information for cert */
+ localname[1024], /* Local hostname */
+ *servername; /* Name of server in cert */
cups_file_t *fp; /* Seed/info file */
int infofd; /* Info file descriptor */
+ if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName)
+ {
+ snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
+ servername = localname;
+ }
+ else
+ servername = con->servername;
+
/*
* Run the "certtool" command to generate a self-signed certificate...
*/
return (0);
}
- cupsFilePrintf(fp, "%s\nr\n\ny\nb\ns\ny\n%s\n\n\n\n\n%s\ny\n",
- con->servername, con->servername, ServerAdmin);
+ cupsFilePrintf(fp, "%s\nr\n\ny\nb\ns\ny\n%s\n\n\n\n\n%s\ny\n",
+ servername, servername, ServerAdmin);
cupsFileClose(fp);
cupsdLogMessage(CUPSD_LOG_INFO,
char argbuf[10240], /* Argument buffer */
*argv[100], /* Argument strings */
*envp[MAX_ENV + 20]; /* Environment variables */
- char auth_type[256], /* CUPSD_AUTH_TYPE environment variable */
+ char auth_type[256], /* AUTH_TYPE environment variable */
content_length[1024], /* CONTENT_LENGTH environment variable */
content_type[1024], /* CONTENT_TYPE environment variable */
http_cookie[32768], /* HTTP_COOKIE environment variable */
argv[0] = command;
if (options)
- strlcpy(argbuf, options, sizeof(argbuf));
+ {
+ commptr = options;
+ if (*commptr == ' ')
+ commptr ++;
+ strlcpy(argbuf, commptr, sizeof(argbuf));
+ }
else
argbuf[0] = '\0';
if (con->username[0])
{
- snprintf(auth_type, sizeof(auth_type), "CUPSD_AUTH_TYPE=%s",
+ snprintf(auth_type, sizeof(auth_type), "AUTH_TYPE=%s",
httpGetField(HTTP(con), HTTP_FIELD_AUTHORIZATION));
if ((uriptr = strchr(auth_type + 10, ' ')) != NULL)