Merge illumos-gate
[unleashed/lotheac.git] / usr / src / lib / krb5 / kadm5 / kadm_host_srv_names.c
blobbc94473d370511a0d78df892f1dd0692fdbda2f1
1 /*
2 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
3 */
5 /*
6 * lib/kad5/kadm_host_srv_names.c
7 */
9 #include <k5-int.h>
10 #include "admin.h"
11 #include <stdio.h>
12 #include <os-proto.h>
15 #define KADM5_MASTER "admin_server"
16 #define KADM5_KPASSWD "kpasswd_server"
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.
24 kadm5_ret_t
25 kadm5_get_master(krb5_context context, const char *realm, char **master)
27 /* Solaris Kerberos */
28 char *def_realm = NULL;
30 char *delim;
31 #ifdef KRB5_DNS_LOOKUP
32 struct sockaddr *addrs;
33 int naddrs;
34 unsigned short dns_portno;
35 char dns_host[MAX_DNS_NAMELEN];
36 krb5_data dns_realm;
37 krb5_error_code dns_ret = 1;
38 #endif /* KRB5_DNS_LOOKUP */
40 if (realm == 0 || *realm == '\0')
41 krb5_get_default_realm(context, &def_realm);
43 (void) profile_get_string(context->profile, "realms",
44 realm ? realm : def_realm,
45 KADM5_MASTER, 0, master);
47 if ((*master != NULL) && ((delim = strchr(*master, ':')) != NULL))
48 *delim = '\0';
49 #ifdef KRB5_DNS_LOOKUP
50 if (*master == NULL) {
52 * Initialize realm info for (possible) DNS lookups.
54 dns_realm.data = strdup(realm ? realm : def_realm);
55 dns_realm.length = strlen(realm ? realm : def_realm);
56 dns_realm.magic = 0;
58 dns_ret = krb5_get_servername(context, &dns_realm,
59 "_kerberos-adm", "_udp",
60 dns_host, &dns_portno);
61 if (dns_ret == 0)
62 *master = strdup(dns_host);
64 free(dns_realm.data);
66 #endif /* KRB5_DNS_LOOKUP */
68 /* Solaris Kerberos */
69 if (def_realm != NULL)
70 krb5_free_default_realm(context, def_realm);
72 return (*master ? KADM5_OK : KADM5_NO_SRV);
76 * Find the kpasswd server for the given realm. If the realm is null or
77 * the empty string, find the admin server for the default realm.
78 * Returns 0 on succsess (KADM5_OK). It is the callers responsibility to
79 * free the storage allocated to the admin server, master.
81 kadm5_ret_t
82 kadm5_get_kpasswd(krb5_context context, const char *realm, char **kpasswd)
84 char *def_realm = NULL;
85 char *delim;
86 #ifdef KRB5_DNS_LOOKUP
87 struct sockaddr *addrs;
88 int naddrs;
89 unsigned short dns_portno;
90 char dns_host[MAX_DNS_NAMELEN];
91 krb5_data dns_realm;
92 krb5_error_code dns_ret = 1, ret;
93 #endif /* KRB5_DNS_LOOKUP */
95 if (realm == 0 || *realm == '\0') {
96 ret = krb5_get_default_realm(context, &def_realm);
97 if (ret != 0)
98 return (ret);
101 (void) profile_get_string(context->profile, "realms",
102 realm ? realm : def_realm,
103 KADM5_KPASSWD, 0, kpasswd);
105 if ((*kpasswd != NULL) && ((delim = strchr(*kpasswd, ':')) != NULL))
106 *delim = '\0';
107 #ifdef KRB5_DNS_LOOKUP
108 if (*kpasswd == NULL) {
110 * Initialize realm info for (possible) DNS lookups.
112 dns_realm.data = strdup(realm ? realm : def_realm);
113 if (dns_realm.data == NULL) {
114 free(def_realm);
115 return (ENOMEM);
117 dns_realm.length = strlen(realm ? realm : def_realm);
118 dns_realm.magic = 0;
120 dns_ret = krb5_get_servername(context, &dns_realm,
121 "_kpasswd", "_tcp",
122 dns_host, &dns_portno);
123 if (dns_ret == 0) {
124 *kpasswd = strdup(dns_host);
126 if (*kpasswd == NULL) {
127 free(dns_realm.data);
128 free(def_realm);
129 return (ENOMEM);
133 free(dns_realm.data);
135 #endif /* KRB5_DNS_LOOKUP */
137 free(def_realm);
138 return (*kpasswd ? KADM5_OK : KADM5_NO_SRV);
142 * Get the host base service name for the admin principal. Returns
143 * KADM5_OK on success. Caller must free the storage allocated for
144 * host_service_name.
146 kadm5_ret_t
147 kadm5_get_adm_host_srv_name(krb5_context context,
148 const char *realm, char **host_service_name)
150 kadm5_ret_t ret;
151 char *name;
152 char *host;
155 if (ret = kadm5_get_master(context, realm, &host))
156 return (ret);
158 name = malloc(strlen(KADM5_ADMIN_HOST_SERVICE)+ strlen(host) + 2);
159 if (name == NULL) {
160 free(host);
161 return (ENOMEM);
163 sprintf(name, "%s@%s", KADM5_ADMIN_HOST_SERVICE, host);
164 free(host);
165 *host_service_name = name;
167 return (KADM5_OK);
171 * Get the host base service name for the changepw principal. Returns
172 * KADM5_OK on success. Caller must free the storage allocated for
173 * host_service_name.
175 kadm5_ret_t
176 kadm5_get_cpw_host_srv_name(krb5_context context,
177 const char *realm, char **host_service_name)
179 kadm5_ret_t ret;
180 char *name;
181 char *host;
184 * First try to find the kpasswd server, after all we are about to
185 * try to change our password. If this fails then try admin_server.
187 if (ret = kadm5_get_kpasswd(context, realm, &host)) {
188 if (ret = kadm5_get_master(context, realm, &host))
189 return (ret);
192 name = malloc(strlen(KADM5_CHANGEPW_HOST_SERVICE) + strlen(host) + 2);
193 if (name == NULL) {
194 free(host);
195 return (ENOMEM);
197 sprintf(name, "%s@%s", KADM5_CHANGEPW_HOST_SERVICE, host);
198 free(host);
199 *host_service_name = name;
201 return (KADM5_OK);
205 * Get the host base service name for the kiprop principal. Returns
206 * KADM5_OK on success. Caller must free the storage allocated
207 * for host_service_name.
209 kadm5_ret_t kadm5_get_kiprop_host_srv_name(krb5_context context,
210 const char *realm,
211 char **host_service_name) {
212 kadm5_ret_t ret;
213 char *name;
214 char *host;
217 if (ret = kadm5_get_master(context, realm, &host))
218 return (ret);
220 name = malloc(strlen(KADM5_KIPROP_HOST_SERVICE) + strlen(host) + 2);
221 if (name == NULL) {
222 free(host);
223 return (ENOMEM);
225 sprintf(name, "%s@%s", KADM5_KIPROP_HOST_SERVICE, host);
226 free(host);
227 *host_service_name = name;
229 return (KADM5_OK);
233 * Solaris Kerberos:
234 * Try to determine if this is the master KDC for a given realm
236 kadm5_ret_t kadm5_is_master(krb5_context context, const char *realm,
237 krb5_boolean *is_master) {
239 kadm5_ret_t ret;
240 char *admin_host = NULL;
241 krb5_address **tmp_addr, **master_addr = NULL;
242 krb5_address **local_addr = NULL;
244 if (is_master)
245 *is_master = FALSE;
246 else
247 return (KADM5_FAILURE);
249 /* Locate the master KDC */
250 if (ret = kadm5_get_master(context, realm, &admin_host))
251 return (ret);
253 if (ret = krb5_os_hostaddr(context, admin_host, &master_addr)) {
254 free(admin_host);
255 return (ret);
258 /* Get the local addresses */
259 if (ret = krb5_os_localaddr(context, &local_addr)) {
260 krb5_free_addresses(context, master_addr);
261 free(admin_host);
262 return (ret);
265 /* Compare them */
266 for (tmp_addr = master_addr; *tmp_addr; tmp_addr++) {
267 if (krb5_address_search(context, *tmp_addr, local_addr)) {
268 *is_master = TRUE;
269 break;
273 krb5_free_addresses(context, local_addr);
274 krb5_free_addresses(context, master_addr);
275 free(admin_host);
277 return (KADM5_OK);