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 /* 232264Sjacobs * Copyright 2006 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 #pragma ident "%Z%%M% %I% %E% SMI" 312264Sjacobs 322264Sjacobs #include <papi_impl.h> 332264Sjacobs #include <stdlib.h> 342264Sjacobs #include <pwd.h> 352264Sjacobs #include <locale.h> 362264Sjacobs #include <errno.h> 372264Sjacobs #include <fcntl.h> 382264Sjacobs #include <sys/stat.h> 392264Sjacobs #include <md5.h> 402264Sjacobs 412264Sjacobs #include <config-site.h> 422264Sjacobs 43*3125Sjacobs #include <ipp.h> 44*3125Sjacobs 452264Sjacobs papi_status_t 462264Sjacobs http_to_papi_status(http_status_t status) 472264Sjacobs { 482264Sjacobs switch (status) { 492264Sjacobs case HTTP_OK: 502264Sjacobs return (PAPI_OK); 512264Sjacobs case HTTP_BAD_REQUEST: 522264Sjacobs return (PAPI_BAD_REQUEST); 532264Sjacobs case HTTP_UNAUTHORIZED: 542264Sjacobs case HTTP_FORBIDDEN: 552264Sjacobs return (PAPI_NOT_AUTHORIZED); 562264Sjacobs case HTTP_NOT_FOUND: 572264Sjacobs return (PAPI_NOT_FOUND); 582264Sjacobs case HTTP_GONE: 592264Sjacobs return (PAPI_GONE); 602264Sjacobs case HTTP_SERVICE_UNAVAILABLE: 612264Sjacobs return (PAPI_SERVICE_UNAVAILABLE); 622264Sjacobs default: 632264Sjacobs return ((papi_status_t)status); 642264Sjacobs } 652264Sjacobs } 662264Sjacobs 672264Sjacobs papi_status_t 682264Sjacobs ipp_to_papi_status(uint16_t status) 692264Sjacobs { 702264Sjacobs switch (status) { 712264Sjacobs case IPP_OK: 722264Sjacobs return (PAPI_OK); 732264Sjacobs case IPP_OK_IGNORED_ATTRIBUTES: 742264Sjacobs return (PAPI_OK); 752264Sjacobs case IPP_OK_CONFLICTING_ATTRIBUTES: 762264Sjacobs return (PAPI_OK); 772264Sjacobs case IPP_OK_IGNORED_SUBSCRIPTIONS: 782264Sjacobs return (PAPI_OK_IGNORED_SUBSCRIPTIONS); 792264Sjacobs case IPP_OK_IGNORED_NOTIFICATIONS: 802264Sjacobs return (PAPI_OK_IGNORED_NOTIFICATIONS); 812264Sjacobs case IPP_CERR_BAD_REQUEST: 822264Sjacobs return (PAPI_BAD_REQUEST); 832264Sjacobs case IPP_CERR_FORBIDDEN: 842264Sjacobs return (PAPI_FORBIDDEN); 852264Sjacobs case IPP_CERR_NOT_AUTHENTICATED: 862264Sjacobs return (PAPI_NOT_AUTHENTICATED); 872264Sjacobs case IPP_CERR_NOT_AUTHORIZED: 882264Sjacobs return (PAPI_NOT_AUTHORIZED); 892264Sjacobs case IPP_CERR_NOT_POSSIBLE: 902264Sjacobs return (PAPI_NOT_POSSIBLE); 912264Sjacobs case IPP_CERR_TIMEOUT: 922264Sjacobs return (PAPI_TIMEOUT); 932264Sjacobs case IPP_CERR_NOT_FOUND: 942264Sjacobs return (PAPI_NOT_FOUND); 952264Sjacobs case IPP_CERR_GONE: 962264Sjacobs return (PAPI_GONE); 972264Sjacobs case IPP_CERR_REQUEST_ENTITY: 982264Sjacobs return (PAPI_REQUEST_ENTITY); 992264Sjacobs case IPP_CERR_REQUEST_VALUE: 1002264Sjacobs return (PAPI_REQUEST_VALUE); 1012264Sjacobs case IPP_CERR_DOCUMENT_FORMAT: 1022264Sjacobs return (PAPI_DOCUMENT_FORMAT); 1032264Sjacobs case IPP_CERR_ATTRIBUTES: 1042264Sjacobs return (PAPI_ATTRIBUTES); 1052264Sjacobs case IPP_CERR_URI_SCHEME: 1062264Sjacobs return (PAPI_URI_SCHEME); 1072264Sjacobs case IPP_CERR_CHARSET: 1082264Sjacobs return (PAPI_CHARSET); 1092264Sjacobs case IPP_CERR_CONFLICT: 1102264Sjacobs return (PAPI_CONFLICT); 1112264Sjacobs case IPP_CERR_COMPRESSION_NOT_SUPPORTED: 1122264Sjacobs return (PAPI_COMPRESSION_NOT_SUPPORTED); 1132264Sjacobs case IPP_CERR_COMPRESSION_ERROR: 1142264Sjacobs return (PAPI_COMPRESSION_ERROR); 1152264Sjacobs case IPP_CERR_DOCUMENT_FORMAT_ERROR: 1162264Sjacobs return (PAPI_DOCUMENT_FORMAT_ERROR); 1172264Sjacobs case IPP_CERR_DOCUMENT_ACCESS_ERROR: 1182264Sjacobs return (PAPI_DOCUMENT_ACCESS_ERROR); 1192264Sjacobs case IPP_CERR_ATTRIBUTES_NOT_SETTABLE: 1202264Sjacobs return (PAPI_ATTRIBUTES_NOT_SETTABLE); 1212264Sjacobs case IPP_CERR_IGNORED_ALL_SUBSCRIPTIONS: 1222264Sjacobs return (PAPI_IGNORED_ALL_SUBSCRIPTIONS); 1232264Sjacobs case IPP_CERR_TOO_MANY_SUBSCRIPTIONS: 1242264Sjacobs return (PAPI_TOO_MANY_SUBSCRIPTIONS); 1252264Sjacobs case IPP_CERR_IGNORED_ALL_NOTIFICATIONS: 1262264Sjacobs return (PAPI_IGNORED_ALL_NOTIFICATIONS); 1272264Sjacobs case IPP_CERR_PRINT_SUPPORT_FILE_NOT_FOUND: 1282264Sjacobs return (PAPI_PRINT_SUPPORT_FILE_NOT_FOUND); 1292264Sjacobs case IPP_SERR_INTERNAL: 1302264Sjacobs return (PAPI_INTERNAL_ERROR); 1312264Sjacobs case IPP_SERR_OPERATION_NOT_SUPPORTED: 1322264Sjacobs return (PAPI_OPERATION_NOT_SUPPORTED); 1332264Sjacobs case IPP_SERR_SERVICE_UNAVAILABLE: 1342264Sjacobs return (PAPI_SERVICE_UNAVAILABLE); 1352264Sjacobs case IPP_SERR_VERSION_NOT_SUPPORTED: 1362264Sjacobs return (PAPI_VERSION_NOT_SUPPORTED); 1372264Sjacobs case IPP_SERR_DEVICE_ERROR: 1382264Sjacobs return (PAPI_DEVICE_ERROR); 1392264Sjacobs case IPP_SERR_TEMPORARY_ERROR: 1402264Sjacobs return (PAPI_TEMPORARY_ERROR); 1412264Sjacobs case IPP_SERR_NOT_ACCEPTING: 1422264Sjacobs return (PAPI_NOT_ACCEPTING); 1432264Sjacobs case IPP_SERR_BUSY: 1442264Sjacobs case IPP_SERR_CANCELLED: 1452264Sjacobs default: 1462264Sjacobs return (PAPI_TEMPORARY_ERROR); 1472264Sjacobs } 1482264Sjacobs } 1492264Sjacobs 1502264Sjacobs void 1512264Sjacobs ipp_initialize_request(service_t *svc, papi_attribute_t ***request, 1522264Sjacobs uint16_t operation) 1532264Sjacobs { 1542264Sjacobs papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, 1552264Sjacobs "version-major", 1); 1562264Sjacobs papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, 1572264Sjacobs "version-minor", 1); 1582264Sjacobs papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, 1592264Sjacobs "request-id", (short)lrand48()); 1602264Sjacobs papiAttributeListAddInteger(request, PAPI_ATTR_EXCL, 1612264Sjacobs "operation-id", operation); 1622264Sjacobs } 1632264Sjacobs 1642264Sjacobs void 1652264Sjacobs ipp_initialize_operational_attributes(service_t *svc, papi_attribute_t ***op, 1662264Sjacobs papi_attribute_t **attributes) 1672264Sjacobs { 1682264Sjacobs char *charset = "utf-8"; /* default to UTF-8 encoding */ 1692264Sjacobs char *language = setlocale(LC_ALL, ""); 1702264Sjacobs char *user = "nobody"; 1712264Sjacobs struct passwd *pw = NULL; 1722264Sjacobs 1732264Sjacobs /* 1742264Sjacobs * All IPP requests must contain the following: 1752264Sjacobs * attributes-charset (UTF-8) 1762264Sjacobs * attributes-natural-language (our current locale) 1772264Sjacobs * requesting-user-name (process user) 1782264Sjacobs */ 1792264Sjacobs papiAttributeListGetString(attributes, NULL, 1802264Sjacobs "attributes-charset", &charset); 1812264Sjacobs papiAttributeListAddString(op, PAPI_ATTR_EXCL, 1822264Sjacobs "attributes-charset", charset); 1832264Sjacobs 1842264Sjacobs papiAttributeListGetString(attributes, NULL, 1852264Sjacobs "attributes-natural-language", &language); 1862264Sjacobs papiAttributeListAddString(op, PAPI_ATTR_EXCL, 1872264Sjacobs "attributes-natural-language", language); 1882264Sjacobs 1892264Sjacobs if ((pw = getpwuid(getuid())) != NULL) 1902264Sjacobs user = pw->pw_name; 1912264Sjacobs /* 1922264Sjacobs * if our euid is 0 "super user", we will allow the system supplied 1932264Sjacobs * user name to be overridden, if the requestor wants to. 1942264Sjacobs */ 1952264Sjacobs if (geteuid() == 0) { 1962264Sjacobs if (svc->user != NULL) 1972264Sjacobs user = svc->user; 1982264Sjacobs papiAttributeListGetString(attributes, NULL, 1992264Sjacobs "requesting-user-name", &user); 2002264Sjacobs } 2012264Sjacobs papiAttributeListAddString(op, PAPI_ATTR_REPLACE, 2022264Sjacobs "requesting-user-name", user); 2032264Sjacobs } 2042264Sjacobs 2052264Sjacobs #ifndef OPID_CUPS_GET_DEFAULT /* for servers that will enumerate */ 2062264Sjacobs #define OPID_CUPS_GET_DEFAULT 0x4001 2072264Sjacobs #endif /* OPID_CUPS_GET_DEFAULT */ 2082264Sjacobs 2092264Sjacobs static papi_status_t 2102264Sjacobs _default_destination(service_t *svc, char **uri) 2112264Sjacobs { 2122264Sjacobs papi_status_t result = PAPI_INTERNAL_ERROR; 2132264Sjacobs printer_t *p = NULL; 2142264Sjacobs papi_attribute_t **request = NULL, **op = NULL, **response = NULL; 2152264Sjacobs char *tmp = NULL; 2162264Sjacobs 2172264Sjacobs if ((svc == NULL) || (uri == NULL)) 2182264Sjacobs return (PAPI_BAD_ARGUMENT); 2192264Sjacobs 2202264Sjacobs /* we must be connected to find the default destination */ 2212264Sjacobs if (svc->connection == NULL) 2222264Sjacobs return (PAPI_NOT_POSSIBLE); 2232264Sjacobs 2242264Sjacobs if ((p = calloc(1, sizeof (*p))) == NULL) 2252264Sjacobs return (PAPI_TEMPORARY_ERROR); 2262264Sjacobs 2272264Sjacobs ipp_initialize_request(svc, &request, OPID_CUPS_GET_DEFAULT); 2282264Sjacobs ipp_initialize_operational_attributes(svc, &op, NULL); 2292264Sjacobs papiAttributeListAddString(&op, PAPI_ATTR_APPEND, 2302264Sjacobs "requested-attributes", "printer-uri-supported"); 2312264Sjacobs papiAttributeListAddCollection(&request, PAPI_ATTR_REPLACE, 2322264Sjacobs "operational-attributes-group", op); 2332264Sjacobs papiAttributeListFree(op); 2342264Sjacobs result = ipp_send_request(svc, request, &response); 2352264Sjacobs papiAttributeListFree(request); 2362264Sjacobs 2372264Sjacobs op = NULL; 2382264Sjacobs papiAttributeListGetCollection(response, NULL, 2392264Sjacobs "printer-attributes-group", &op); 2402264Sjacobs 2412264Sjacobs if (uri != NULL) { 2422264Sjacobs char *tmp = NULL; 2432264Sjacobs 2442264Sjacobs papiAttributeListGetString(op, NULL, "printer-uri", &tmp); 2452264Sjacobs papiAttributeListGetString(op, NULL, 2462264Sjacobs "printer-uri-supported", &tmp); 2472264Sjacobs if (tmp != NULL) 2482264Sjacobs *uri = strdup(tmp); 2492264Sjacobs } 2502264Sjacobs 2512264Sjacobs papiAttributeListFree(response); 2522264Sjacobs 2532264Sjacobs return (result); 2542264Sjacobs } 2552264Sjacobs 2562264Sjacobs void 2572264Sjacobs ipp_add_printer_uri(service_t *svc, char *name, papi_attribute_t ***op) 2582264Sjacobs { 2592264Sjacobs char *uri = name; 2602264Sjacobs char buf[BUFSIZ]; 2612264Sjacobs uri_t *tmp = NULL; 2622264Sjacobs 2632264Sjacobs if (strstr(name, "://") == NULL) { /* not in URI form */ 2642264Sjacobs if (strcmp(name, DEFAULT_DEST) != 0) { 2652264Sjacobs /* not the "default" */ 2662264Sjacobs snprintf(buf, sizeof (buf), "%s/%s", svc->name, name); 2672264Sjacobs uri = buf; 2682264Sjacobs } else 2692264Sjacobs _default_destination(svc, &uri); 2702264Sjacobs } 2712264Sjacobs 2722264Sjacobs papiAttributeListAddString(op, PAPI_ATTR_EXCL, "printer-uri", uri); 2732264Sjacobs 2742264Sjacobs /* save the printer-uri's path to be used by http POST request */ 2752264Sjacobs if ((uri_from_string(uri, &tmp) == 0) && (tmp != NULL)) { 2762264Sjacobs if (svc->post != NULL) 2772264Sjacobs free(svc->post); 2782264Sjacobs svc->post = strdup(tmp->path); 2792264Sjacobs uri_free(tmp); 2802264Sjacobs } 2812264Sjacobs } 2822264Sjacobs 2832264Sjacobs 2842264Sjacobs /* 2852264Sjacobs * don't actually write anything, just add to the total size and return the 2862264Sjacobs * size of what would be written, so we can figure out how big the request 2872264Sjacobs * is going to be. 2882264Sjacobs */ 2892264Sjacobs static ssize_t 2902264Sjacobs size_calculate(void *fd, void *buffer, size_t length) 2912264Sjacobs { 2922264Sjacobs ssize_t *size = (ssize_t *)fd; 2932264Sjacobs 2942264Sjacobs *size += length; 2952264Sjacobs return (length); 2962264Sjacobs } 2972264Sjacobs 2982264Sjacobs 2992264Sjacobs static ssize_t 3002264Sjacobs build_chunk(void *fd, void *buffer, size_t length) 3012264Sjacobs { 3022264Sjacobs char **s1 = fd; 3032264Sjacobs 3042264Sjacobs memcpy(*s1, buffer, length); 3052264Sjacobs *s1 = *s1 + length; 3062264Sjacobs 3072264Sjacobs return (length); 3082264Sjacobs } 3092264Sjacobs 3102264Sjacobs ssize_t 3112264Sjacobs ipp_request_write(void *fd, void *buffer, size_t length) 3122264Sjacobs { 3132264Sjacobs service_t *svc = (service_t *)fd; 3142264Sjacobs 3152264Sjacobs #ifdef DEBUG 3162264Sjacobs printf("ipp_request_write(0x%8.8x, 0x%8.8x, %d)\n", fd, buffer, length); 3172264Sjacobs httpDumpData(stdout, "ipp_request_write:", buffer, length); 3182264Sjacobs #endif 3192264Sjacobs return (httpWrite(svc->connection, buffer, length)); 3202264Sjacobs } 3212264Sjacobs 3222264Sjacobs ssize_t 3232264Sjacobs ipp_request_read(void *fd, void *buffer, size_t length) 3242264Sjacobs { 3252264Sjacobs service_t *svc = (service_t *)fd; 3262264Sjacobs ssize_t rc, i = length; 3272264Sjacobs char *p = buffer; 3282264Sjacobs 3292264Sjacobs while ((rc = httpRead(svc->connection, p, i)) != i) { 3302264Sjacobs if (rc == 0) 3312264Sjacobs return (rc); 3322264Sjacobs if (rc < 0) 3332264Sjacobs return (rc); 3342264Sjacobs i -= rc; 3352264Sjacobs p += rc; 3362264Sjacobs } 3372264Sjacobs #ifdef DEBUG 3382264Sjacobs printf("ipp_request_read(0x%8.8x, 0x%8.8x, %d) = %d\n", 3392264Sjacobs fd, buffer, length, rc); 3402264Sjacobs httpDumpData(stdout, "ipp_request_read:", buffer, length); 3412264Sjacobs #endif 3422264Sjacobs 3432264Sjacobs return (length); 3442264Sjacobs } 3452264Sjacobs 3462264Sjacobs papi_status_t 3472264Sjacobs ipp_send_initial_request_block(service_t *svc, papi_attribute_t **request, 3482264Sjacobs ssize_t file_size) 3492264Sjacobs { 3502264Sjacobs papi_status_t result = PAPI_OK; 3512264Sjacobs ssize_t chunk_size = 0; 3522264Sjacobs char length[32]; 3532264Sjacobs void *chunk, *ptr; 3542264Sjacobs http_status_t status; 3552264Sjacobs 3562264Sjacobs /* calculate the request size */ 3572264Sjacobs (void) ipp_write_message(&size_calculate, &chunk_size, request); 3582264Sjacobs 3592264Sjacobs /* Fill in the HTTP Header information */ 3602264Sjacobs httpClearFields(svc->connection); 3612264Sjacobs if (svc->transfer_encoding == TRANSFER_ENCODING_CHUNKED) 3622264Sjacobs httpSetField(svc->connection, HTTP_FIELD_TRANSFER_ENCODING, 3632264Sjacobs "chunked"); 3642264Sjacobs else { 3652264Sjacobs sprintf(length, "%lu", (unsigned long)(file_size + chunk_size)); 3662264Sjacobs httpSetField(svc->connection, HTTP_FIELD_CONTENT_LENGTH, 3672264Sjacobs length); 3682264Sjacobs } 3692264Sjacobs httpSetField(svc->connection, HTTP_FIELD_CONTENT_TYPE, 3702264Sjacobs "application/ipp"); 3712264Sjacobs httpSetField(svc->connection, HTTP_FIELD_AUTHORIZATION, 3722264Sjacobs svc->connection->authstring); 3732264Sjacobs 3742264Sjacobs /* flush any state information about this connection */ 3752264Sjacobs httpFlush(svc->connection); 3762264Sjacobs 3772264Sjacobs /* if we have don't have a POST path, use the service uri path */ 3782264Sjacobs if (svc->post == NULL) 3792264Sjacobs svc->post = strdup(svc->uri->path); 3802264Sjacobs /* send the HTTP POST message for the IPP request */ 3812264Sjacobs /* if the POST fails, return the error */ 3822264Sjacobs status = httpPost(svc->connection, svc->post); 3832264Sjacobs if (status != 0) 3842264Sjacobs return (http_to_papi_status(status)); 3852264Sjacobs 3862264Sjacobs if (httpCheck(svc->connection) != 0) { 3872264Sjacobs status = httpUpdate(svc->connection); 3882264Sjacobs if (status != HTTP_OK) 3892264Sjacobs return (http_to_papi_status(status)); 3902264Sjacobs } 3912264Sjacobs 3922264Sjacobs /* build the request chunk */ 3932264Sjacobs chunk = ptr = calloc(1, chunk_size); 3942264Sjacobs result = ipp_write_message(&build_chunk, &ptr, request); 3952264Sjacobs #ifdef DEBUG 3962264Sjacobs printf("request: %d (0x%x) bytes\n", chunk_size, chunk_size); 3972264Sjacobs httpDumpData(stdout, "request:", chunk, chunk_size); 3982264Sjacobs #endif 3992264Sjacobs 4002264Sjacobs /* send the actual IPP request */ 4012264Sjacobs if (ipp_request_write(svc, chunk, chunk_size) != chunk_size) 4022264Sjacobs result = PAPI_TEMPORARY_ERROR; 4032264Sjacobs free(chunk); 4042264Sjacobs 4052264Sjacobs if (httpCheck(svc->connection) != 0) { 4062264Sjacobs status = httpUpdate(svc->connection); 4072264Sjacobs if (status != HTTP_OK) 4082264Sjacobs return (http_to_papi_status(status)); 4092264Sjacobs } 4102264Sjacobs 4112264Sjacobs return (result); 4122264Sjacobs } 4132264Sjacobs 4142264Sjacobs static int 4152264Sjacobs setAuthString(service_t *svc) 4162264Sjacobs { 4172264Sjacobs http_t *http; 4182264Sjacobs char *user, *passphrase; 4192264Sjacobs char encoded[BUFSIZ]; 4202264Sjacobs 4212264Sjacobs if ((svc == NULL) || (svc->connection == NULL) || (svc->name == NULL)) 4222264Sjacobs return (-1); 4232264Sjacobs 4242264Sjacobs http = svc->connection; 4252264Sjacobs 4262264Sjacobs if (svc->user == NULL) { 4272264Sjacobs struct passwd *p; 4282264Sjacobs 4292264Sjacobs if ((p = getpwuid(getuid())) != NULL) { 4302264Sjacobs user = p->pw_name; 4312264Sjacobs } else if ((user = getenv("LOGNAME")) == NULL) 4322264Sjacobs user = getenv("USER"); 4332264Sjacobs if (user == NULL) 4342264Sjacobs user = "nobody"; 4352264Sjacobs } else 4362264Sjacobs user = svc->user; 4372264Sjacobs 4382264Sjacobs /* if the passphrase is not set, use the Authentication Callback */ 4392264Sjacobs if (((svc->password == NULL) || (svc->password[0] == '\0')) && 4402264Sjacobs (svc->authCB != NULL)) 4412264Sjacobs (svc->authCB)(svc, svc->app_data); 4422264Sjacobs passphrase = svc->password; 4432264Sjacobs 4442264Sjacobs /* if there is still no passphrase, we have to fail */ 4452264Sjacobs if ((passphrase == NULL) || (passphrase[0] == '\0')) 4462264Sjacobs return (-1); 4472264Sjacobs 4482264Sjacobs if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], 4492264Sjacobs "Basic", 5) == 0) { 4502264Sjacobs char plain[BUFSIZ]; 4512264Sjacobs 4522264Sjacobs snprintf(plain, sizeof (plain), "%s:%s", user, passphrase); 4532264Sjacobs httpEncode64(encoded, plain); 4542264Sjacobs snprintf(http->authstring, sizeof (http->authstring), 4552264Sjacobs "Basic %s", encoded); 4562264Sjacobs } else if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], 4572264Sjacobs "Digest", 6) == 0) { 4582264Sjacobs char realm[HTTP_MAX_VALUE]; 4592264Sjacobs char nonce[HTTP_MAX_VALUE]; 4602264Sjacobs char line [BUFSIZ]; 4612264Sjacobs char urp[128]; 4622264Sjacobs char mr[128]; 4632264Sjacobs char *uri = svc->post; 4642264Sjacobs 4652264Sjacobs httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, 4662264Sjacobs "realm", realm); 4672264Sjacobs httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, 4682264Sjacobs "nonce", nonce); 4692264Sjacobs 4702264Sjacobs snprintf(line, sizeof (line), "%s:%s:%s", user, realm, 4712264Sjacobs passphrase); 4722264Sjacobs md5_calc(urp, line, strlen(line)); 4732264Sjacobs 4742264Sjacobs snprintf(line, sizeof (line), "POST:%s", uri); 4752264Sjacobs md5_calc(mr, line, strlen(line)); 4762264Sjacobs 4772264Sjacobs snprintf(line, sizeof (line), "%s:%s:%s", urp, mr, nonce); 4782264Sjacobs md5_calc(encoded, line, strlen(line)); 4792264Sjacobs 4802264Sjacobs snprintf(http->authstring, sizeof (http->authstring), 4812264Sjacobs "Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", " 4822264Sjacobs "uri=\"%s\", response=\"%s\"", user, realm, nonce, uri, 4832264Sjacobs encoded); 4842264Sjacobs } 4852264Sjacobs 4862264Sjacobs return (0); 4872264Sjacobs } 4882264Sjacobs 4892264Sjacobs papi_status_t 4902264Sjacobs ipp_status_info(service_t *svc, papi_attribute_t **response) 4912264Sjacobs { 4922264Sjacobs papi_attribute_t **operational = NULL; 4932264Sjacobs int32_t status = 0; 4942264Sjacobs 4952264Sjacobs papiAttributeListGetCollection(response, NULL, 4962264Sjacobs "operational-attributes-group", &operational); 4972264Sjacobs if (operational != NULL) { 4982264Sjacobs char *message = NULL; 4992264Sjacobs 5002264Sjacobs papiAttributeListGetString(response, NULL, 5012264Sjacobs "status-message", &message); 5022264Sjacobs papiAttributeListAddString(&svc->attributes, PAPI_ATTR_REPLACE, 5032264Sjacobs "detailed-status-message", message); 5042264Sjacobs } 5052264Sjacobs papiAttributeListGetInteger(response, NULL, "status-code", &status); 5062264Sjacobs 5072264Sjacobs return (ipp_to_papi_status(status)); 5082264Sjacobs } 5092264Sjacobs 5102264Sjacobs papi_status_t 5112264Sjacobs ipp_send_request_with_file(service_t *svc, papi_attribute_t **request, 5122264Sjacobs papi_attribute_t ***response, char *file) 5132264Sjacobs { 5142264Sjacobs papi_status_t result = PAPI_OK; 5152264Sjacobs ssize_t size = 0; 5162264Sjacobs int fd; 5172264Sjacobs 5182264Sjacobs #ifdef DEBUG 5192264Sjacobs fprintf(stderr, "\nIPP-REQUEST: (%s)", (file ? file : "")); 5202264Sjacobs papiAttributeListPrint(stderr, request, " "); 5212264Sjacobs putc('\n', stderr); 5222264Sjacobs fflush(stderr); 5232264Sjacobs #endif 5242264Sjacobs 5252264Sjacobs /* 5262264Sjacobs * if we are sending a file, open it and include it's size in the 5272264Sjacobs * message size. 5282264Sjacobs */ 5292264Sjacobs if (file != NULL) { 5302264Sjacobs if ((fd = open(file, O_RDONLY)) < 0) { 5312264Sjacobs detailed_error(svc, "%s: %s", file, strerror(errno)); 5322264Sjacobs return (PAPI_DOCUMENT_ACCESS_ERROR); 5332264Sjacobs } else if (svc->transfer_encoding != 5342264Sjacobs TRANSFER_ENCODING_CHUNKED) { 5352264Sjacobs struct stat st; 5362264Sjacobs 5372264Sjacobs if (fstat(fd, &st) >= 0) 5382264Sjacobs size = st.st_size; 5392264Sjacobs } 5402264Sjacobs } 5412264Sjacobs 5422264Sjacobs *response = NULL; 5432264Sjacobs while (*response == NULL) { 5442264Sjacobs http_status_t status = HTTP_CONTINUE; 5452264Sjacobs 5462264Sjacobs result = ipp_send_initial_request_block(svc, request, size); 5472264Sjacobs 5482264Sjacobs if (result == PAPI_OK) { 5492264Sjacobs if (file != NULL) { 5502264Sjacobs /* send the file contents if we have it */ 5512264Sjacobs int rc; 5522264Sjacobs char buf[BUFSIZ]; 5532264Sjacobs 5542264Sjacobs lseek(fd, 0L, SEEK_SET); 5552264Sjacobs while ((rc = read(fd, buf, sizeof (buf))) > 0) { 5562264Sjacobs if (ipp_request_write(svc, buf, rc) 5572264Sjacobs < rc) { 5582264Sjacobs break; 5592264Sjacobs } 5602264Sjacobs } 5612264Sjacobs } 5622264Sjacobs 5632264Sjacobs (void) ipp_request_write(svc, "", 0); 5642264Sjacobs } 5652264Sjacobs 5662264Sjacobs /* update our connection info */ 5672264Sjacobs while (status == HTTP_CONTINUE) 5682264Sjacobs status = httpUpdate(svc->connection); 5692264Sjacobs 5702264Sjacobs if (status == HTTP_UNAUTHORIZED) { 5712264Sjacobs httpFlush(svc->connection); 5722264Sjacobs if ((svc->connection->authstring[0] == '\0') && 5732264Sjacobs (setAuthString(svc) == 0)) { 5742264Sjacobs httpReconnect(svc->connection); 5752264Sjacobs continue; 5762264Sjacobs } 5772264Sjacobs } else if (status == HTTP_UPGRADE_REQUIRED) { 5782264Sjacobs /* 5792264Sjacobs * If the transport was built with TLS support, we can 5802264Sjacobs * try to use it. 5812264Sjacobs */ 5822264Sjacobs httpFlush(svc->connection); 5832264Sjacobs httpReconnect(svc->connection); 5842264Sjacobs httpEncryption(svc->connection, HTTP_ENCRYPT_REQUIRED); 5852264Sjacobs continue; 5862264Sjacobs } 5872264Sjacobs 5882264Sjacobs if (status != HTTP_OK) 5892264Sjacobs return (http_to_papi_status(status)); 5902264Sjacobs 5912264Sjacobs /* read the IPP response */ 5922264Sjacobs result = ipp_read_message(&ipp_request_read, svc, response, 5932264Sjacobs IPP_TYPE_RESPONSE); 5942264Sjacobs 5952264Sjacobs if (result == PAPI_OK) 5962264Sjacobs result = ipp_status_info(svc, *response); 5972264Sjacobs #ifdef DEBUG 5982264Sjacobs fprintf(stderr, "\nIPP-RESPONSE: (%s) (%s)", (file ? file : ""), 5992264Sjacobs papiStatusString(result)); 6002264Sjacobs papiAttributeListPrint(stderr, *response, " "); 6012264Sjacobs putc('\n', stderr); 6022264Sjacobs fflush(stderr); 6032264Sjacobs #endif 6042264Sjacobs } 6052264Sjacobs 6062264Sjacobs return (result); 6072264Sjacobs } 6082264Sjacobs 6092264Sjacobs papi_status_t 6102264Sjacobs ipp_send_request(service_t *svc, papi_attribute_t **request, 6112264Sjacobs papi_attribute_t ***response) 6122264Sjacobs { 6132264Sjacobs return (ipp_send_request_with_file(svc, request, response, NULL)); 6142264Sjacobs } 615