1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* 9 * lib/kad5/kadm_host_srv_names.c 10 */ 11 12 #include "admin.h" 13 #include <stdio.h> 14 #include <os-proto.h> 15 16 #define KADM5_MASTER "admin_server" 17 18 /* 19 * Find the admin server for the given realm. If the realm is null or 20 * the empty string, find the admin server for the default realm. 21 * Returns 0 on succsess (KADM5_OK). It is the callers responsibility to 22 * free the storage allocated to the admin server, master. 23 */ 24 kadm5_ret_t 25 kadm5_get_master(krb5_context context, const char *realm, char **master) 26 { 27 char *def_realm; 28 char *delim; 29 #ifdef KRB5_DNS_LOOKUP 30 struct sockaddr *addrs; 31 int naddrs; 32 unsigned short dns_portno; 33 char dns_host[MAX_DNS_NAMELEN]; 34 krb5_data dns_realm; 35 krb5_error_code dns_ret = 1; 36 #endif /* KRB5_DNS_LOOKUP */ 37 38 if (realm == 0 || *realm == '\0') 39 krb5_get_default_realm(context, &def_realm); 40 41 (void) profile_get_string(context->profile, "realms", 42 realm ? realm : def_realm, 43 KADM5_MASTER, 0, master); 44 45 if ((*master != NULL) && ((delim = strchr(*master, ':')) != NULL)) 46 *delim = '\0'; 47 #ifdef KRB5_DNS_LOOKUP 48 if (*master == NULL) { 49 /* 50 * Initialize realm info for (possible) DNS lookups. 51 */ 52 dns_realm.data = strdup(realm ? realm : def_realm); 53 dns_realm.length = strlen(realm ? realm : def_realm); 54 dns_realm.magic = 0; 55 56 dns_ret = krb5_get_servername(context, &dns_realm, 57 "_kerberos-adm", "_udp", 58 dns_host, &dns_portno); 59 if (dns_ret == 0) 60 *master = strdup(dns_host); 61 62 if (dns_realm.data) 63 free(dns_realm.data); 64 } 65 #endif /* KRB5_DNS_LOOKUP */ 66 return (*master ? KADM5_OK : KADM5_NO_SRV); 67 } 68 69 /* 70 * Get the host base service name for the admin principal. Returns 71 * KADM5_OK on success. Caller must free the storage allocated for 72 * host_service_name. 73 */ 74 kadm5_ret_t 75 kadm5_get_adm_host_srv_name(krb5_context context, 76 const char *realm, char **host_service_name) 77 { 78 kadm5_ret_t ret; 79 char *name; 80 char *host; 81 82 83 if (ret = kadm5_get_master(context, realm, &host)) 84 return (ret); 85 86 name = malloc(strlen(KADM5_ADMIN_HOST_SERVICE)+ strlen(host) + 2); 87 if (name == NULL) { 88 free(host); 89 return (ENOMEM); 90 } 91 sprintf(name, "%s@%s", KADM5_ADMIN_HOST_SERVICE, host); 92 free(host); 93 *host_service_name = name; 94 95 return (KADM5_OK); 96 } 97 98 /* 99 * Get the host base service name for the changepw principal. Returns 100 * KADM5_OK on success. Caller must free the storage allocated for 101 * host_service_name. 102 */ 103 kadm5_ret_t 104 kadm5_get_cpw_host_srv_name(krb5_context context, 105 const char *realm, char **host_service_name) 106 { 107 kadm5_ret_t ret; 108 char *name; 109 char *host; 110 111 112 if (ret = kadm5_get_master(context, realm, &host)) 113 return (ret); 114 115 name = malloc(strlen(KADM5_CHANGEPW_HOST_SERVICE) + strlen(host) + 2); 116 if (name == NULL) { 117 free(host); 118 return (ENOMEM); 119 } 120 sprintf(name, "%s@%s", KADM5_CHANGEPW_HOST_SERVICE, host); 121 free(host); 122 *host_service_name = name; 123 124 return (KADM5_OK); 125 } 126 127 /* 128 * Get the host base service name for the kiprop principal. Returns 129 * KADM5_OK on success. Caller must free the storage allocated 130 * for host_service_name. 131 */ 132 kadm5_ret_t kadm5_get_kiprop_host_srv_name(krb5_context context, 133 const char *realm, 134 char **host_service_name) { 135 kadm5_ret_t ret; 136 char *name; 137 char *host; 138 139 140 if (ret = kadm5_get_master(context, realm, &host)) 141 return (ret); 142 143 name = malloc(strlen(KADM5_KIPROP_HOST_SERVICE) + strlen(host) + 2); 144 if (name == NULL) { 145 free(host); 146 return (ENOMEM); 147 } 148 sprintf(name, "%s@%s", KADM5_KIPROP_HOST_SERVICE, host); 149 free(host); 150 *host_service_name = name; 151 152 return (KADM5_OK); 153 } 154 155 /* 156 * Solaris Kerberos: 157 * Try to determine if this is the master KDC for a given realm 158 */ 159 kadm5_ret_t kadm5_is_master(krb5_context context, const char *realm, 160 krb5_boolean *is_master) { 161 162 kadm5_ret_t ret; 163 char *admin_host = NULL; 164 krb5_address **master_addr = NULL; 165 krb5_address **local_addr = NULL; 166 167 if (is_master) 168 *is_master = FALSE; 169 else 170 return (KADM5_FAILURE); 171 172 /* Locate the master KDC */ 173 if (ret = kadm5_get_master(context, realm, &admin_host)) 174 return (ret); 175 176 if (ret = krb5_os_hostaddr(context, admin_host, &master_addr)) { 177 free(admin_host); 178 return (ret); 179 } 180 181 /* Get the local addresses */ 182 if (ret = krb5_os_localaddr(context, &local_addr)) { 183 krb5_free_addresses(context, master_addr); 184 free(admin_host); 185 return (ret); 186 } 187 188 /* Compare them */ 189 for (; *master_addr; master_addr++) { 190 if (krb5_address_search(context, *master_addr, local_addr)) { 191 *is_master = TRUE; 192 break; 193 } 194 } 195 196 krb5_free_addresses(context, local_addr); 197 krb5_free_addresses(context, master_addr); 198 free(admin_host); 199 200 return (KADM5_OK); 201 } 202