/*
- * "$Id: client.c 5367 2006-04-02 19:00:00Z mike $"
+ * "$Id: client.c 5630 2006-06-05 18:42:53Z mike $"
*
* Client routines for the Common UNIX Printing System (CUPS) scheduler.
*
* is_path_absolute() - Is a path absolute and free of relative elements.
* make_certificate() - Make a self-signed SSL/TLS certificate.
* pipe_command() - Pipe the output of a command to the remote client.
- * send_file() - Send a file via HTTP.
+ * write_file() - Send a file via HTTP.
*/
/*
#ifdef HAVE_CDSASSL
# include <Security/Security.h>
+# ifdef HAVE_SECBASEPRIV_H
+# include <Security/SecBasePriv.h>
+# else
+ extern const char *cssmErrorString(int error);
+# endif /* HAVE_SECBASEPRIV_H */
#endif /* HAVE_CDSASSL */
#ifdef HAVE_GNUTLS
# include <gnutls/x509.h>
#endif /* HAVE_GNUTLS */
static int pipe_command(cupsd_client_t *con, int infile, int *outfile,
char *command, char *options, int root);
-static int send_file(cupsd_client_t *con, http_status_t code,
- char *filename, char *type,
- struct stat *filestats);
+static int write_file(cupsd_client_t *con, http_status_t code,
+ char *filename, char *type,
+ struct stat *filestats);
/*
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 */
+ 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 */
free(conn);
# elif defined(HAVE_CDSASSL)
- while (SSLClose((SSLContextRef)con->http.tls) == errSSLWouldBlock)
+ conn = (http_tls_t *)(con->http.tls);
+
+ while (SSLClose(conn->session) == errSSLWouldBlock)
usleep(1000);
- SSLDisposeContext((SSLContextRef)con->http.tls);
+ SSLDisposeContext(conn->session);
+
+ if (conn->certsArray)
+ CFRelease(conn->certsArray);
+
+ free(conn);
# endif /* HAVE_LIBSSL */
con->http.tls = NULL;
con->start = time(NULL);
con->operation = con->http.state;
- cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdReadClient: %d %s %s HTTP/%d.%d", con->http.fd,
- operation, con->uri,
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdReadClient: %d %s %s HTTP/%d.%d",
+ con->http.fd, operation, con->uri,
con->http.version / 100, con->http.version % 100);
con->http.status = HTTP_OK;
snprintf(locale, sizeof(locale), "%s.%s",
con->http.fields[HTTP_FIELD_ACCEPT_LANGUAGE], DefaultCharset);
+ cupsdLogMessage(CUPSD_LOG_DEBUG,
+ "cupsdReadClient: %d Browser asked for language \"%s\"...",
+ con->http.fd, locale);
+
con->language = cupsLangGet(locale);
}
else
else
snprintf(line, sizeof(line), "%s/%s", type->super, type->type);
- if (!send_file(con, HTTP_OK, filename, line, &filestats))
+ if (!write_file(con, HTTP_OK, filename, line, &filestats))
return (cupsdCloseClient(con));
}
}
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"cupsdReadClient: %d command=\"%s\", "
"options = \"%s\"",
- con->http.fd, con->command, con->options);
+ con->http.fd, con->command,
+ con->options ? con->options : "(null)");
if (con->http.version <= HTTP_1_0)
con->http.keep_alive = HTTP_KEEPALIVE_OFF;
if (con->filename)
+ {
fd = open(con->filename, O_RDONLY);
- else
- fd = open("/dev/null", O_RDONLY);
- if (fd < 0)
- {
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "cupsdSendCommand: %d Unable to open \"%s\" for reading: %s",
- con->http.fd, con->filename ? con->filename : "/dev/null",
- strerror(errno));
- return (0);
- }
+ if (fd < 0)
+ {
+ cupsdLogMessage(CUPSD_LOG_ERROR,
+ "cupsdSendCommand: %d Unable to open \"%s\" for reading: %s",
+ con->http.fd, con->filename ? con->filename : "/dev/null",
+ strerror(errno));
+ return (0);
+ }
- fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+ fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
+ }
+ else
+ fd = -1;
con->pipe_pid = pipe_command(con, fd, &(con->file), command, options, root);
- close(fd);
+ if (fd >= 0)
+ close(fd);
cupsdLogMessage(CUPSD_LOG_INFO, "Started \"%s\" (pid=%d)", command,
con->pipe_pid);
while (*ptr != '\0' && *ptr != ';')
ptr ++;
}
+ else
+ ptr ++;
}
cupsdLogMessage(CUPSD_LOG_DEBUG2,
* Create the SSL object and perform the SSL handshake...
*/
- conn = (http_tls_t *)malloc(sizeof(gnutls_session));
+ conn = (http_tls_t *)malloc(sizeof(http_tls_t));
if (conn == NULL)
return (0);
return (1);
# elif defined(HAVE_CDSASSL)
- OSStatus error; /* Error info */
- SSLContextRef conn; /* New connection */
- CFArrayRef certificatesArray; /* Array containing certificates */
- int allowExpired; /* Allow expired certificates? */
- int allowAnyRoot; /* Allow any root certificate? */
+ OSStatus error; /* Error code */
+ http_tls_t *conn; /* CDSA connection information */
+ cdsa_conn_ref_t u; /* Connection reference union */
- conn = NULL;
- error = SSLNewContext(true, &conn);
- allowExpired = 1;
- allowAnyRoot = 1;
+ if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
+ return (0);
- certificatesArray = get_cdsa_server_certs();
+ error = 0;
+ conn->session = NULL;
+ conn->certsArray = get_cdsa_server_certs();
- if (!certificatesArray)
+ if (!conn->certsArray)
{
cupsdLogMessage(CUPSD_LOG_ERROR,
"EncryptClient: Could not find signing key in keychain "
}
if (!error)
- error = SSLSetIOFuncs(conn, _httpReadCDSA, _httpWriteCDSA);
+ error = SSLNewContext(true, &conn->session);
if (!error)
- error = SSLSetProtocolVersion(conn, kSSLProtocol3);
+ error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
if (!error)
- error = SSLSetConnection(conn, (SSLConnectionRef)con->http.fd);
+ error = SSLSetProtocolVersionEnabled(conn->session, kSSLProtocol2, false);
if (!error)
- error = SSLSetPeerDomainName(conn, ServerName, strlen(ServerName) + 1);
+ {
+ /*
+ * Use a union to resolve warnings about int/pointer size mismatches...
+ */
- /* have to do these options before setting server certs */
- if (!error && allowExpired)
- error = SSLSetAllowsExpiredCerts(conn, true);
+ u.connection = NULL;
+ u.sock = con->http.fd;
+ error = SSLSetConnection(conn->session, u.connection);
+ }
- if (!error && allowAnyRoot)
- error = SSLSetAllowsAnyRoot(conn, true);
+ if (!error)
+ error = SSLSetAllowsExpiredCerts(conn->session, true);
if (!error)
- error = SSLSetCertificate(conn, certificatesArray);
+ error = SSLSetAllowsAnyRoot(conn->session, true);
- if (certificatesArray)
- {
- CFRelease(certificatesArray);
- certificatesArray = NULL;
- }
+ if (!error)
+ error = SSLSetCertificate(conn->session, conn->certsArray);
if (!error)
{
* Perform SSL/TLS handshake
*/
- while ((error = SSLHandshake(conn)) == errSSLWouldBlock)
+ while ((error = SSLHandshake(conn->session)) == errSSLWouldBlock)
usleep(1000);
}
"encrypt_client: Unable to encrypt connection from %s!",
con->http.hostname);
- cupsdLogMessage(CUPSD_LOG_ERROR,
- "encrypt_client: CDSA error code is %d", (int)error);
+ cupsdLogMessage(CUPSD_LOG_ERROR, "encrypt_client: %s (%d)",
+ cssmErrorString(error), (int)error);
con->http.error = error;
con->http.status = HTTP_ERROR;
- if (conn != NULL)
- SSLDisposeContext(conn);
+ if (conn->session)
+ SSLDisposeContext(conn->session);
+
+ if (conn->certsArray)
+ CFRelease(conn->certsArray);
+
+ free(conn);
return (0);
}
cupsdLogMessage(CUPSD_LOG_DEBUG2,
"pipe_command: command=\"%s\", options=\"%s\"",
- command, options);
+ command, options ? options : "(null)");
argv[0] = command;
query_string = NULL;
* Tell the CGI if we are using encryption...
*/
- if (con->http.encryption == HTTP_ENCRYPT_ALWAYS)
+ if (con->http.tls)
envp[envc ++] = "HTTPS=ON";
/*
/*
- * 'send_file()' - Send a file via HTTP.
+ * 'write_file()' - Send a file via HTTP.
*/
static int /* O - 0 on failure, 1 on success */
-send_file(cupsd_client_t *con, /* I - Client connection */
- http_status_t code, /* I - HTTP status */
- char *filename, /* I - Filename */
- char *type, /* I - File type */
- struct stat *filestats) /* O - File information */
+write_file(cupsd_client_t *con, /* I - Client connection */
+ http_status_t code, /* I - HTTP status */
+ char *filename, /* I - Filename */
+ char *type, /* I - File type */
+ struct stat *filestats) /* O - File information */
{
con->file = open(filename, O_RDONLY);
- cupsdLogMessage(CUPSD_LOG_DEBUG, "send_file: %d file=%d", con->http.fd,
+ cupsdLogMessage(CUPSD_LOG_DEBUG, "write_file: %d file=%d", con->http.fd,
con->file);
if (con->file < 0)
con->http._data_remaining = INT_MAX;
cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "send_file: Adding fd %d to OutputSet...", con->http.fd);
+ "write_file: Adding fd %d to OutputSet...", con->http.fd);
FD_SET(con->http.fd, OutputSet);
/*
- * End of "$Id: client.c 5367 2006-04-02 19:00:00Z mike $".
+ * End of "$Id: client.c 5630 2006-06-05 18:42:53Z mike $".
*/