/* * Copyright (c) 2013 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2013 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "krb5_locl.h" #include #include static krb5_error_code requestToURL(krb5_context context, const char *stringurl, const krb5_data *outdata, krb5_data *retdata) { CFMutableDataRef responseBytes = NULL; CFReadStreamRef requestStream = NULL; CFHTTPMessageRef message = NULL; CFDataRef bodyData = NULL; KDC_PROXY_MESSAGE msg; CFIndex numBytesRead; krb5_error_code ret; CFURLRef url = NULL; size_t size; bodyData = CFDataCreateWithBytesNoCopy(NULL, outdata->data, outdata->length, kCFAllocatorNull); if (bodyData == NULL) { ret = ENOMEM; goto out; } url = CFURLCreateWithBytes(NULL, (const UInt8 *)stringurl, strlen(stringurl), kCFStringEncodingUTF8, NULL); if (url == NULL) { ret = ENOMEM; goto out; } message = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("POST"), url, kCFHTTPVersion1_1); if (message == NULL) { ret = ENOMEM; goto out; } CFHTTPMessageSetBody(message, bodyData); CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Content-Type"), CFSTR("application/octet-stream")); requestStream = CFReadStreamCreateForHTTPRequest(NULL, message); if (requestStream == NULL) { ret = ENOMEM; goto out; } if (!CFReadStreamOpen(requestStream)) { CFErrorRef error = CFReadStreamCopyError(requestStream); ret = HEIM_ERR_EOF; _krb5_set_cf_error_message(context, ret, error, "Failed to open kkdcp stream"); if (error) CFRelease(error); goto out; } responseBytes = CFDataCreateMutable(NULL, 0); numBytesRead = 0 ; do { UInt8 buf[1024]; numBytesRead = CFReadStreamRead(requestStream, buf, sizeof(buf)); if(numBytesRead > 0) CFDataAppendBytes(responseBytes, buf, numBytesRead); } while(numBytesRead > 0); if (numBytesRead < 0) { CFErrorRef error = CFReadStreamCopyError(requestStream); ret = HEIM_ERR_EOF; _krb5_set_cf_error_message(context, ret, error, "Failed to reading kkdcp stream"); goto out; } CFReadStreamClose(requestStream); ret = decode_KDC_PROXY_MESSAGE(CFDataGetBytePtr(responseBytes), CFDataGetLength(responseBytes), &msg, &size); if (ret) { krb5_set_error_message(context, ret, "failed to decode KDC_PROXY_MESSAGE"); goto out; } ret = krb5_data_copy(retdata, msg.kerb_message.data, msg.kerb_message.length); free_KDC_PROXY_MESSAGE(&msg); if (ret) goto out; ret = 0; out: if (ret) _krb5_debug(context, 10, ret, "kkdcp to url (%s) failed", stringurl); if (bodyData) CFRelease(bodyData); if (url) CFRelease(url); if (message) CFRelease(message); if (requestStream) CFRelease(requestStream); if (responseBytes) CFRelease(responseBytes); return ret; } krb5_error_code _krb5_kkdcp_request(krb5_context context, const char *realm, const char *url, const krb5_data *data, krb5_data *retdata) { KDC_PROXY_MESSAGE msg; krb5_data msgdata; krb5_error_code ret; size_t size; memset(&msg, 0, sizeof(msg)); msg.kerb_message = *data; msg.target_domain = (Realm *)&realm; msg.dclocator_hint = NULL; ASN1_MALLOC_ENCODE(KDC_PROXY_MESSAGE, msgdata.data, msgdata.length, &msg, &size, ret); if (ret) return ret; heim_assert(msgdata.length == size, "internal asn1. encoder error"); ret = requestToURL(context, url, &msgdata, retdata); krb5_data_free(&msgdata); return ret; }