1*b3700b07SGordon Ross /* 2*b3700b07SGordon Ross * This file and its contents are supplied under the terms of the 3*b3700b07SGordon Ross * Common Development and Distribution License ("CDDL"), version 1.0. 4*b3700b07SGordon Ross * You may only use this file in accordance with the terms of version 5*b3700b07SGordon Ross * 1.0 of the CDDL. 6*b3700b07SGordon Ross * 7*b3700b07SGordon Ross * A full copy of the text of the CDDL should have accompanied this 8*b3700b07SGordon Ross * source. A copy of the CDDL is also available via the Internet at 9*b3700b07SGordon Ross * http://www.illumos.org/license/CDDL. 10*b3700b07SGordon Ross */ 11*b3700b07SGordon Ross 12*b3700b07SGordon Ross /* 13*b3700b07SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 14*b3700b07SGordon Ross */ 15*b3700b07SGordon Ross 16*b3700b07SGordon Ross #include <stdio.h> 17*b3700b07SGordon Ross #include <stdlib.h> 18*b3700b07SGordon Ross #include <stdarg.h> 19*b3700b07SGordon Ross #include <string.h> 20*b3700b07SGordon Ross #include <syslog.h> 21*b3700b07SGordon Ross 22*b3700b07SGordon Ross #include <sys/types.h> 23*b3700b07SGordon Ross #include <sys/errno.h> 24*b3700b07SGordon Ross #include <sys/socket.h> 25*b3700b07SGordon Ross #include <netinet/in.h> 26*b3700b07SGordon Ross #include <sys/note.h> 27*b3700b07SGordon Ross #include <synch.h> 28*b3700b07SGordon Ross #include <thread.h> 29*b3700b07SGordon Ross 30*b3700b07SGordon Ross #include "idmapd.h" 31*b3700b07SGordon Ross #include "libadutils.h" 32*b3700b07SGordon Ross #include "locate_plugin.h" 33*b3700b07SGordon Ross 34*b3700b07SGordon Ross /* osconf.h - sigh */ 35*b3700b07SGordon Ross #define KRB5_DEFAULT_PORT 88 36*b3700b07SGordon Ross #define DEFAULT_KADM5_PORT 749 37*b3700b07SGordon Ross #define DEFAULT_KPASSWD_PORT 464 38*b3700b07SGordon Ross 39*b3700b07SGordon Ross /* 40*b3700b07SGordon Ross * This is an "override plugin" used by libkrb5. See: 41*b3700b07SGordon Ross * lib/gss_mechs/mech_krb5/krb5/os/locate_kdc.c 42*b3700b07SGordon Ross * 43*b3700b07SGordon Ross * The interface is based on: 44*b3700b07SGordon Ross * http://web.mit.edu/~kerberos/krb5-1.12/doc/plugindev/locate.html 45*b3700b07SGordon Ross */ 46*b3700b07SGordon Ross 47*b3700b07SGordon Ross /* 48*b3700b07SGordon Ross * Called by krb5int_locate_server / override_locate_server 49*b3700b07SGordon Ross */ 50*b3700b07SGordon Ross 51*b3700b07SGordon Ross krb5_error_code 52*b3700b07SGordon Ross _krb5_override_service_locator( 53*b3700b07SGordon Ross void *arg0, 54*b3700b07SGordon Ross enum locate_service_type svc, 55*b3700b07SGordon Ross const char *realm, 56*b3700b07SGordon Ross int socktype, 57*b3700b07SGordon Ross int family, 58*b3700b07SGordon Ross int (*cbfunc)(void *, int, struct sockaddr *), 59*b3700b07SGordon Ross void *cbdata) 60*b3700b07SGordon Ross { 61*b3700b07SGordon Ross _NOTE(ARGUNUSED(arg0)) 62*b3700b07SGordon Ross idmap_pg_config_t *pgcfg; 63*b3700b07SGordon Ross ad_disc_ds_t *ds; 64*b3700b07SGordon Ross int rc = KRB5_PLUGIN_NO_HANDLE; 65*b3700b07SGordon Ross short port; 66*b3700b07SGordon Ross 67*b3700b07SGordon Ross /* 68*b3700b07SGordon Ross * Is this a service we want to override? 69*b3700b07SGordon Ross */ 70*b3700b07SGordon Ross switch (svc) { 71*b3700b07SGordon Ross case locate_service_kdc: 72*b3700b07SGordon Ross case locate_service_master_kdc: 73*b3700b07SGordon Ross port = htons(KRB5_DEFAULT_PORT); 74*b3700b07SGordon Ross break; 75*b3700b07SGordon Ross case locate_service_kadmin: 76*b3700b07SGordon Ross port = htons(DEFAULT_KADM5_PORT); 77*b3700b07SGordon Ross break; 78*b3700b07SGordon Ross case locate_service_kpasswd: 79*b3700b07SGordon Ross port = htons(DEFAULT_KPASSWD_PORT); 80*b3700b07SGordon Ross break; 81*b3700b07SGordon Ross case locate_service_krb524: 82*b3700b07SGordon Ross default: 83*b3700b07SGordon Ross return (rc); 84*b3700b07SGordon Ross } 85*b3700b07SGordon Ross 86*b3700b07SGordon Ross RDLOCK_CONFIG(); 87*b3700b07SGordon Ross pgcfg = &_idmapdstate.cfg->pgcfg; 88*b3700b07SGordon Ross 89*b3700b07SGordon Ross /* 90*b3700b07SGordon Ross * Is this a realm we want to override? 91*b3700b07SGordon Ross */ 92*b3700b07SGordon Ross if (pgcfg->domain_name == NULL) 93*b3700b07SGordon Ross goto out; 94*b3700b07SGordon Ross if (0 != strcasecmp(realm, pgcfg->domain_name)) 95*b3700b07SGordon Ross goto out; 96*b3700b07SGordon Ross 97*b3700b07SGordon Ross /* 98*b3700b07SGordon Ross * Yes, this is our domain. Have a DC? 99*b3700b07SGordon Ross */ 100*b3700b07SGordon Ross if ((ds = pgcfg->domain_controller) == NULL) { 101*b3700b07SGordon Ross rc = KRB5_REALM_CANT_RESOLVE; 102*b3700b07SGordon Ross goto out; 103*b3700b07SGordon Ross } 104*b3700b07SGordon Ross 105*b3700b07SGordon Ross switch (family) { 106*b3700b07SGordon Ross case AF_UNSPEC: 107*b3700b07SGordon Ross break; /* OK */ 108*b3700b07SGordon Ross case AF_INET: 109*b3700b07SGordon Ross case AF_INET6: 110*b3700b07SGordon Ross if (family == ds->addr.ss_family) 111*b3700b07SGordon Ross break; /* OK */ 112*b3700b07SGordon Ross /* else fallthrough */ 113*b3700b07SGordon Ross default: 114*b3700b07SGordon Ross rc = KRB5_ERR_NO_SERVICE; 115*b3700b07SGordon Ross goto out; 116*b3700b07SGordon Ross } 117*b3700b07SGordon Ross 118*b3700b07SGordon Ross /* 119*b3700b07SGordon Ross * Provide the service address we have. 120*b3700b07SGordon Ross */ 121*b3700b07SGordon Ross switch (ds->addr.ss_family) { 122*b3700b07SGordon Ross case AF_INET: { 123*b3700b07SGordon Ross struct sockaddr_in sin; 124*b3700b07SGordon Ross struct sockaddr_in *dsa = (void *)&ds->addr; 125*b3700b07SGordon Ross (void) memset(&sin, 0, sizeof (sin)); 126*b3700b07SGordon Ross sin.sin_family = AF_INET; 127*b3700b07SGordon Ross sin.sin_port = port; 128*b3700b07SGordon Ross (void) memcpy(&sin.sin_addr, &dsa->sin_addr, 129*b3700b07SGordon Ross sizeof (sin.sin_addr)); 130*b3700b07SGordon Ross rc = cbfunc(cbdata, socktype, (struct sockaddr *)&sin); 131*b3700b07SGordon Ross break; 132*b3700b07SGordon Ross } 133*b3700b07SGordon Ross case AF_INET6: { 134*b3700b07SGordon Ross struct sockaddr_in6 sin6; 135*b3700b07SGordon Ross struct sockaddr_in6 *dsa6 = (void *)&ds->addr; 136*b3700b07SGordon Ross (void) memset(&sin6, 0, sizeof (sin6)); 137*b3700b07SGordon Ross sin6.sin6_family = AF_INET6; 138*b3700b07SGordon Ross sin6.sin6_port = port; 139*b3700b07SGordon Ross (void) memcpy(&sin6.sin6_addr, &dsa6->sin6_addr, 140*b3700b07SGordon Ross sizeof (sin6.sin6_addr)); 141*b3700b07SGordon Ross rc = cbfunc(cbdata, socktype, (struct sockaddr *)&sin6); 142*b3700b07SGordon Ross break; 143*b3700b07SGordon Ross } 144*b3700b07SGordon Ross default: 145*b3700b07SGordon Ross rc = KRB5_ERR_NO_SERVICE; 146*b3700b07SGordon Ross goto out; 147*b3700b07SGordon Ross } 148*b3700b07SGordon Ross /* rc from cbfunc is special. */ 149*b3700b07SGordon Ross if (rc) 150*b3700b07SGordon Ross rc = ENOMEM; 151*b3700b07SGordon Ross 152*b3700b07SGordon Ross out: 153*b3700b07SGordon Ross UNLOCK_CONFIG(); 154*b3700b07SGordon Ross 155*b3700b07SGordon Ross return (rc); 156*b3700b07SGordon Ross } 157