12264Sjacobs /* 22264Sjacobs * CDDL HEADER START 32264Sjacobs * 42264Sjacobs * The contents of this file are subject to the terms of the 52264Sjacobs * Common Development and Distribution License (the "License"). 62264Sjacobs * You may not use this file except in compliance with the License. 72264Sjacobs * 82264Sjacobs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 92264Sjacobs * or http://www.opensolaris.org/os/licensing. 102264Sjacobs * See the License for the specific language governing permissions 112264Sjacobs * and limitations under the License. 122264Sjacobs * 132264Sjacobs * When distributing Covered Code, include this CDDL HEADER in each 142264Sjacobs * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 152264Sjacobs * If applicable, add the following below this CDDL HEADER, with the 162264Sjacobs * fields enclosed by brackets "[]" replaced with your own identifying 172264Sjacobs * information: Portions Copyright [yyyy] [name of copyright owner] 182264Sjacobs * 192264Sjacobs * CDDL HEADER END 202264Sjacobs */ 212264Sjacobs 222264Sjacobs /* 23*8569SJonathan.Ca@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 242264Sjacobs * Use is subject to license terms. 252264Sjacobs * 262264Sjacobs */ 272264Sjacobs 282264Sjacobs /* $Id: ipp-support.c 148 2006-04-25 16:54:17Z njacobs $ */ 292264Sjacobs 302264Sjacobs 312264Sjacobs #include <papi_impl.h> 322264Sjacobs #include <stdlib.h> 332264Sjacobs #include <pwd.h> 342264Sjacobs #include <locale.h> 352264Sjacobs #include <errno.h> 362264Sjacobs #include <fcntl.h> 372264Sjacobs #include <sys/stat.h> 382264Sjacobs #include <md5.h> 392264Sjacobs 402264Sjacobs #include <config-site.h> 412264Sjacobs 423125Sjacobs #include <ipp.h> 433125Sjacobs 443917Sjacobs static void ipp_add_printer_uri(service_t *svc, char *name, 453917Sjacobs papi_attribute_t ***op); 463917Sjacobs 472264Sjacobs papi_status_t 482264Sjacobs http_to_papi_status(http_status_t status) 492264Sjacobs { 502264Sjacobs switch (status) { 512264Sjacobs case HTTP_OK: 522264Sjacobs return (PAPI_OK); 532264Sjacobs case HTTP_BAD_REQUEST: 542264Sjacobs return (PAPI_BAD_REQUEST); 552264Sjacobs case HTTP_UNAUTHORIZED: 562264Sjacobs case HTTP_FORBIDDEN: 572264Sjacobs return (PAPI_NOT_AUTHORIZED); 582264Sjacobs case HTTP_NOT_FOUND: 592264Sjacobs return (PAPI_NOT_FOUND); 602264Sjacobs case HTTP_GONE: 612264Sjacobs return (PAPI_GONE); 622264Sjacobs case HTTP_SERVICE_UNAVAILABLE: 632264Sjacobs return (PAPI_SERVICE_UNAVAILABLE); 642264Sjacobs default: 652264Sjacobs return ((papi_status_t)status); 662264Sjacobs } 672264Sjacobs } 682264Sjacobs 692264Sjacobs papi_status_t 702264Sjacobs ipp_to_papi_status(uint16_t status) 712264Sjacobs { 722264Sjacobs switch (status) { 732264Sjacobs case IPP_OK: 742264Sjacobs return (PAPI_OK); 752264Sjacobs case IPP_OK_IGNORED_ATTRIBUTES: 762264Sjacobs return (PAPI_OK); 772264Sjacobs case IPP_OK_CONFLICTING_ATTRIBUTES: 782264Sjacobs return (PAPI_OK); 792264Sjacobs case IPP_OK_IGNORED_SUBSCRIPTIONS: 802264Sjacobs return (PAPI_OK_IGNORED_SUBSCRIPTIONS); 812264Sjacobs case IPP_OK_IGNORED_NOTIFICATIONS: 822264Sjacobs return (PAPI_OK_IGNORED_NOTIFICATIONS); 832264Sjacobs case IPP_CERR_BAD_REQUEST: 842264Sjacobs return (PAPI_BAD_REQUEST); 852264Sjacobs case IPP_CERR_FORBIDDEN: 862264Sjacobs return (PAPI_FORBIDDEN); 872264Sjacobs case IPP_CERR_NOT_AUTHENTICATED: 882264Sjacobs return (PAPI_NOT_AUTHENTICATED); 892264Sjacobs case IPP_CERR_NOT_AUTHORIZED: 902264Sjacobs return (PAPI_NOT_AUTHORIZED); 912264Sjacobs case IPP_CERR_NOT_POSSIBLE: 922264Sjacobs return (PAPI_NOT_POSSIBLE); 932264Sjacobs case IPP_CERR_TIMEOUT: 942264Sjacobs return (PAPI_TIMEOUT); 952264Sjacobs case IPP_CERR_NOT_FOUND: 962264Sjacobs return (PAPI_NOT_FOUND); 972264Sjacobs case IPP_CERR_GONE: 982264Sjacobs return (PAPI_GONE); 992264Sjacobs case IPP_CERR_REQUEST_ENTITY: 1002264Sjacobs return (PAPI_REQUEST_ENTITY); 1012264Sjacobs case IPP_CERR_REQUEST_VALUE: 1022264Sjacobs return (PAPI_REQUEST_VALUE); 1032264Sjacobs case IPP_CERR_DOCUMENT_FORMAT: 1042264Sjacobs return (PAPI_DOCUMENT_FORMAT); 1052264Sjacobs case IPP_CERR_ATTRIBUTES: 1062264Sjacobs return (PAPI_ATTRIBUTES); 1072264Sjacobs case IPP_CERR_URI_SCHEME: 1082264Sjacobs return (PAPI_URI_SCHEME); 1092264Sjacobs case IPP_CERR_CHARSET: 1102264Sjacobs return (PAPI_CHARSET); 1112264Sjacobs case IPP_CERR_CONFLICT: 1122264Sjacobs return (PAPI_CONFLICT); 1132264Sjacobs case IPP_CERR_COMPRESSION_NOT_SUPPORTED: 1142264Sjacobs return (PAPI_COMPRESSION_NOT_SUPPORTED); 1152264Sjacobs case IPP_CERR_COMPRESSION_ERROR: 1162264Sjacobs return (PAPI_COMPRESSION_ERROR); 1172264Sjacobs case IPP_CERR_DOCUMENT_FORMAT_ERROR: 1182264Sjacobs return (PAPI_DOCUMENT_FORMAT_ERROR); 1192264Sjacobs case IPP_CERR_DOCUMENT_ACCESS_ERROR: 1202264Sjacobs return (PAPI_DOCUMENT_ACCESS_ERROR); 1212264Sjacobs case IPP_CERR_ATTRIBUTES_NOT_SETTABLE: 1222264Sjacobs return (PAPI_ATTRIBUTES_NOT_SETTABLE); 1232264Sjacobs case IPP_CERR_IGNORED_ALL_SUBSCRIPTIONS: 1242264Sjacobs return (PAPI_IGNORED_ALL_SUBSCRIPTIONS); 1252264Sjacobs case IPP_CERR_TOO_MANY_SUBSCRIPTIONS: 1262264Sjacobs return (PAPI_TOO_MANY_SUBSCRIPTIONS); 1272264Sjacobs case IPP_CERR_IGNORED_ALL_NOTIFICATIONS: 1282264Sjacobs return (PAPI_IGNORED_ALL_NOTIFICATIONS); 1292264Sjacobs case IPP_CERR_PRINT_SUPPORT_FILE_NOT_FOUND: 1302264Sjacobs return (PAPI_PRINT_SUPPORT_FILE_NOT_FOUND); 1312264Sjacobs case IPP_SERR_INTERNAL: 1322264Sjacobs return (PAPI_INTERNAL_ERROR); 1332264Sjacobs case IPP_SERR_OPERATION_NOT_SUPPORTED: 1342264Sjacobs return (PAPI_OPERATION_NOT_SUPPORTED); 1352264Sjacobs case IPP_SERR_SERVICE_UNAVAILABLE: 1362264Sjacobs return (PAPI_SERVICE_UNAVAILABLE); 1372264Sjacobs case IPP_SERR_VERSION_NOT_SUPPORTED: 1382264Sjacobs return (PAPI_VERSION_NOT_SUPPORTED); 1392264Sjacobs case IPP_SERR_DEVICE_ERROR: 1402264Sjacobs return (PAPI_DEVICE_ERROR); 1412264Sjacobs case IPP_SERR_TEMPORARY_ERROR: 1422264Sjacobs return (PAPI_TEMPORARY_ERROR); 1432264Sjacobs case IPP_SERR_NOT_ACCEPTING: 1442264Sjacobs return (PAPI_NOT_ACCEPTING); 1452264Sjacobs case IPP_SERR_BUSY: 1462264Sjacobs case IPP_SERR_CANCELLED: 1472264Sjacobs default: 1482264Sjacobs return (PAPI_TEMPORARY_ERROR); 1492264Sjacobs } 1502264Sjacobs } 1512264Sjacobs 1522264Sjacobs void 1532264Sjacobs ipp_initialize_request(service_t *svc, papi_attribute_t ***request, 1542264Sjacobs uint16_t operation) 1552264Sjacobs { 1562264Sjacobs papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, 157*8569SJonathan.Ca@Sun.COM "version-major", 1); 1582264Sjacobs papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, 159*8569SJonathan.Ca@Sun.COM "version-minor", 1); 1602264Sjacobs papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, 161*8569SJonathan.Ca@Sun.COM "request-id", (short)lrand48()); 1622264Sjacobs papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, 163*8569SJonathan.Ca@Sun.COM "operation-id", operation); 1642264Sjacobs } 1652264Sjacobs 1662264Sjacobs void 1672264Sjacobs ipp_initialize_operational_attributes(service_t *svc, papi_attribute_t ***op, 1683917Sjacobs char *printer, int job_id) 1692264Sjacobs { 1702264Sjacobs char *charset = "utf-8"; /* default to UTF-8 encoding */ 1712264Sjacobs char *language = setlocale(LC_ALL, ""); 1722264Sjacobs char *user = "nobody"; 1732264Sjacobs struct passwd *pw = NULL; 1742264Sjacobs 1752264Sjacobs /* 1762264Sjacobs * All IPP requests must contain the following: 1772264Sjacobs * attributes-charset (UTF-8) 1782264Sjacobs * attributes-natural-language (our current locale) 1793917Sjacobs * (object identifier) printer-uri/job-id or job-uri 1803917Sjacobs * requesting-user-name (process user or none) 1812264Sjacobs */ 1822264Sjacobs papiAttributeListAddString(op, PAPI_ATTR_EXCL, 183*8569SJonathan.Ca@Sun.COM "attributes-charset", charset); 1842264Sjacobs 1852264Sjacobs papiAttributeListAddString(op, PAPI_ATTR_EXCL, 186*8569SJonathan.Ca@Sun.COM "attributes-natural-language", language); 1872264Sjacobs 1883917Sjacobs if (printer != NULL) 1893917Sjacobs ipp_add_printer_uri(svc, printer, op); 1903917Sjacobs 1913917Sjacobs if ((printer != NULL) && (job_id >= 0)) 1923917Sjacobs papiAttributeListAddInteger(op, PAPI_ATTR_EXCL, 193*8569SJonathan.Ca@Sun.COM "job-id", job_id); 1943917Sjacobs 1952264Sjacobs if ((pw = getpwuid(getuid())) != NULL) 1962264Sjacobs user = pw->pw_name; 1972264Sjacobs /* 1982264Sjacobs * if our euid is 0 "super user", we will allow the system supplied 1992264Sjacobs * user name to be overridden, if the requestor wants to. 2002264Sjacobs */ 2012264Sjacobs if (geteuid() == 0) { 2022264Sjacobs if (svc->user != NULL) 2032264Sjacobs user = svc->user; 2042264Sjacobs } 2052264Sjacobs papiAttributeListAddString(op, PAPI_ATTR_REPLACE, 206*8569SJonathan.Ca@Sun.COM "requesting-user-name", user); 2072264Sjacobs } 2082264Sjacobs 2092264Sjacobs #ifndef OPID_CUPS_GET_DEFAULT /* for servers that will enumerate */ 2102264Sjacobs #define OPID_CUPS_GET_DEFAULT 0x4001 2112264Sjacobs #endif /* OPID_CUPS_GET_DEFAULT */ 2122264Sjacobs 2132264Sjacobs static papi_status_t 2142264Sjacobs _default_destination(service_t *svc, char **uri) 2152264Sjacobs { 2162264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 2172264Sjacobs printer_t *p = NULL; 2182264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 2192264Sjacobs char *tmp = NULL; 2202264Sjacobs 2212264Sjacobs if ((svc == NULL) || (uri == NULL)) 2222264Sjacobs return (PAPI_BAD_ARGUMENT); 2232264Sjacobs 2242264Sjacobs /* we must be connected to find the default destination */ 2252264Sjacobs if (svc->connection == NULL) 2262264Sjacobs return (PAPI_NOT_POSSIBLE); 2272264Sjacobs 2282264Sjacobs if ((p = calloc(1, sizeof (*p))) == NULL) 2292264Sjacobs return (PAPI_TEMPORARY_ERROR); 2302264Sjacobs 2312264Sjacobs ipp_initialize_request(svc, &request, OPID_CUPS_GET_DEFAULT); 2323917Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL, -1); 2332264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_APPEND, 234*8569SJonathan.Ca@Sun.COM "requested-attributes", "printer-uri-supported"); 2352264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 236*8569SJonathan.Ca@Sun.COM "operational-attributes-group", op); 2372264Sjacobs papiAttributeListFree(op); 2382264Sjacobs result = ipp_send_request(svc, request, &response); 2392264Sjacobs papiAttributeListFree(request); 2402264Sjacobs 2412264Sjacobs op = NULL; 2422264Sjacobs papiAttributeListGetCollection(response, NULL, 243*8569SJonathan.Ca@Sun.COM "printer-attributes-group", &op); 2442264Sjacobs 2452264Sjacobs if (uri != NULL) { 2462264Sjacobs char *tmp = NULL; 2472264Sjacobs 2482264Sjacobs papiAttributeListGetString(op, NULL, "printer-uri", &tmp); 2492264Sjacobs papiAttributeListGetString(op, NULL, 250*8569SJonathan.Ca@Sun.COM "printer-uri-supported", &tmp); 2512264Sjacobs if (tmp != NULL) 2522264Sjacobs *uri = strdup(tmp); 2532264Sjacobs } 2542264Sjacobs 2552264Sjacobs papiAttributeListFree(response); 2562264Sjacobs 2572264Sjacobs return (result); 2582264Sjacobs } 2592264Sjacobs 2603917Sjacobs static void 2612264Sjacobs ipp_add_printer_uri(service_t *svc, char *name, papi_attribute_t ***op) 2622264Sjacobs { 2632264Sjacobs char *uri = name; 2642264Sjacobs char buf[BUFSIZ]; 2652264Sjacobs uri_t *tmp = NULL; 2662264Sjacobs 2672264Sjacobs if (strstr(name, "://") == NULL) { /* not in URI form */ 2682264Sjacobs if (strcmp(name, DEFAULT_DEST) != 0) { 2692264Sjacobs /* not the "default" */ 2702264Sjacobs snprintf(buf, sizeof (buf), "%s/%s", svc->name, name); 2712264Sjacobs uri = buf; 2722264Sjacobs } else 2732264Sjacobs _default_destination(svc, &uri); 2742264Sjacobs } 2752264Sjacobs 2762264Sjacobs papiAttributeListAddString(op, PAPI_ATTR_EXCL, "printer-uri", uri); 2772264Sjacobs 2782264Sjacobs /* save the printer-uri's path to be used by http POST request */ 2792264Sjacobs if ((uri_from_string(uri, &tmp) == 0) && (tmp != NULL)) { 2802264Sjacobs if (svc->post != NULL) 2812264Sjacobs free(svc->post); 2822264Sjacobs svc->post = strdup(tmp->path); 2832264Sjacobs uri_free(tmp); 2842264Sjacobs } 2852264Sjacobs } 2862264Sjacobs 2872264Sjacobs 2882264Sjacobs /* 2892264Sjacobs * don't actually write anything, just add to the total size and return the 2902264Sjacobs * size of what would be written, so we can figure out how big the request 2912264Sjacobs * is going to be. 2922264Sjacobs */ 2932264Sjacobs static ssize_t 2942264Sjacobs size_calculate(void *fd, void *buffer, size_t length) 2952264Sjacobs { 2962264Sjacobs ssize_t *size = (ssize_t *)fd; 2972264Sjacobs 2982264Sjacobs *size += length; 2992264Sjacobs return (length); 3002264Sjacobs } 3012264Sjacobs 3022264Sjacobs 3032264Sjacobs static ssize_t 3042264Sjacobs build_chunk(void *fd, void *buffer, size_t length) 3052264Sjacobs { 3062264Sjacobs char **s1 = fd; 3072264Sjacobs 3082264Sjacobs memcpy(*s1, buffer, length); 3092264Sjacobs *s1 = *s1 + length; 3102264Sjacobs 3112264Sjacobs return (length); 3122264Sjacobs } 3132264Sjacobs 3142264Sjacobs ssize_t 3152264Sjacobs ipp_request_write(void *fd, void *buffer, size_t length) 3162264Sjacobs { 3172264Sjacobs service_t *svc = (service_t *)fd; 3182264Sjacobs 3192264Sjacobs #ifdef DEBUG 3202264Sjacobs printf("ipp_request_write(0x%8.8x, 0x%8.8x, %d)\n", fd, buffer, length); 3212264Sjacobs httpDumpData(stdout, "ipp_request_write:", buffer, length); 3222264Sjacobs #endif 3232264Sjacobs return (httpWrite(svc->connection, buffer, length)); 3242264Sjacobs } 3252264Sjacobs 3262264Sjacobs ssize_t 3272264Sjacobs ipp_request_read(void *fd, void *buffer, size_t length) 3282264Sjacobs { 3292264Sjacobs service_t *svc = (service_t *)fd; 3302264Sjacobs ssize_t rc, i = length; 3312264Sjacobs char *p = buffer; 3322264Sjacobs 3332264Sjacobs while ((rc = httpRead(svc->connection, p, i)) != i) { 3342264Sjacobs if (rc == 0) 3352264Sjacobs return (rc); 3362264Sjacobs if (rc < 0) 3372264Sjacobs return (rc); 3382264Sjacobs i -= rc; 3392264Sjacobs p += rc; 3402264Sjacobs } 3412264Sjacobs #ifdef DEBUG 3422264Sjacobs printf("ipp_request_read(0x%8.8x, 0x%8.8x, %d) = %d\n", 343*8569SJonathan.Ca@Sun.COM fd, buffer, length, rc); 3442264Sjacobs httpDumpData(stdout, "ipp_request_read:", buffer, length); 3452264Sjacobs #endif 3462264Sjacobs 3472264Sjacobs return (length); 3482264Sjacobs } 3492264Sjacobs 3502264Sjacobs papi_status_t 3512264Sjacobs ipp_send_initial_request_block(service_t *svc, papi_attribute_t **request, 3522264Sjacobs ssize_t file_size) 3532264Sjacobs { 3542264Sjacobs papi_status_t result = PAPI_OK; 3552264Sjacobs ssize_t chunk_size = 0; 3562264Sjacobs char length[32]; 3572264Sjacobs void *chunk, *ptr; 3582264Sjacobs http_status_t status; 3592264Sjacobs 3602264Sjacobs /* calculate the request size */ 3612264Sjacobs (void) ipp_write_message(&size_calculate, &chunk_size, request); 3622264Sjacobs 3632264Sjacobs /* Fill in the HTTP Header information */ 3642264Sjacobs httpClearFields(svc->connection); 3652264Sjacobs if (svc->transfer_encoding == TRANSFER_ENCODING_CHUNKED) 3662264Sjacobs httpSetField(svc->connection, HTTP_FIELD_TRANSFER_ENCODING, 367*8569SJonathan.Ca@Sun.COM "chunked"); 3682264Sjacobs else { 3692264Sjacobs sprintf(length, "%lu", (unsigned long)(file_size + chunk_size)); 3702264Sjacobs httpSetField(svc->connection, HTTP_FIELD_CONTENT_LENGTH, 371*8569SJonathan.Ca@Sun.COM length); 3722264Sjacobs } 3732264Sjacobs httpSetField(svc->connection, HTTP_FIELD_CONTENT_TYPE, 374*8569SJonathan.Ca@Sun.COM "application/ipp"); 3752264Sjacobs httpSetField(svc->connection, HTTP_FIELD_AUTHORIZATION, 376*8569SJonathan.Ca@Sun.COM svc->connection->authstring); 3772264Sjacobs 3782264Sjacobs /* flush any state information about this connection */ 3792264Sjacobs httpFlush(svc->connection); 3802264Sjacobs 3812264Sjacobs /* if we have don't have a POST path, use the service uri path */ 3822264Sjacobs if (svc->post == NULL) 3832264Sjacobs svc->post = strdup(svc->uri->path); 3842264Sjacobs /* send the HTTP POST message for the IPP request */ 3852264Sjacobs /* if the POST fails, return the error */ 3862264Sjacobs status = httpPost(svc->connection, svc->post); 3872264Sjacobs if (status != 0) 3882264Sjacobs return (http_to_papi_status(status)); 3892264Sjacobs 3902264Sjacobs if (httpCheck(svc->connection) != 0) { 3912264Sjacobs status = httpUpdate(svc->connection); 3922264Sjacobs if (status != HTTP_OK) 3932264Sjacobs return (http_to_papi_status(status)); 3942264Sjacobs } 3952264Sjacobs 3962264Sjacobs /* build the request chunk */ 3972264Sjacobs chunk = ptr = calloc(1, chunk_size); 3982264Sjacobs result = ipp_write_message(&build_chunk, &ptr, request); 3992264Sjacobs #ifdef DEBUG 4002264Sjacobs printf("request: %d (0x%x) bytes\n", chunk_size, chunk_size); 4012264Sjacobs httpDumpData(stdout, "request:", chunk, chunk_size); 4022264Sjacobs #endif 4032264Sjacobs 4042264Sjacobs /* send the actual IPP request */ 4052264Sjacobs if (ipp_request_write(svc, chunk, chunk_size) != chunk_size) 4062264Sjacobs result = PAPI_TEMPORARY_ERROR; 4072264Sjacobs free(chunk); 4082264Sjacobs 4092264Sjacobs if (httpCheck(svc->connection) != 0) { 4102264Sjacobs status = httpUpdate(svc->connection); 4112264Sjacobs if (status != HTTP_OK) 4122264Sjacobs return (http_to_papi_status(status)); 4132264Sjacobs } 4142264Sjacobs 4152264Sjacobs return (result); 4162264Sjacobs } 4172264Sjacobs 4182264Sjacobs static int 4192264Sjacobs setAuthString(service_t *svc) 4202264Sjacobs { 4212264Sjacobs http_t *http; 4222264Sjacobs char *user, *passphrase; 4232264Sjacobs char encoded[BUFSIZ]; 4242264Sjacobs 4252264Sjacobs if ((svc == NULL) || (svc->connection == NULL) || (svc->name == NULL)) 4262264Sjacobs return (-1); 4272264Sjacobs 4282264Sjacobs http = svc->connection; 4292264Sjacobs 4302264Sjacobs if (svc->user == NULL) { 4312264Sjacobs struct passwd *p; 4322264Sjacobs 4332264Sjacobs if ((p = getpwuid(getuid())) != NULL) { 4342264Sjacobs user = p->pw_name; 4352264Sjacobs } else if ((user = getenv("LOGNAME")) == NULL) 4362264Sjacobs user = getenv("USER"); 4372264Sjacobs if (user == NULL) 4382264Sjacobs user = "nobody"; 4392264Sjacobs } else 4402264Sjacobs user = svc->user; 4412264Sjacobs 4422264Sjacobs /* if the passphrase is not set, use the Authentication Callback */ 4432264Sjacobs if (((svc->password == NULL) || (svc->password[0] == '\0')) && 4442264Sjacobs (svc->authCB != NULL)) 4452264Sjacobs (svc->authCB)(svc, svc->app_data); 4462264Sjacobs passphrase = svc->password; 4472264Sjacobs 4482264Sjacobs /* if there is still no passphrase, we have to fail */ 4492264Sjacobs if ((passphrase == NULL) || (passphrase[0] == '\0')) 4502264Sjacobs return (-1); 4512264Sjacobs 4522264Sjacobs if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], 453*8569SJonathan.Ca@Sun.COM "Basic", 5) == 0) { 4542264Sjacobs char plain[BUFSIZ]; 4552264Sjacobs 4562264Sjacobs snprintf(plain, sizeof (plain), "%s:%s", user, passphrase); 4572264Sjacobs httpEncode64(encoded, plain); 4582264Sjacobs snprintf(http->authstring, sizeof (http->authstring), 459*8569SJonathan.Ca@Sun.COM "Basic %s", encoded); 4602264Sjacobs } else if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], 461*8569SJonathan.Ca@Sun.COM "Digest", 6) == 0) { 4622264Sjacobs char realm[HTTP_MAX_VALUE]; 4632264Sjacobs char nonce[HTTP_MAX_VALUE]; 4642264Sjacobs char line [BUFSIZ]; 4652264Sjacobs char urp[128]; 4662264Sjacobs char mr[128]; 4672264Sjacobs char *uri = svc->post; 4682264Sjacobs 4692264Sjacobs httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, 470*8569SJonathan.Ca@Sun.COM "realm", realm); 4712264Sjacobs httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, 472*8569SJonathan.Ca@Sun.COM "nonce", nonce); 4732264Sjacobs 4742264Sjacobs snprintf(line, sizeof (line), "%s:%s:%s", user, realm, 475*8569SJonathan.Ca@Sun.COM passphrase); 4762264Sjacobs md5_calc(urp, line, strlen(line)); 4772264Sjacobs 4782264Sjacobs snprintf(line, sizeof (line), "POST:%s", uri); 4792264Sjacobs md5_calc(mr, line, strlen(line)); 4802264Sjacobs 4812264Sjacobs snprintf(line, sizeof (line), "%s:%s:%s", urp, mr, nonce); 4822264Sjacobs md5_calc(encoded, line, strlen(line)); 4832264Sjacobs 4842264Sjacobs snprintf(http->authstring, sizeof (http->authstring), 485*8569SJonathan.Ca@Sun.COM "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", " 486*8569SJonathan.Ca@Sun.COM "uri=\"%s\", response=\"%s\"", user, realm, nonce, uri, 487*8569SJonathan.Ca@Sun.COM encoded); 4882264Sjacobs } 4892264Sjacobs 4902264Sjacobs return (0); 4912264Sjacobs } 4922264Sjacobs 4932264Sjacobs papi_status_t 4942264Sjacobs ipp_status_info(service_t *svc, papi_attribute_t **response) 4952264Sjacobs { 4962264Sjacobs papi_attribute_t **operational = NULL; 4972264Sjacobs int32_t status = 0; 4982264Sjacobs 4992264Sjacobs papiAttributeListGetCollection(response, NULL, 500*8569SJonathan.Ca@Sun.COM "operational-attributes-group", &operational); 5012264Sjacobs if (operational != NULL) { 5022264Sjacobs char *message = NULL; 5032264Sjacobs 5042264Sjacobs papiAttributeListGetString(response, NULL, 505*8569SJonathan.Ca@Sun.COM "status-message", &message); 5062264Sjacobs papiAttributeListAddString(&svc->attributes, PAPI_ATTR_REPLACE, 507*8569SJonathan.Ca@Sun.COM "detailed-status-message", message); 5082264Sjacobs } 5092264Sjacobs papiAttributeListGetInteger(response, NULL, "status-code", &status); 5102264Sjacobs 5112264Sjacobs return (ipp_to_papi_status(status)); 5122264Sjacobs } 5132264Sjacobs 5142264Sjacobs papi_status_t 5152264Sjacobs ipp_send_request_with_file(service_t *svc, papi_attribute_t **request, 5162264Sjacobs papi_attribute_t ***response, char *file) 5172264Sjacobs { 5182264Sjacobs papi_status_t result = PAPI_OK; 5192264Sjacobs ssize_t size = 0; 520*8569SJonathan.Ca@Sun.COM struct stat statbuf; 5212264Sjacobs int fd; 5222264Sjacobs 5232264Sjacobs #ifdef DEBUG 5242264Sjacobs fprintf(stderr, "\nIPP-REQUEST: (%s)", (file ? file : "")); 5252264Sjacobs papiAttributeListPrint(stderr, request, " "); 5262264Sjacobs putc('\n', stderr); 5272264Sjacobs fflush(stderr); 5282264Sjacobs #endif 5292264Sjacobs 5302264Sjacobs /* 5312264Sjacobs * if we are sending a file, open it and include it's size in the 5322264Sjacobs * message size. 5332264Sjacobs */ 5342264Sjacobs if (file != NULL) { 5352264Sjacobs if ((fd = open(file, O_RDONLY)) < 0) { 5362264Sjacobs detailed_error(svc, "%s: %s", file, strerror(errno)); 5372264Sjacobs return (PAPI_DOCUMENT_ACCESS_ERROR); 538*8569SJonathan.Ca@Sun.COM } else if (strcmp("standard input", file) != 0) { 539*8569SJonathan.Ca@Sun.COM stat(file, &statbuf); 540*8569SJonathan.Ca@Sun.COM if (statbuf.st_size == 0) { 541*8569SJonathan.Ca@Sun.COM detailed_error(svc, 542*8569SJonathan.Ca@Sun.COM "Zero byte (empty) file: %s", file); 543*8569SJonathan.Ca@Sun.COM return (PAPI_BAD_ARGUMENT); 544*8569SJonathan.Ca@Sun.COM } 5452264Sjacobs } else if (svc->transfer_encoding != 546*8569SJonathan.Ca@Sun.COM TRANSFER_ENCODING_CHUNKED) { 5472264Sjacobs struct stat st; 5482264Sjacobs 5492264Sjacobs if (fstat(fd, &st) >= 0) 5502264Sjacobs size = st.st_size; 5512264Sjacobs } 5522264Sjacobs } 5532264Sjacobs 5542264Sjacobs *response = NULL; 5552264Sjacobs while (*response == NULL) { 5562264Sjacobs http_status_t status = HTTP_CONTINUE; 5572264Sjacobs 5582264Sjacobs result = ipp_send_initial_request_block(svc, request, size); 5592264Sjacobs 5602264Sjacobs if (result == PAPI_OK) { 5612264Sjacobs if (file != NULL) { 5622264Sjacobs /* send the file contents if we have it */ 5632264Sjacobs int rc; 5642264Sjacobs char buf[BUFSIZ]; 5652264Sjacobs 5662264Sjacobs lseek(fd, 0L, SEEK_SET); 5672264Sjacobs while ((rc = read(fd, buf, sizeof (buf))) > 0) { 5682264Sjacobs if (ipp_request_write(svc, buf, rc) 569*8569SJonathan.Ca@Sun.COM < rc) { 5702264Sjacobs break; 5712264Sjacobs } 5722264Sjacobs } 5732264Sjacobs } 5742264Sjacobs 5752264Sjacobs (void) ipp_request_write(svc, "", 0); 5762264Sjacobs } 5772264Sjacobs 5782264Sjacobs /* update our connection info */ 5792264Sjacobs while (status == HTTP_CONTINUE) 5802264Sjacobs status = httpUpdate(svc->connection); 5812264Sjacobs 5822264Sjacobs if (status == HTTP_UNAUTHORIZED) { 5832264Sjacobs httpFlush(svc->connection); 5842264Sjacobs if ((svc->connection->authstring[0] == '\0') && 5852264Sjacobs (setAuthString(svc) == 0)) { 5862264Sjacobs httpReconnect(svc->connection); 5872264Sjacobs continue; 5882264Sjacobs } 5892264Sjacobs } else if (status == HTTP_UPGRADE_REQUIRED) { 5902264Sjacobs /* 5912264Sjacobs * If the transport was built with TLS support, we can 5922264Sjacobs * try to use it. 5932264Sjacobs */ 5942264Sjacobs httpFlush(svc->connection); 5952264Sjacobs httpReconnect(svc->connection); 5962264Sjacobs httpEncryption(svc->connection, HTTP_ENCRYPT_REQUIRED); 5972264Sjacobs continue; 5982264Sjacobs } 5992264Sjacobs 6002264Sjacobs if (status != HTTP_OK) 6012264Sjacobs return (http_to_papi_status(status)); 6022264Sjacobs 6032264Sjacobs /* read the IPP response */ 6042264Sjacobs result = ipp_read_message(&ipp_request_read, svc, response, 605*8569SJonathan.Ca@Sun.COM IPP_TYPE_RESPONSE); 6062264Sjacobs 6072264Sjacobs if (result == PAPI_OK) 6082264Sjacobs result = ipp_status_info(svc, *response); 6092264Sjacobs #ifdef DEBUG 6102264Sjacobs fprintf(stderr, "\nIPP-RESPONSE: (%s) (%s)", (file ? file : ""), 611*8569SJonathan.Ca@Sun.COM papiStatusString(result)); 6122264Sjacobs papiAttributeListPrint(stderr, *response, " "); 6132264Sjacobs putc('\n', stderr); 6142264Sjacobs fflush(stderr); 6152264Sjacobs #endif 6162264Sjacobs } 6172264Sjacobs 6182264Sjacobs return (result); 6192264Sjacobs } 6202264Sjacobs 6212264Sjacobs papi_status_t 6222264Sjacobs ipp_send_request(service_t *svc, papi_attribute_t **request, 6232264Sjacobs papi_attribute_t ***response) 6242264Sjacobs { 6252264Sjacobs return (ipp_send_request_with_file(svc, request, response, NULL)); 6262264Sjacobs } 627