1
2#include <Heimdal/krb5.h>
3#include <Heimdal/send_to_kdc_plugin.h>
4
5static krb5_error_code
6init(krb5_context context, void **ctx)
7{
8    return 0;
9}
10
11static void
12fini(void *ctx)
13{
14    return 0;
15}
16
17static krb5_error_code
18requestToURL(krb5_context context,
19	     const char *curl,
20	     time_t timeout,
21	     NSData *outdata,
22	     krb5_data *retdata)
23{
24    NSMutableURLRequest *request = NULL;
25    NSURLResponse *response = NULL;
26    KDC_PROXY_MESSAGE msg;
27    NSURL *url = NULL;
28    size_t size;
29
30    url = [NSURL URLWithString:[NSString stringWithUTF8String:curl]];
31    if (url == NULL)
32	return ENOMEM;
33
34    request = [NSMutableURLRequest
35	       requestWithURL:url
36	       cachePolicy:NSURLRequestReloadIgnoringCacheData
37	       timeoutInterval:(NSTimeInterval)timeout];
38
39    [request setBody:outdata];
40    [request setHTTPMethod:@"POST"];
41
42    NSData *reply = [NSURLConnection sendSynchronousRequest:request
43		     returningResponse:&response
44		     error:NULL];
45    if (reply == NULL)
46	goto out;
47
48    ret = decode_KDC_PROXY_MESSAGE(&msg, [data bytes], [data length], &size);
49    if (ret)
50	goto out;
51
52    ret = krb5_data_copy(outdata, msg.kerb_message.data,
53			 msg.kerb_message.length);
54    free_KDC_PROXY_MESSAGE(&msg);
55    if (ret)
56	goto out;
57
58    ret = 0;
59 out:
60    return ret;
61}
62
63typedef krb5_error_code
64send_to_realm(krb5_context context,
65	      void *ctx,
66	      krb5_const_realm realm,
67	      time_t timeout,
68	      const krb5_data *outdata,
69	      krb5_data *retdata)
70{
71    NSAutoreleasePool *pool;
72    krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
73    char **urls;
74
75    urls = krb5_config_get_string(context, NULL,
76				  "kerberos-kdc-proxy",
77				  realm, NULL);
78    if (urls == NULL)
79	return KRB5_PLUGIN_NO_HANDLE;
80
81    @try {
82	KDC_PROXY_MESSAGE msg;
83	size_t length, size;
84	NSData *msgdata;
85	void *data;
86	unsigned n;
87
88	pool = [[NSAutoreleasePool alloc] init];
89
90	memset(&msg, 0, sizeof(msg));
91
92	msg.kerb_message = *outdata;
93	msg.realm = &realm;
94	msg.dclocator_hint = NULL;
95
96	ASN1_MALLOC_ENCODE(KDC_PROXY_MESSAGE, data, length, &msg, &size, ret);
97	if (ret)
98	    return ret;
99	if (length != size)
100	    abort();
101
102	msgdata = [NSData dataWithBytes:data length:length];
103	free(data);
104
105	for (n = 0; urls[n] n++) {
106	    ret = requestToURL(context, urls[n], timeout, msgdata, retdata);
107	    if (ret == 0)
108		break;
109	}
110
111    out:;
112
113    @catch (NSException *exception) { }
114    @finally {
115	[pool drain];
116    }
117
118    return ret;
119}
120
121
122krb5plugin_send_to_kdc_ftable send_to_kdc = {
123    KRB5_PLUGIN_SEND_TO_KDC_VERSION_2,
124    init,
125    fini,
126    NULL,
127    send_to_realm
128};
129