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 = NULL; 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 } 128 if (defport == NULL) { 129 ret = KRB5_PLUGIN_NO_HANDLE; 130 goto out; 131 } 132 133 store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("Kerberos"), NULL, NULL); 134 sckey = [NSString stringWithFormat:@"%@%s", 135 (NSString *)HEIMDAL_SC_LOCATE_REALM_PREFIX, realm]; 136 top = (NSDictionary *)SCDynamicStoreCopyValue(store, (CFStringRef)sckey); 137 if (top == NULL) { 138 ret = KRB5_PLUGIN_NO_HANDLE; 139 goto out; 140 } 141 142 vals = [top valueForKey:svc]; 143 if (vals == NULL) { 144 ret = KRB5_PLUGIN_NO_HANDLE; 145 goto out; 146 } 147 148 if ([vals count] == 0) 149 syslog(LOG_WARNING, 150 "Kerberos-Reachability SystemConfiguration returned 0 entries for %s", 151 realm); 152 153 for (NSDictionary *a in vals) { 154 host = [a valueForKey:(NSString *)HEIMDAL_SC_LOCATE_HOST]; 155 156 rp = [a valueForKey:(NSString *)HEIMDAL_SC_LOCATE_PORT]; 157 if ([rp isKindOfClass:[NSString class]]) 158 port = rp; 159 else if ([rp respondsToSelector:@selector(stringValue)]) 160 port = [rp stringValue]; 161 else 162 port = defport; 163 if (port == nil) 164 continue; 165 166 memset(&hints, 0, sizeof(hints)); 167 hints.ai_flags = 0; 168 hints.ai_family = type; 169 hints.ai_socktype = domain; 170 171 if (getaddrinfo([host UTF8String], [port UTF8String], &hints, &ai0) != 0) 172 continue; 173 174 for (ai = ai0; ai != NULL; ai = ai->ai_next) { 175 ret = addfunc(addctx, ai->ai_socktype, ai->ai_addr); 176 if (ret == 0) 177 found_entry = 1; 178 } 179 freeaddrinfo(ai0); 180 } 181 182 if (!found_entry) 183 ret = KRB5_KDC_UNREACH; 184 else 185 ret = 0; 186 out: 187 do {} while(0); 188 } 189 @catch (NSException * __unused exception) { } 190 @finally { 191 192 if (top) 193 CFRelease((CFTypeRef)top); 194 if (store) 195 CFRelease(store); 196 [pool drain]; 197 } 198 199 return ret; 200} 201 202static krb5_error_code 203reachability_lookup_old(void *ctx, 204 enum locate_service_type service, 205 const char *realm, 206 int domain, 207 int type, 208 int (*addfunc)(void *,int,struct sockaddr *), 209 void *addctx) 210{ 211 return reachability_lookup(ctx, KRB5_PLF_ALLOW_HOMEDIR, service, 212 realm, domain, type, addfunc, addctx); 213} 214 215krb5plugin_service_locate_ftable service_locator = { 216 KRB5_PLUGIN_LOCATE_VERSION_2, 217 reachability_init, 218 reachability_fini, 219 reachability_lookup_old, 220 reachability_lookup 221}; 222