client.c   [plain text]



#include <Heimdal/krb5.h>
#include <Heimdal/send_to_kdc_plugin.h>

static krb5_error_code
init(krb5_context context, void **ctx)
{
    return 0;
}

static void
fini(void *ctx)
{
    return 0;
}

static krb5_error_code
requestToURL(krb5_context context,
	     const char *curl,
	     time_t timeout,
	     NSData *outdata,
	     krb5_data *retdata)
{
    NSMutableURLRequest *request = NULL;
    NSURLResponse *response = NULL;
    KDC_PROXY_MESSAGE msg;
    NSURL *url = NULL;
    size_t size;

    url = [NSURL URLWithString:[NSString stringWithUTF8String:curl]];
    if (url == NULL)
	return ENOMEM;

    request = [NSMutableURLRequest
	       requestWithURL:url 
	       cachePolicy:NSURLRequestReloadIgnoringCacheData
	       timeoutInterval:(NSTimeInterval)timeout];
    
    [request setBody:outdata];
    [request setHTTPMethod:@"POST"];

    NSData *reply = [NSURLConnection sendSynchronousRequest:request
		     returningResponse:&response
		     error:NULL];
    if (reply == NULL)
	goto out;
    
    ret = decode_KDC_PROXY_MESSAGE(&msg, [data bytes], [data length], &size);
    if (ret)
	goto out;
    
    ret = krb5_data_copy(outdata, msg.kerb_message.data,
			 msg.kerb_message.length);
    free_KDC_PROXY_MESSAGE(&msg);
    if (ret)
	goto out;
    
    ret = 0;
 out:
    return ret;
}

typedef krb5_error_code
send_to_realm(krb5_context context,
	      void *ctx,
	      krb5_const_realm realm,
	      time_t timeout,
	      const krb5_data *outdata,
	      krb5_data *retdata)
{
    NSAutoreleasePool *pool;
    krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
    char **urls;

    urls = krb5_config_get_string(context, NULL,
				  "kerberos-kdc-proxy",
				  realm, NULL);
    if (urls == NULL)
	return KRB5_PLUGIN_NO_HANDLE;

    @try {
	KDC_PROXY_MESSAGE msg;
	size_t length, size;
	NSData *msgdata;
	void *data;
	unsigned n;

	pool = [[NSAutoreleasePool alloc] init];

	memset(&msg, 0, sizeof(msg));
    
	msg.kerb_message = *outdata;
	msg.realm = &realm;
	msg.dclocator_hint = NULL;
	
	ASN1_MALLOC_ENCODE(KDC_PROXY_MESSAGE, data, length, &msg, &size, ret);
	if (ret)
	    return ret;
	if (length != size)
	    abort();
	
	msgdata = [NSData dataWithBytes:data length:length];
	free(data);

	for (n = 0; urls[n] n++) {
	    ret = requestToURL(context, urls[n], timeout, msgdata, retdata);
	    if (ret == 0)
		break;
	}
	    
    out:;

    @catch (NSException *exception) { }
    @finally {
	[pool drain];
    }

    return ret;
}


krb5plugin_send_to_kdc_ftable send_to_kdc = {
    KRB5_PLUGIN_SEND_TO_KDC_VERSION_2,
    init,
    fini,
    NULL,
    send_to_realm
};