/ plugins / GSSCredentialSelector / GSSCredentialSelector.m
GSSCredentialSelector.m
  1  /*
  2   * Copyright (c) 2011 Kungliga Tekniska Högskolan
  3   * (Royal Institute of Technology, Stockholm, Sweden).
  4   * All rights reserved.
  5   *
  6   * Portions Copyright (c) 2011 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 <stdio.h>
 37  
 38  #import <Foundation/Foundation.h>
 39  #import <Heimdal/krb5.h>
 40  #import <GSS/gssapi_spi.h>
 41  #import <GSS/gssapi_plugin.h>
 42  
 43  #include <syslog.h>
 44  #include <assert.h>
 45  
 46  /**
 47   * Icky code that prints the target name and replace the cred with another cred that hard coded in the module
 48   */
 49  
 50  #define GSSC_MAGIC 0x47111147
 51  
 52  struct gsssel_ctx {
 53      int magic;
 54  };
 55  
 56  static const char selectuser[] = "lha@KTH.SE";
 57  static const char *replacenames[] = {
 58      "host@svn.h5l.org", 
 59      NULL
 60  };
 61  
 62  static gss_cred_id_t
 63  isc_replace_cred(gss_name_t target, gss_OID mech, gss_cred_id_t original_cred, OM_uint32 flags)
 64  {
 65      OM_uint32 maj_stat, min_stat;
 66      gss_buffer_desc buffer;
 67      gss_name_t name;
 68      gss_cred_id_t newcred;
 69      bool exchange = false;
 70      size_t n;
 71  
 72      /*
 73       * Using gss_display_name() is wrong, however it the best we can
 74       * do right now.
 75       *
 76       * We should use gss_import_name() and then compare the name with
 77       * gss_compare_name(), the only issue with that is that comparing
 78       * names fragile and do not work as expected wrt to case of
 79       * string, and in case or Kerberos, hostbased service gets
 80       * affected by realm.
 81       */
 82      
 83      maj_stat = gss_display_name(&min_stat, target, &buffer, NULL);
 84      if (maj_stat == GSS_S_COMPLETE) {
 85  	syslog(LOG_ERR, "ISC-replace-cred target name: %.*s", (int)buffer.length, (char *)buffer.value);
 86  	for (n = 0; replacenames[n]; n++) {
 87  	    if (memmem(buffer.value, buffer.length, replacenames[n], strlen(replacenames[n])) != NULL)
 88  		exchange = true;
 89  	}
 90  	gss_release_buffer(&min_stat, &buffer);
 91      }
 92      if (!exchange) {
 93  	syslog(LOG_ERR, "ISC-replace-cred not replacing");
 94  	return NULL;
 95      }
 96      
 97      buffer.value = (char *)(uintptr_t)selectuser;
 98      buffer.length = strlen(selectuser);
 99      maj_stat = gss_import_name(&min_stat, &buffer, GSS_C_NT_USER_NAME, &name);
100      if (maj_stat != GSS_S_COMPLETE)
101  	return NULL;
102      
103      maj_stat = gss_acquire_cred(&min_stat, name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, GSS_C_INITIATE, 
104  				&newcred, NULL, NULL);
105      gss_release_name(&min_stat, &name);
106      if (maj_stat != GSS_S_COMPLETE)
107  	return NULL;
108      
109      syslog(LOG_ERR, "ISC-replace-cred replacing cred to: %s", selectuser);
110      
111      return newcred;
112  }
113  
114  static krb5_error_code
115  gsssel_init(krb5_context context, void **ptr)
116  {
117      struct gsssel_ctx *ctx = calloc(1, sizeof(*ctx));
118  
119      if (ctx == NULL)
120  	return ENOMEM;
121      
122      ctx->magic = GSSC_MAGIC;
123  
124      *ptr = ctx;
125      return 0;
126  }
127  
128  static void
129  gsssel_fini(void *ptr)
130  {
131      struct gsssel_ctx *ctx = ptr;
132      
133      assert(ctx->magic == GSSC_MAGIC);
134  
135      free(ctx);
136  }
137  
138  
139  gssapi_plugin_ftable gssapi_plugin = {
140      GSSAPI_PLUGIN_VERSION_1,
141      gsssel_init,
142      gsssel_fini,
143      "gssapi credential selector",
144      0,
145      isc_replace_cred
146  };