/ plugins / SCKerberosConfig / SCKerberosConfig.m
SCKerberosConfig.m
  1  /*
  2   * Copyright (c) 2006, 2010 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  
 43  #import <Foundation/Foundation.h>
 44  #import <SystemConfiguration/SystemConfiguration.h>
 45  #import <Heimdal/HeimdalSystemConfiguration.h>
 46  #import <Heimdal/krb5.h>
 47  #import <Heimdal/config_plugin.h>
 48  
 49  /**
 50   * Configuration plugin uses configuration in SC for Kerberos
 51   */
 52  
 53  struct config_ctx {
 54      SCDynamicStoreRef store;
 55  };
 56  
 57  
 58  static krb5_error_code
 59  get_default_realm(krb5_context context, void *ptr, void *userctx,
 60  		  void (*add_realms)(krb5_context, void *, krb5_const_realm))
 61  {
 62      krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
 63      struct config_ctx *ctx = ptr;
 64      NSAutoreleasePool *pool;
 65      NSArray *vals = NULL;
 66      
 67      @try {
 68  	pool = [[NSAutoreleasePool alloc] init];
 69  
 70  	vals = (NSArray *)SCDynamicStoreCopyValue(ctx->store, HEIMDAL_SC_DEFAULT_REALM);
 71  	if (vals == NULL)
 72  	    goto out;
 73  	
 74  	if ([vals count] == 0)
 75  	    goto out;
 76  	
 77  	for (NSString *a in vals)
 78  	    add_realms(context, userctx, [a UTF8String]);
 79  
 80  	ret = 0;
 81      out:
 82  	do { } while(0);
 83      }
 84      @catch (NSException * __unused exception) { }
 85      @finally {
 86  
 87  	if (vals)
 88  	    CFRelease((CFTypeRef)vals);
 89  	[pool drain];
 90      }
 91  
 92      return ret;
 93  }
 94  
 95  static krb5_error_code
 96  get_host_domain(krb5_context context, const char *hostname, void *ptr, void *userptr,
 97  		void (*add_realms)(krb5_context, void *, krb5_const_realm))
 98  {
 99      krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
100      struct config_ctx *ctx = ptr;
101      NSAutoreleasePool *pool;
102      NSArray *vals = NULL;
103      
104      @try {
105  	pool = [[NSAutoreleasePool alloc] init];
106  	NSMutableArray *res = [NSMutableArray arrayWithCapacity:0];
107  	NSString *host = [NSString stringWithUTF8String:hostname];
108  	
109  	vals = (NSArray *)SCDynamicStoreCopyValue(ctx->store, HEIMDAL_SC_DOMAIN_REALM_MAPPING);
110  	if (vals == NULL)
111  	    goto out;
112  	
113  	/* search dict for matches, all matches from first domain that matches */
114  	for (NSDictionary *a in vals) {
115  	    for (NSString *domain in a)
116  		if ([host hasSuffix:domain])
117  		    [res addObject:[a valueForKey:domain]];
118  	    
119  	    if ([res count])
120  		break;
121  	}
122  	if ([res count] == 0)
123  	    goto out;
124  
125  	for (NSString *realm in res)
126  	    add_realms(context, userptr, [realm UTF8String]);
127  	
128  	ret = 0;
129  	out:
130  	do { } while(0);
131      }
132      @catch (NSException * __unused exception) { }
133      @finally {
134  	
135  	if (vals)
136  	    CFRelease((CFTypeRef)vals);
137  	[pool drain];
138      }
139      
140      return ret;
141  }
142  
143  static krb5_error_code
144  config_init(krb5_context context, void **ptr)
145  {
146      struct config_ctx *ctx = calloc(1, sizeof(*ctx));
147  
148      if (ctx == NULL)
149  	return ENOMEM;
150  
151      ctx->store = SCDynamicStoreCreate(kCFAllocatorDefault, CFSTR("SCKerberosConfig"), NULL, NULL);
152      if (ctx->store == NULL) {
153  	free(ctx);
154  	return ENOMEM;
155      }
156  	
157      *ptr = ctx;
158      return 0;
159  }
160  
161  static void
162  config_fini(void *ptr)
163  {
164      struct config_ctx *ctx = ptr;
165  
166      CFRelease(ctx->store);
167      free(ctx);
168  }
169  
170  
171  krb5plugin_config_ftable krb5_configuration = {
172      KRB5_PLUGIN_CONFIGURATION_VERSION_1,
173      config_init,
174      config_fini,
175      get_default_realm,
176      get_host_domain
177  };