1/* 2 * Copyright (c) 2006 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#import <err.h> 37#import <stdio.h> 38#import <arpa/inet.h> 39#import <netdb.h> 40#import <sys/param.h> 41#import <sys/socket.h> 42#import <syslog.h> 43 44#import <Heimdal/HeimdalSystemConfiguration.h> 45 46#import <Foundation/Foundation.h> 47#import <SystemConfiguration/SystemConfiguration.h> 48#import <krb5.h> 49#import <locate_plugin.h> 50 51/** 52 * Reachablity plugin reads System Configuration to pick up the realm 53 * configuration from OpenDirectory plugins, both OD and AD. 54 * 55 * The keys published is: 56 * 57 * Kerberos:REALM = { 58 * kadmin = [ { host = "hostname", port = "port-number" } ] 59 * kdc = [ .. ] 60 * kpasswd = [ ] 61 * } 62 * 63 * port is optional 64 * 65 * The following behaivor is expected: 66 * 67 * 1. Not joined to a domain 68 * no entry published 69 * 2. Joined to a domain and replica AVAILABLE: 70 * entry pushlished with content 71 * 3. Joined to a domain and replica UNAVAILABLE 72 * entry pushlished, but no content 73 * 74 */ 75 76static krb5_error_code 77reachability_init(krb5_context context, void **ctx) 78{ 79 *ctx = NULL; 80 return 0; 81} 82 83static void 84reachability_fini(void *ctx) 85{ 86} 87 88static krb5_error_code 89reachability_lookup(void *ctx, 90 unsigned long flags, 91 enum locate_service_type service, 92 const char *realm, 93 int domain, 94 int type, 95 int (*addfunc)(void *,int,struct sockaddr *), 96 void *addctx) 97{ 98 krb5_error_code ret; 99 NSAutoreleasePool *pool; 100 NSString *svc, *sckey, *host, *port; 101 struct addrinfo hints, *ai0, *ai; 102 SCDynamicStoreRef store = NULL; 103 NSDictionary *top = NULL; 104 NSArray *vals; 105 NSString *defport; 106 int found_entry = 0; 107 id rp; 108 109 @try { 110 pool = [[NSAutoreleasePool alloc] init]; 111 112 switch(service) { 113 case locate_service_kdc: 114 case locate_service_master_kdc: 115 case locate_service_krb524: 116 svc = (NSString *)HEIMDAL_SC_LOCATE_TYPE_KDC; 117 defport = @"88"; 118 break; 119 case locate_service_kpasswd: 120 svc = (NSString *)HEIMDAL_SC_LOCATE_TYPE_KPASSWD; 121 defport = @"464"; 122 break; 123 case locate_service_kadmin: 124 svc = (NSString *)HEIMDAL_SC_LOCATE_TYPE_ADMIN; 125 defport = @"749"; 126 break; 127 default: 128 ret = KRB5_PLUGIN_NO_HANDLE; 129 goto out; 130 } 131 132 store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("Kerberos"), NULL, NULL); 133 sckey = [NSString stringWithFormat:@"%@%s", 134 (NSString *)HEIMDAL_SC_LOCATE_REALM_PREFIX, realm]; 135 top = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)sckey); 136 if (top == NULL) { 137 ret = KRB5_PLUGIN_NO_HANDLE; 138 goto out; 139 } 140 141 vals = [top valueForKey:svc]; 142 if (vals == NULL) { 143 ret = KRB5_PLUGIN_NO_HANDLE; 144 goto out; 145 } 146 147 if ([vals count] == 0) 148 syslog(LOG_WARNING, 149 "Kerberos-Reachability SystemConfiguration returned 0 entries for %s", 150 realm); 151 152 for (NSDictionary *a in vals) { 153 host = [a valueForKey:(NSString *)HEIMDAL_SC_LOCATE_HOST]; 154 155 rp = [a valueForKey:(NSString *)HEIMDAL_SC_LOCATE_PORT]; 156 if ([rp isKindOfClass:[NSString class]]) 157 port = rp; 158 else if ([rp respondsToSelector:@selector(stringValue)]) 159 port = [rp stringValue]; 160 else 161 port = defport; 162 if (port == nil) 163 continue; 164 165 memset(&hints, 0, sizeof(hints)); 166 hints.ai_flags = 0; 167 hints.ai_family = type; 168 hints.ai_socktype = domain; 169 170 if (getaddrinfo([host UTF8String], [port UTF8String], &hints, &ai0) != 0) 171 continue; 172 173 for (ai = ai0; ai != NULL; ai = ai->ai_next) { 174 ret = addfunc(addctx, ai->ai_socktype, ai->ai_addr); 175 if (ret == 0) 176 found_entry = 1; 177 } 178 freeaddrinfo(ai0); 179 } 180 181 if (!found_entry) 182 ret = KRB5_KDC_UNREACH; 183 else 184 ret = 0; 185 out: 186 do {} while(0); 187 } 188 @catch (NSException *exception) { } 189 @finally { 190 191 if (top) 192 CFRelease((CFTypeRef)top); 193 if (store) 194 CFRelease(store); 195 [pool drain]; 196 } 197 198 return ret; 199} 200 201static krb5_error_code 202reachability_lookup_old(void *ctx, 203 enum locate_service_type service, 204 const char *realm, 205 int domain, 206 int type, 207 int (*addfunc)(void *,int,struct sockaddr *), 208 void *addctx) 209{ 210 return reachability_lookup(ctx, KRB5_PLF_ALLOW_HOMEDIR, service, 211 realm, domain, type, addfunc, addctx); 212} 213 214krb5plugin_service_locate_ftable service_locator = { 215 KRB5_PLUGIN_LOCATE_VERSION_2, 216 reachability_init, 217 reachability_fini, 218 reachability_lookup_old, 219 reachability_lookup 220}; 221