/* * The following are based on krb5_libdefault_* functions in * src/lib/krb5/krb/get_in_tkt.c * N.B. This assumes that context->default_realm has * already been established. */ krb5_error_code pkinit_kdcdefault_strings(krb5_context context, const char *realmname, const char *option, char ***ret_value) { profile_t profile = NULL; const char *names[5]; char **values = NULL; krb5_error_code retval; if (context == NULL) return KV5M_CONTEXT; profile = context->profile; if (realmname != NULL) { /* * Try number one: * * [realms] * REALM = { * option = <value> * } */ names[0] = "realms"; names[1] = realmname; names[2] = option; names[3] = 0; retval = profile_get_values(profile, names, &values); if (retval == 0 && values != NULL) goto goodbye; } /* * Try number two: * * [kdcdefaults] * option = <value> */ names[0] = "kdcdefaults"; names[1] = option; names[2] = 0; retval = profile_get_values(profile, names, &values); if (retval == 0 && values != NULL) goto goodbye; goodbye: if (values == NULL) retval = ENOENT; *ret_value = values; return retval; }
static void profile_name_change(const char *profile, void *dummy) { /* Active profile has changed */ /* get values for the new profile */ (void)dummy; profileval_t *values = NULL; #if 0 OHM_INFO("profile: active profile has changed: '%s'", profile); #endif if (!profile) return; values = profile_get_values(profile); /* empty 'values' means that the profile is empty */ /* change profile data */ profile_create_fact(profile, values); profile_free_values(values); }
static krb5_error_code prof_locate_server (krb5_context context, const krb5_data *realm, char ***hostlist, enum locate_service_type svc) { const char *realm_srv_names[4]; char **hl, *host, *profname; krb5_error_code code; int i, j, count; *hostlist = NULL; /* default - indicate no KDCs found */ switch (svc) { case locate_service_kdc: profname = "kdc"; break; case locate_service_master_kdc: profname = "master_kdc"; break; case locate_service_kadmin: profname = "admin_server"; break; case locate_service_krb524: profname = "krb524_server"; break; case locate_service_kpasswd: profname = "kpasswd_server"; break; default: return EINVAL; } if ((host = malloc(realm->length + 1)) == NULL) return ENOMEM; (void) strncpy(host, realm->data, realm->length); host[realm->length] = '\0'; hl = 0; realm_srv_names[0] = "realms"; realm_srv_names[1] = host; realm_srv_names[2] = profname; realm_srv_names[3] = 0; code = profile_get_values(context->profile, realm_srv_names, &hl); if (code) { Tprintf ("config file lookup failed: %s\n", error_message(code)); if (code == PROF_NO_SECTION || code == PROF_NO_RELATION) code = KRB5_REALM_UNKNOWN; krb5_xfree(host); return code; } krb5_xfree(host); *hostlist = hl; return 0; }
bool sss_krb5_realm_has_proxy(const char *realm) { krb5_context context = NULL; krb5_error_code kerr; struct _profile_t *profile = NULL; const char *profile_path[4] = {"realms", NULL, "kdc", NULL}; char **list = NULL; bool res = false; size_t c; if (realm == NULL) { return false; } kerr = krb5_init_context(&context); if (kerr != 0) { DEBUG(SSSDBG_OP_FAILURE, "krb5_init_context failed.\n"); return false; } kerr = krb5_get_profile(context, &profile); if (kerr != 0) { DEBUG(SSSDBG_OP_FAILURE, "krb5_get_profile failed.\n"); goto done; } profile_path[1] = realm; kerr = profile_get_values(profile, profile_path, &list); if (kerr == PROF_NO_RELATION || kerr == PROF_NO_SECTION) { kerr = 0; goto done; } else if (kerr != 0) { DEBUG(SSSDBG_OP_FAILURE, "profile_get_values failed.\n"); goto done; } for (c = 0; list[c] != NULL; c++) { if (strncasecmp(KDC_PROXY_INDICATOR, list[c], KDC_PROXY_INDICATOR_LEN) == 0) { DEBUG(SSSDBG_TRACE_ALL, "Found KDC Proxy indicator [%s] in [%s].\n", KDC_PROXY_INDICATOR, list[c]); res = true; break; } } done: profile_free_list(list); profile_release(profile); krb5_free_context(context); return res; }
static void query_current_values (NCore *core) { NContext *context = n_core_get_context (core); char **profiles = NULL; char **p = NULL; const char *current = NULL; profileval_t *values = NULL; profileval_t *v = NULL; gboolean is_current = FALSE; profiles = profile_get_profiles (); current = n_value_get_string ((NValue*) n_context_get_value (context, "profile.current_profile")); for (p = profiles; *p; ++p) { is_current = current && g_str_equal (current, *p); values = profile_get_values (*p); for (v = values; v->pv_key; ++v) { update_context_value (context, *p, v->pv_key, v->pv_val); if (is_current) update_context_value (context, NULL, v->pv_key, v->pv_val); } profile_free_values (values); } /* fallbacks */ /* This is in a way a bug, since profiled doesn't expose fallback settings ever, * but, when requesting non-existing profile, profile_get_values() returns * fallback profile contents. */ values = profile_get_values ("fallback"); for (v = values; v->pv_key; ++v) update_context_value (context, "fallback", v->pv_key, v->pv_val); profile_free_values (values); profile_free_profiles (profiles); }
/* Get the list of values for the profile variable varname in the section for * interface id, or NULL if no values are set. */ static krb5_error_code get_profile_var(krb5_context context, int id, const char *varname, char ***out) { krb5_error_code ret; const char *path[4]; *out = NULL; path[0] = KRB5_CONF_PLUGINS; path[1] = interface_names[id]; path[2] = varname; path[3] = NULL; ret = profile_get_values(context->profile, path, out); return (ret == PROF_NO_RELATION) ? 0 : ret; }
/* * Get realm list from "capaths" section of the profile. Deliberately * returns success but leaves VALS null if profile_get_values() fails * by not finding anything. */ static krb5_error_code rtree_capath_vals( krb5_context context, const krb5_data *client, const krb5_data *server, char ***vals) { krb5_error_code retval = 0; /* null-terminated realm names */ char *clientz = NULL, *serverz = NULL; const char *key[4]; *vals = NULL; clientz = calloc(client->length + 1, 1); if (clientz == NULL) { retval = ENOMEM; goto error; } memcpy(clientz, client->data, client->length); serverz = calloc(server->length + 1, 1); if (serverz == NULL) { retval = ENOMEM; goto error; } memcpy(serverz, server->data, server->length); key[0] = "capaths"; key[1] = clientz; key[2] = serverz; key[3] = NULL; retval = profile_get_values(context->profile, key, vals); switch (retval) { case PROF_NO_SECTION: case PROF_NO_RELATION: /* * Not found; don't return an error. */ retval = 0; break; default: break; } error: free(clientz); free(serverz); return retval; }
profile_plugin * init_profile() { profile_plugin *plugin = g_new0(profile_plugin, 1); char *profile = NULL; profileval_t *values = NULL; if (!plugin) { return NULL; } /* let libprofile know the correct bus connection */ profile_connection_set(bus_conn); /* get current profile */ profile = profile_get_profile(); /* start tracking profile changes */ if (profile && subscribe_to_service()) { values = profile_get_values(profile); } else { g_free(plugin); plugin = NULL; goto end; } if (!profile_create_fact(profile, values)) { g_free(plugin); plugin = NULL; goto end; } end: free(profile); profile_free_values(values); return plugin; }
/* Set up conn->http.tls. Return true on success. */ static krb5_boolean setup_tls(krb5_context context, const krb5_data *realm, struct conn_state *conn, struct select_state *selstate) { krb5_error_code ret; krb5_boolean ok = FALSE; char **anchors = NULL, *realmstr = NULL; const char *names[4]; if (init_tls_vtable(context) != 0 || context->tls->setup == NULL) return FALSE; realmstr = k5memdup0(realm->data, realm->length, &ret); if (realmstr == NULL) goto cleanup; /* Load the configured anchors. */ names[0] = KRB5_CONF_REALMS; names[1] = realmstr; names[2] = KRB5_CONF_HTTP_ANCHORS; names[3] = NULL; ret = profile_get_values(context->profile, names, &anchors); if (ret != 0 && ret != PROF_NO_RELATION) goto cleanup; if (context->tls->setup(context, conn->fd, conn->http.servername, anchors, &conn->http.tls) != 0) { TRACE_SENDTO_KDC_HTTPS_ERROR_CONNECT(context, &conn->addr); goto cleanup; } ok = TRUE; cleanup: free(realmstr); profile_free_list(anchors); return ok; }
krb5_error_code pkinit_libdefault_strings(krb5_context context, const krb5_data *realm, const char *option, char ***ret_value) { profile_t profile; const char *names[5]; char **values = NULL; krb5_error_code retval; char realmstr[1024]; if (realm != NULL && realm->length > sizeof(realmstr)-1) return EINVAL; if (realm != NULL) { strncpy(realmstr, realm->data, realm->length); realmstr[realm->length] = '\0'; } if (!context || (context->magic != KV5M_CONTEXT)) return KV5M_CONTEXT; profile = context->profile; if (realm != NULL) { /* * Try number one: * * [libdefaults] * REALM = { * option = <value> * } */ names[0] = "libdefaults"; names[1] = realmstr; names[2] = option; names[3] = 0; retval = profile_get_values(profile, names, &values); if (retval == 0 && values != NULL && values[0] != NULL) goto goodbye; /* * Try number two: * * [realms] * REALM = { * option = <value> * } */ names[0] = "realms"; names[1] = realmstr; names[2] = option; names[3] = 0; retval = profile_get_values(profile, names, &values); if (retval == 0 && values != NULL && values[0] != NULL) goto goodbye; } /* * Try number three: * * [libdefaults] * option = <value> */ names[0] = "libdefaults"; names[1] = option; names[2] = 0; retval = profile_get_values(profile, names, &values); if (retval == 0 && values != NULL && values[0] != NULL) goto goodbye; goodbye: if (values == NULL) return ENOENT; *ret_value = values; return retval; }
static krb5_error_code kdb_load_library(krb5_context kcontext, char *lib_name, db_library * lib) { krb5_error_code status = 0; int ndx; void **vftabl_addrs = NULL; /* N.B.: If this is "const" but not "static", the Solaris 10 native compiler has trouble building the library because of absolute relocations needed in read-only section ".rodata". When it's static, it goes into ".picdata", which is read-write. */ static const char *const dbpath_names[] = { KDB_MODULE_SECTION, "db_module_dir", NULL, }; const char *filebases[2]; char **profpath = NULL; char **path = NULL; filebases[0] = lib_name; filebases[1] = NULL; if (!strcmp(DB2_NAME, lib_name) && (kdb_db2_pol_err_loaded == 0)) { initialize_adb_error_table(); kdb_db2_pol_err_loaded = 1; } *lib = calloc((size_t) 1, sizeof(**lib)); if (*lib == NULL) { status = ENOMEM; goto clean_n_exit; } status = kdb_init_lib_lock(*lib); if (status) { goto clean_n_exit; } strcpy((*lib)->name, lib_name); /* Fetch the list of directories specified in the config file(s) first. */ status = profile_get_values(kcontext->profile, dbpath_names, &profpath); if (status != 0 && status != PROF_NO_RELATION) goto clean_n_exit; ndx = 0; if (profpath) while (profpath[ndx] != NULL) ndx++; path = calloc(ndx + db_dl_n_locations, sizeof (char *)); if (path == NULL) { status = errno; goto clean_n_exit; } if (ndx) memcpy(path, profpath, ndx * sizeof(profpath[0])); memcpy(path + ndx, db_dl_location, db_dl_n_locations * sizeof(char *)); status = 0; if ((status = krb5int_open_plugin_dirs ((const char **) path, filebases, &(*lib)->dl_dir_handle, &kcontext->err))) { char *err_str = krb5_get_error_message(kcontext, status); status = KRB5_KDB_DBTYPE_NOTFOUND; krb5_set_error_message (kcontext, status, "Unable to find requested database type: %s", err_str); krb5_free_error_message (kcontext, err_str); goto clean_n_exit; } if ((status = krb5int_get_plugin_dir_data (&(*lib)->dl_dir_handle, "kdb_function_table", &vftabl_addrs, &kcontext->err))) { char *err_str = krb5_get_error_message(kcontext, status); status = KRB5_KDB_DBTYPE_INIT; krb5_set_error_message (kcontext, status, "plugin symbol 'kdb_function_table' lookup failed: %s", err_str); krb5_free_error_message (kcontext, err_str); goto clean_n_exit; } if (vftabl_addrs[0] == NULL) { /* No plugins! */ status = KRB5_KDB_DBTYPE_NOTFOUND; krb5_set_error_message (kcontext, status, _("Unable to load requested database module '%s': plugin symbol 'kdb_function_table' not found"), lib_name); goto clean_n_exit; } memcpy(&(*lib)->vftabl, vftabl_addrs[0], sizeof(kdb_vftabl)); kdb_setup_opt_functions(*lib); if ((status = (*lib)->vftabl.init_library())) { /* ERROR. library not initialized cleanly */ goto clean_n_exit; } clean_n_exit: if (vftabl_addrs != NULL) { krb5int_free_plugin_dir_data (vftabl_addrs); } /* Both of these DTRT with NULL. */ profile_free_list(profpath); free(path); if (status) { if (*lib) { kdb_destroy_lib_lock(*lib); if (PLUGIN_DIR_OPEN((&(*lib)->dl_dir_handle))) { krb5int_close_plugin_dirs (&(*lib)->dl_dir_handle); } free(*lib); *lib = NULL; } } return status; }
krb5_error_code KRB5_CALLCONV krb5_425_conv_principal(krb5_context context, const char *name, const char *instance, const char *realm, krb5_principal *princ) { const struct krb_convert *p; char buf[256]; /* V4 instances are limited to 40 characters */ krb5_error_code retval; char *domain, *cp; char **full_name = 0; const char *names[5], *names2[2]; void* iterator = NULL; char** v4realms = NULL; char* realm_name = NULL; char* dummy_value = NULL; /* First, convert the realm, since the v4 realm is not necessarily the same as the v5 realm To do that, iterate over all the realms in the config file, looking for a matching v4_realm line */ names2 [0] = "realms"; names2 [1] = NULL; retval = profile_iterator_create (context -> profile, names2, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &iterator); while (retval == 0) { retval = profile_iterator (&iterator, &realm_name, &dummy_value); if ((retval == 0) && (realm_name != NULL)) { names [0] = "realms"; names [1] = realm_name; names [2] = "v4_realm"; names [3] = NULL; retval = profile_get_values (context -> profile, names, &v4realms); if ((retval == 0) && (v4realms != NULL) && (v4realms [0] != NULL) && (strcmp (v4realms [0], realm) == 0)) { realm = realm_name; break; } else if (retval == PROF_NO_RELATION) { /* If it's not found, just keep going */ retval = 0; } } else if ((retval == 0) && (realm_name == NULL)) { break; } if (v4realms != NULL) { profile_free_list(v4realms); v4realms = NULL; } if (realm_name != NULL) { profile_release_string (realm_name); realm_name = NULL; } if (dummy_value != NULL) { profile_release_string (dummy_value); dummy_value = NULL; } } if (instance) { if (instance[0] == '\0') { instance = 0; goto not_service; } p = sconv_list; while (1) { if (!p->v4_str) goto not_service; if (!strcmp(p->v4_str, name)) break; p++; } name = p->v5_str; if ((p->flags & DO_REALM_CONVERSION) && !strchr(instance, '.')) { names[0] = "realms"; names[1] = realm; names[2] = "v4_instance_convert"; names[3] = instance; names[4] = 0; retval = profile_get_values(context->profile, names, &full_name); if (retval == 0 && full_name && full_name[0]) { instance = full_name[0]; } else { strncpy(buf, instance, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; retval = krb5_get_realm_domain(context, realm, &domain); if (retval) return retval; if (domain) { for (cp = domain; *cp; cp++) if (isupper((unsigned char) (*cp))) *cp = tolower((unsigned char) *cp); strncat(buf, ".", sizeof(buf) - 1 - strlen(buf)); strncat(buf, domain, sizeof(buf) - 1 - strlen(buf)); krb5_xfree(domain); } instance = buf; } } } not_service: retval = krb5_build_principal(context, princ, strlen(realm), realm, name, instance, NULL); if (iterator) profile_iterator_free (&iterator); if (full_name) profile_free_list(full_name); if (v4realms) profile_free_list(v4realms); if (realm_name) profile_release_string (realm_name); if (dummy_value) profile_release_string (dummy_value); return retval; }
krb5_error_code krb5_walk_realm_tree(krb5_context context, const krb5_data *client, const krb5_data *server, krb5_principal **tree, int realm_branch_char) { krb5_error_code retval; krb5_principal *rettree; register char *ccp, *scp; register char *prevccp = 0, *prevscp = 0; char *com_sdot = 0, *com_cdot = 0; register int i, links = 0; int clen, slen = -1; krb5_data tmpcrealm, tmpsrealm; int nocommon = 1; #ifdef CONFIGURABLE_AUTHENTICATION_PATH const char *cap_names[4]; char *cap_client, *cap_server; char **cap_nodes; krb5_error_code cap_code; #endif #ifdef DEBUG_REFERRALS printf("krb5_walk_realm_tree starting\n"); printf(" client is %s\n",client->data); printf(" server is %s\n",server->data); #endif if (!(client->data && server->data)) { /* Solaris Kerberos - enhance error message */ if (!client->data && !server->data) { krb5_set_error_message(context, KRB5_NO_TKT_IN_RLM, dgettext(TEXT_DOMAIN, "Cannot find ticket for requested realm: unknown client and server")); } else { if (!client->data) { krb5_set_error_message(context, KRB5_NO_TKT_IN_RLM, dgettext(TEXT_DOMAIN, "Cannot find ticket for requested realm: unknown client")); } else { krb5_set_error_message(context, KRB5_NO_TKT_IN_RLM, dgettext(TEXT_DOMAIN, "Cannot find ticket for requested realm: unknown server")); } } return KRB5_NO_TKT_IN_RLM; } #ifdef CONFIGURABLE_AUTHENTICATION_PATH if ((cap_client = (char *)malloc(client->length + 1)) == NULL) return ENOMEM; strncpy(cap_client, client->data, client->length); cap_client[client->length] = '\0'; if ((cap_server = (char *)malloc(server->length + 1)) == NULL) { krb5_xfree(cap_client); return ENOMEM; } strncpy(cap_server, server->data, server->length); cap_server[server->length] = '\0'; cap_names[0] = "capaths"; cap_names[1] = cap_client; cap_names[2] = cap_server; cap_names[3] = 0; cap_code = profile_get_values(context->profile, cap_names, &cap_nodes); krb5_xfree(cap_client); /* done with client string */ cap_names[1] = 0; if (cap_code == 0) { /* found a path, so lets use it */ links = 0; if (*cap_nodes[0] != '.') { /* a link of . means direct */ while(cap_nodes[links]) { links++; } } if (cap_nodes[links] != NULL) krb5_xfree(cap_nodes[links]); cap_nodes[links] = cap_server; /* put server on end of list */ /* this simplifies the code later and make */ /* cleanup eaiser as well */ links++; /* count the null entry at end */ } else { /* no path use hierarchical method */ krb5_xfree(cap_server); /* failed, don't need server string */ cap_names[2] = 0; #endif clen = client->length; slen = server->length; for (com_cdot = ccp = client->data + clen - 1, com_sdot = scp = server->data + slen - 1; clen && slen && *ccp == *scp ; ccp--, scp--, clen--, slen--) { if (*ccp == realm_branch_char) { com_cdot = ccp; com_sdot = scp; nocommon = 0; } } /* ccp, scp point to common root. com_cdot, com_sdot point to common components. */ /* handle case of one ran out */ if (!clen) { /* construct path from client to server, down the tree */ if (!slen) { /* in the same realm--this means there is no ticket in this realm. */ krb5_set_error_message(context, KRB5_NO_TKT_IN_RLM, dgettext(TEXT_DOMAIN, "Cannot find ticket for requested realm: client is '%s', server is '%s'"), client->data, server->data); return KRB5_NO_TKT_IN_RLM; } if (*scp == realm_branch_char) { /* one is a subdomain of the other */ com_cdot = client->data; com_sdot = scp; nocommon = 0; } /* else normal case of two sharing parents */ } if (!slen) { /* construct path from client to server, up the tree */ if (*ccp == realm_branch_char) { /* one is a subdomain of the other */ com_sdot = server->data; com_cdot = ccp; nocommon = 0; } /* else normal case of two sharing parents */ } /* determine #links to/from common ancestor */ if (nocommon) links = 1; else links = 2; /* if no common ancestor, artificially set up common root at the last component, then join with special code */ for (ccp = client->data; ccp < com_cdot; ccp++) { if (*ccp == realm_branch_char) { links++; if (nocommon) prevccp = ccp; } } for (scp = server->data; scp < com_sdot; scp++) { if (*scp == realm_branch_char) { links++; if (nocommon) prevscp = scp; } } if (nocommon) { if (prevccp) com_cdot = prevccp; if (prevscp) com_sdot = prevscp; if(com_cdot == client->data + client->length -1) com_cdot = client->data - 1 ; if(com_sdot == server->data + server->length -1) com_sdot = server->data - 1 ; } #ifdef CONFIGURABLE_AUTHENTICATION_PATH } /* end of if use hierarchical method */ #endif if (!(rettree = (krb5_principal *)calloc(links+2, sizeof(krb5_principal)))) { return ENOMEM; } i = 1; if ((retval = krb5_tgtname(context, client, client, &rettree[0]))) { krb5_xfree(rettree); return retval; } #ifdef CONFIGURABLE_AUTHENTICATION_PATH links--; /* dont count the null entry on end */ if (cap_code == 0) { /* found a path above */ tmpcrealm.data = client->data; tmpcrealm.length = client->length; while( i-1 <= links) { tmpsrealm.data = cap_nodes[i-1]; /* don't count trailing whitespace from profile_get */ tmpsrealm.length = strcspn(cap_nodes[i-1],"\t "); if ((retval = krb5_tgtname(context, &tmpsrealm, &tmpcrealm, &rettree[i]))) { while (i) { krb5_free_principal(context, rettree[i-1]); i--; } krb5_xfree(rettree); /* cleanup the cap_nodes from profile_get */ for (i = 0; i<=links; i++) { krb5_xfree(cap_nodes[i]); } krb5_xfree((char *)cap_nodes); return retval; } tmpcrealm.data = tmpsrealm.data; tmpcrealm.length = tmpsrealm.length; i++; } /* cleanup the cap_nodes from profile_get last one has server */ for (i = 0; i<=links; i++) { krb5_xfree(cap_nodes[i]); } krb5_xfree((char *)cap_nodes); } else { /* if not cap then use hierarchical method */ #endif for (prevccp = ccp = client->data; ccp <= com_cdot; ccp++) { if (*ccp != realm_branch_char) continue; ++ccp; /* advance past dot */ tmpcrealm.data = prevccp; tmpcrealm.length = client->length - (prevccp - client->data); tmpsrealm.data = ccp; tmpsrealm.length = client->length - (ccp - client->data); if ((retval = krb5_tgtname(context, &tmpsrealm, &tmpcrealm, &rettree[i]))) { while (i) { krb5_free_principal(context, rettree[i-1]); i--; } krb5_xfree(rettree); return retval; } prevccp = ccp; i++; } if (nocommon) { tmpcrealm.data = com_cdot + 1; tmpcrealm.length = client->length - (com_cdot + 1 - client->data); tmpsrealm.data = com_sdot + 1; tmpsrealm.length = server->length - (com_sdot + 1 - server->data); if ((retval = krb5_tgtname(context, &tmpsrealm, &tmpcrealm, &rettree[i]))) { while (i) { krb5_free_principal(context, rettree[i-1]); i--; } krb5_xfree(rettree); return retval; } i++; } for (prevscp = com_sdot + 1, scp = com_sdot - 1; scp > server->data; scp--) { if (*scp != realm_branch_char) continue; if (scp - 1 < server->data) break; /* XXX only if . starts realm? */ tmpcrealm.data = prevscp; tmpcrealm.length = server->length - (prevscp - server->data); tmpsrealm.data = scp + 1; tmpsrealm.length = server->length - (scp + 1 - server->data); if ((retval = krb5_tgtname(context, &tmpsrealm, &tmpcrealm, &rettree[i]))) { while (i) { krb5_free_principal(context, rettree[i-1]); i--; } krb5_xfree(rettree); return retval; } prevscp = scp + 1; i++; } if (slen && com_sdot >= server->data) { /* only necessary if building down tree from ancestor or client */ /* however, we can get here if we have only one component in the server realm name, hence we make sure we found a component separator there... */ tmpcrealm.data = prevscp; tmpcrealm.length = server->length - (prevscp - server->data); if ((retval = krb5_tgtname(context, server, &tmpcrealm, &rettree[i]))) { while (i) { krb5_free_principal(context, rettree[i-1]); i--; } krb5_xfree(rettree); return retval; } } #ifdef CONFIGURABLE_AUTHENTICATION_PATH } #endif *tree = rettree; #ifdef DEBUG_REFERRALS printf("krb5_walk_realm_tree ending; tree (length %d) is:\n",links); for(i=0;i<links+2;i++) { if ((*tree)[i]) krb5int_dbgref_dump_principal("krb5_walk_realm_tree tree",(*tree)[i]); else printf("tree element %i null\n"); } #endif return 0; }
static krb5_error_code locate_srv_conf_1(krb5_context context, const krb5_data *realm, const char * name, struct serverlist *serverlist, int socktype, int udpport, int sec_udpport) { const char *realm_srv_names[4]; char **hostlist, *host, *port, *cp; krb5_error_code code; int i; Tprintf ("looking in krb5.conf for realm %s entry %s; ports %d,%d\n", realm->data, name, ntohs (udpport), ntohs (sec_udpport)); if ((host = malloc(realm->length + 1)) == NULL) return ENOMEM; strncpy(host, realm->data, realm->length); host[realm->length] = '\0'; hostlist = 0; realm_srv_names[0] = KRB5_CONF_REALMS; realm_srv_names[1] = host; realm_srv_names[2] = name; realm_srv_names[3] = 0; code = profile_get_values(context->profile, realm_srv_names, &hostlist); free(host); if (code) { Tprintf ("config file lookup failed: %s\n", error_message(code)); if (code == PROF_NO_SECTION || code == PROF_NO_RELATION) code = 0; return code; } for (i=0; hostlist[i]; i++) { int p1, p2; host = hostlist[i]; Tprintf ("entry %d is '%s'\n", i, host); /* Find port number, and strip off any excess characters. */ if (*host == '[' && (cp = strchr(host, ']'))) cp = cp + 1; else cp = host + strcspn(host, " \t:"); port = (*cp == ':') ? cp + 1 : NULL; *cp = '\0'; if (port) { unsigned long l; #ifdef HAVE_STROUL char *endptr; l = strtoul (port, &endptr, 10); if (endptr == NULL || *endptr != 0) return EINVAL; #else l = atoi (port); #endif /* L is unsigned, don't need to check <0. */ if (l > 65535) return EINVAL; p1 = htons (l); p2 = 0; } else { p1 = udpport; p2 = sec_udpport; } /* If the hostname was in brackets, strip those off now. */ if (*host == '[' && (cp = strchr(host, ']'))) { host++; *cp = '\0'; } code = add_host_to_list(serverlist, host, p1, socktype, AF_UNSPEC); /* Second port is for IPv4 UDP only, and should possibly go away as * it was originally a krb4 compatibility measure. */ if (code == 0 && p2 != 0 && (socktype == 0 || socktype == SOCK_DGRAM)) code = add_host_to_list(serverlist, host, p2, SOCK_DGRAM, AF_INET); if (code) goto cleanup; } cleanup: profile_free_list(hostlist); return code; }
krb5_error_code krb5_get_krbhst(krb5_context context, const krb5_data *realm, char ***hostlist) { char **values, **cpp, *cp; const char *realm_kdc_names[4]; krb5_error_code retval; int i, count; char **rethosts; rethosts = 0; realm_kdc_names[0] = "realms"; realm_kdc_names[1] = realm->data; realm_kdc_names[2] = "kdc"; realm_kdc_names[3] = 0; if (context->profile == 0) return KRB5_CONFIG_CANTOPEN; retval = profile_get_values(context->profile, realm_kdc_names, &values); if (retval == PROF_NO_SECTION) return KRB5_REALM_UNKNOWN; if (retval == PROF_NO_RELATION) return KRB5_CONFIG_BADFORMAT; if (retval) return retval; /* * Do cleanup over the list. We allow for some extra field to be * added to the kdc line later (maybe the port number) */ for (cpp = values; *cpp; cpp++) { cp = strchr(*cpp, ' '); if (cp) *cp = 0; cp = strchr(*cpp, '\t'); if (cp) *cp = 0; cp = strchr(*cpp, ':'); if (cp) *cp = 0; } count = cpp - values; rethosts = malloc(sizeof(char *) * (count + 1)); if (!rethosts) { retval = ENOMEM; goto cleanup; } for (i = 0; i < count; i++) { unsigned int len = strlen (values[i]) + 1; rethosts[i] = malloc(len); if (!rethosts[i]) { retval = ENOMEM; goto cleanup; } memcpy (rethosts[i], values[i], len); } rethosts[count] = 0; cleanup: if (retval && rethosts) { for (cpp = rethosts; *cpp; cpp++) free(*cpp); free(rethosts); rethosts = 0; } profile_free_list(values); *hostlist = rethosts; return retval; }
int main(int argc, char **argv) { int opt; char *p,*k,*v,**w; while( (opt = getopt(argc, argv, "hp:s:d:g:t:TlkvV:B:I:D:G:rR:")) != -1 ) { switch (opt) { case 'h': write(STDOUT_FILENO, usage, sizeof usage - 1); exit(0); case 'p': profile_set_profile(optarg); break; case 'l': p = profile_get_profile(); w = profile_get_profiles(); for( size_t i = 0; w && w[i]; ++i ) { printf("%s%s\n", w[i], strcmp(w[i],p) ? "" : "*"); } profile_free_profiles(w); free(p); break; case 'k': w = profile_get_keys(); for( size_t i = 0; w && w[i]; ++i ) { printf("%s\n", w[i]); } profile_free_keys(w); break; case 'r': w = profile_get_keys(); for( size_t i = 0; w && w[i]; ++i ) { profile_set_value(0, w[i], ""); } profile_free_keys(w); break; case 'R': w = profile_get_keys(); for( size_t i = 0; w && w[i]; ++i ) { profile_set_value(optarg, w[i], ""); } profile_free_keys(w); break; case 'v': case 'V': { p = (opt == 'v') ? 0 : optarg; profileval_t *t = profile_get_values(p); for( size_t i = 0; t && t[i].pv_key; ++i ) { printf("%s = %s (%s)\n", t[i].pv_key, t[i].pv_val, t[i].pv_type); } profile_free_values(t); } break; case 'T': exit(track()); case 's': parse(optarg, &p,&k,&v); profile_set_value(p, k, v); break; case 'd': parse(optarg, &p,&k,&v); profile_set_value(p, k, ""); break; case 'g': parse(optarg, &p,&k,&v); v = profile_get_value(p,k); printf("%s\n", v); free(v); break; case 'G': { parse(optarg, &p,&k,&v); char *s = profile_get_value(p,k); printf("STRING: '%s'\n", s); free(s); int b = profile_get_value_as_bool(p,k); printf("BOOL: %s (%d)\n", b ? "On" : "Off", b); int i = profile_get_value_as_int(p,k); printf("INT: %d\n", i); double d = profile_get_value_as_double(p,k); printf("DOUBLE:%g\n", d); } break; case 'B': { parse(optarg, &p,&k,&v); int v = profile_get_value_as_bool(p,k); printf("BOOL:%s (%d)\n", v ? "On" : "Off", v); } break; case 'I': { parse(optarg, &p,&k,&v); int v = profile_get_value_as_int(p,k); printf("INT:%d\n", v); } break; case 'D': { parse(optarg, &p,&k,&v); double v = profile_get_value_as_double(p,k); printf("DOUBLE:%g\n", v); } break; case 't': v = profile_get_type(optarg); printf("%s\n", v); free(v); break; default: /* '?' */ fprintf(stderr, "(use -h for usage info)\n"); exit(EXIT_FAILURE); } } return 0; }
/* * krb5_klog_init() - Initialize logging. * * This routine parses the syntax described above to specify destinations for * com_err(3) or krb5_klog_syslog() messages generated by the caller. * * Parameters: * kcontext - Kerberos context. * ename - Entity name as it is to appear in the profile. * whoami - Entity name as it is to appear in error output. * do_com_err - Take over com_err(3) processing. * * Implicit inputs: * stderr - This is where STDERR output goes. * * Implicit outputs: * log_nentries - Number of log entries, both valid and invalid. * log_control - List of entries (log_nentries long) which contains * data for klog_com_err_proc() to use to determine * where/how to send output. */ krb5_error_code krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do_com_err) { const char *logging_profent[3]; const char *logging_defent[3]; char **logging_specs; int i, ngood; char *cp, *cp2; char savec = '\0'; int error; int do_openlog, log_facility; FILE *f; mode_t old_umask; /* Initialize */ do_openlog = 0; log_facility = 0; err_context = kcontext; /* * Look up [logging]-><ename> in the profile. If that doesn't * succeed, then look for [logging]->default. */ logging_profent[0] = "logging"; logging_profent[1] = ename; logging_profent[2] = (char *) NULL; logging_defent[0] = "logging"; logging_defent[1] = "default"; logging_defent[2] = (char *) NULL; logging_specs = (char **) NULL; ngood = 0; log_control.log_nentries = 0; if (!profile_get_values(kcontext->profile, logging_profent, &logging_specs) || !profile_get_values(kcontext->profile, logging_defent, &logging_specs)) { /* * We have a match, so we first count the number of elements */ for (log_control.log_nentries = 0; logging_specs[log_control.log_nentries]; log_control.log_nentries++); /* * Now allocate our structure. */ log_control.log_entries = (struct log_entry *) malloc(log_control.log_nentries * sizeof(struct log_entry)); if (log_control.log_entries) { /* * Scan through the list. */ for (i=0; i<log_control.log_nentries; i++) { log_control.log_entries[i].log_type = K_LOG_NONE; log_control.log_entries[i].log_2free = logging_specs[i]; /* * The format is: * <whitespace><data><whitespace> * so, trim off the leading and trailing whitespace here. */ for (cp = logging_specs[i]; isspace((int) *cp); cp++); for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1]; isspace((int) *cp2); cp2--); cp2++; *cp2 = '\0'; /* * Is this a file? */ if (!strncasecmp(cp, "FILE", 4)) { /* * Check for append/overwrite, then open the file. */ if (cp[4] == ':' || cp[4] == '=') { log_control.log_entries[i].lfu_fopen_mode = (cp[4] == ':') ? "a+F" : "wF"; old_umask = umask(077); f = fopen(&cp[5], log_control.log_entries[i].lfu_fopen_mode); umask(old_umask); if (f) { char rotate_kw[128]; log_control.log_entries[i].lfu_filep = f; log_control.log_entries[i].log_type = K_LOG_FILE; log_control.log_entries[i].lfu_fname = &cp[5]; log_control.log_entries[i].lfu_rotate_period = K_LOG_DEF_FILE_ROTATE_PERIOD; log_control.log_entries[i].lfu_rotate_versions = K_LOG_DEF_FILE_ROTATE_VERSIONS; log_control.log_entries[i].lfu_last_rotated = time(0); /* * Now parse for ename_"rotate" = { * period = XXX * versions = 10 * } */ if (strlen(ename) + strlen("_rotate") < sizeof (rotate_kw)) { char *time; krb5_deltat dt; int vers; strcpy(rotate_kw, ename); strcat(rotate_kw, "_rotate"); if (!profile_get_string(kcontext->profile, "logging", rotate_kw, "period", NULL, &time)) { if (time != NULL) { if (!krb5_string_to_deltat(time, &dt)) { log_control.log_entries[i].lfu_rotate_period = (time_t) dt; } free(time); } } if (!profile_get_integer( kcontext->profile, "logging", rotate_kw, "versions", K_LOG_DEF_FILE_ROTATE_VERSIONS, &vers)) { log_control.log_entries[i].lfu_rotate_versions = vers; } } } else { fprintf(stderr, gettext("Couldn't open log file %s: %s\n"), &cp[5], error_message(errno)); continue; } } } #ifdef HAVE_SYSLOG /* * Is this a syslog? */ else if (!strncasecmp(cp, "SYSLOG", 6)) { error = 0; log_control.log_entries[i].lsu_facility = LOG_AUTH; log_control.log_entries[i].lsu_severity = LOG_ERR; /* * Is there a severify specified? */ if (cp[6] == ':') { /* * Find the end of the severity. */ cp2 = strchr(&cp[7], ':'); if (cp2) { savec = *cp2; *cp2 = '\0'; cp2++; } /* * Match a severity. */ if (!strcasecmp(&cp[7], "ERR")) { log_control.log_entries[i].lsu_severity = LOG_ERR; } #ifdef LOG_EMERG else if (!strcasecmp(&cp[7], "EMERG")) { log_control.log_entries[i].lsu_severity = LOG_EMERG; } #endif /* LOG_EMERG */ #ifdef LOG_ALERT else if (!strcasecmp(&cp[7], "ALERT")) { log_control.log_entries[i].lsu_severity = LOG_ALERT; } #endif /* LOG_ALERT */ #ifdef LOG_CRIT else if (!strcasecmp(&cp[7], "CRIT")) { log_control.log_entries[i].lsu_severity = LOG_CRIT; } #endif /* LOG_CRIT */ #ifdef LOG_WARNING else if (!strcasecmp(&cp[7], "WARNING")) { log_control.log_entries[i].lsu_severity = LOG_WARNING; } #endif /* LOG_WARNING */ #ifdef LOG_NOTICE else if (!strcasecmp(&cp[7], "NOTICE")) { log_control.log_entries[i].lsu_severity = LOG_NOTICE; } #endif /* LOG_NOTICE */ #ifdef LOG_INFO else if (!strcasecmp(&cp[7], "INFO")) { log_control.log_entries[i].lsu_severity = LOG_INFO; } #endif /* LOG_INFO */ #ifdef LOG_DEBUG else if (!strcasecmp(&cp[7], "DEBUG")) { log_control.log_entries[i].lsu_severity = LOG_DEBUG; } #endif /* LOG_DEBUG */ else error = 1; /* * If there is a facility present, then parse that. */ if (cp2) { if (!strcasecmp(cp2, "AUTH")) { log_control.log_entries[i].lsu_facility = LOG_AUTH; } else if (!strcasecmp(cp2, "KERN")) { log_control.log_entries[i].lsu_facility = LOG_KERN; } else if (!strcasecmp(cp2, "USER")) { log_control.log_entries[i].lsu_facility = LOG_USER; } else if (!strcasecmp(cp2, "MAIL")) { log_control.log_entries[i].lsu_facility = LOG_MAIL; } else if (!strcasecmp(cp2, "DAEMON")) { log_control.log_entries[i].lsu_facility = LOG_DAEMON; } else if (!strcasecmp(cp2, "LPR")) { log_control.log_entries[i].lsu_facility = LOG_LPR; } else if (!strcasecmp(cp2, "NEWS")) { log_control.log_entries[i].lsu_facility = LOG_NEWS; } else if (!strcasecmp(cp2, "UUCP")) { log_control.log_entries[i].lsu_facility = LOG_UUCP; } else if (!strcasecmp(cp2, "CRON")) { log_control.log_entries[i].lsu_facility = LOG_CRON; } else if (!strcasecmp(cp2, "LOCAL0")) { log_control.log_entries[i].lsu_facility = LOG_LOCAL0; } else if (!strcasecmp(cp2, "LOCAL1")) { log_control.log_entries[i].lsu_facility = LOG_LOCAL1; } else if (!strcasecmp(cp2, "LOCAL2")) { log_control.log_entries[i].lsu_facility = LOG_LOCAL2; } else if (!strcasecmp(cp2, "LOCAL3")) { log_control.log_entries[i].lsu_facility = LOG_LOCAL3; } else if (!strcasecmp(cp2, "LOCAL4")) { log_control.log_entries[i].lsu_facility = LOG_LOCAL4; } else if (!strcasecmp(cp2, "LOCAL5")) { log_control.log_entries[i].lsu_facility = LOG_LOCAL5; } else if (!strcasecmp(cp2, "LOCAL6")) { log_control.log_entries[i].lsu_facility = LOG_LOCAL6; } else if (!strcasecmp(cp2, "LOCAL7")) { log_control.log_entries[i].lsu_facility = LOG_LOCAL7; } cp2--; *cp2 = savec; } } if (!error) { log_control.log_entries[i].log_type = K_LOG_SYSLOG; do_openlog = 1; log_facility = log_control.log_entries[i].lsu_facility; } } #endif /* HAVE_SYSLOG */ /* * Is this a standard error specification? */ else if (!strcasecmp(cp, "STDERR")) { log_control.log_entries[i].lfu_filep = fdopen(fileno(stderr), "a+F"); if (log_control.log_entries[i].lfu_filep) { log_control.log_entries[i].log_type = K_LOG_STDERR; log_control.log_entries[i].lfu_fname = "standard error"; } } /* * Is this a specification of the console? */ else if (!strcasecmp(cp, "CONSOLE")) { log_control.log_entries[i].ldu_filep = CONSOLE_OPEN("a+F"); if (log_control.log_entries[i].ldu_filep) { log_control.log_entries[i].log_type = K_LOG_CONSOLE; log_control.log_entries[i].ldu_devname = "console"; } } /* * Is this a specification of a device? */ else if (!strncasecmp(cp, "DEVICE", 6)) { /* * We handle devices very similarly to files. */ if (cp[6] == '=') { log_control.log_entries[i].ldu_filep = DEVICE_OPEN(&cp[7], "wF"); if (log_control.log_entries[i].ldu_filep) { log_control.log_entries[i].log_type = K_LOG_DEVICE; log_control.log_entries[i].ldu_devname = &cp[7]; } } } /* * See if we successfully parsed this specification. */ if (log_control.log_entries[i].log_type == K_LOG_NONE) { fprintf(stderr, krb5_log_error_table(LSPEC_PARSE_ERR_1), whoami, cp); fprintf(stderr, krb5_log_error_table(LSPEC_PARSE_ERR_2), whoami); } else ngood++; } } /* * If we didn't find anything, then free our lists. */ if (ngood == 0) { for (i=0; i<log_control.log_nentries; i++) free(logging_specs[i]); } free(logging_specs); } /* * If we didn't find anything, go for the default which is to log to * the system log. */ if (ngood == 0) { if (log_control.log_entries) free(log_control.log_entries); log_control.log_entries = &def_log_entry; log_control.log_entries->log_type = K_LOG_SYSLOG; log_control.log_entries->log_2free = (krb5_pointer) NULL; log_facility = log_control.log_entries->lsu_facility = LOG_AUTH; log_control.log_entries->lsu_severity = LOG_ERR; do_openlog = 1; log_control.log_nentries = 1; } if (log_control.log_nentries) { log_control.log_whoami = (char *) malloc(strlen(whoami)+1); if (log_control.log_whoami) strcpy(log_control.log_whoami, whoami); log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN + 1); if (log_control.log_hostname) { gethostname(log_control.log_hostname, MAXHOSTNAMELEN); log_control.log_hostname[MAXHOSTNAMELEN] = '\0'; } #ifdef HAVE_OPENLOG if (do_openlog) { openlog(whoami, LOG_NDELAY|LOG_PID, log_facility); log_control.log_opened = 1; } #endif /* HAVE_OPENLOG */ if (do_com_err) (void) set_com_err_hook(klog_com_err_proc); } return((log_control.log_nentries) ? 0 : ENOENT); }
static krb5_error_code appdefault_get(krb5_context context, const char *appname, const krb5_data *realm, const char *option, char **ret_value) { profile_t profile; const char *names[5]; char **nameval = NULL; krb5_error_code retval; const char * realmstr = realm?realm->data:NULL; if (!context || (context->magic != KV5M_CONTEXT)) return KV5M_CONTEXT; profile = context->profile; /* * Try number one: * * [appdefaults] * app = { * SOME.REALM = { * option = <boolean> * } * } */ names[0] = "appdefaults"; names[1] = appname; if (realmstr) { names[2] = realmstr; names[3] = option; names[4] = 0; retval = profile_get_values(profile, names, &nameval); if (retval == 0 && nameval && nameval[0]) { *ret_value = strdup(nameval[0]); goto goodbye; } } /* * Try number two: * * [appdefaults] * app = { * option = <boolean> * } */ names[2] = option; names[3] = 0; retval = profile_get_values(profile, names, &nameval); if (retval == 0 && nameval && nameval[0]) { *ret_value = strdup(nameval[0]); goto goodbye; } /* * Try number three: * * [appdefaults] * realm = { * option = <boolean> */ if (realmstr) { names[1] = realmstr; names[2] = option; names[3] = 0; retval = profile_get_values(profile, names, &nameval); if (retval == 0 && nameval && nameval[0]) { *ret_value = strdup(nameval[0]); goto goodbye; } } /* * Try number four: * * [appdefaults] * option = <boolean> */ names[1] = option; names[2] = 0; retval = profile_get_values(profile, names, &nameval); if (retval == 0 && nameval && nameval[0]) { *ret_value = strdup(nameval[0]); } else { return retval; } goodbye: if (nameval) { char **cpp; for (cpp = nameval; *cpp; cpp++) free(*cpp); free(nameval); } return 0; }
/*! * A method for getting AlertTone objects for all * available settings (ringing, voip, email, sms, im) * * \return AlertTone instances... */ QList<AlertTone *> AlertTone::alertTones () { QList<AlertTone *> v; #ifdef HAVE_LIBPROFILE #ifdef WANT_PROFILED_CHECKS QList<QString> keys; profileval_t *vals = profile_get_values(NULL); if (vals) { for (int profile = 0 ; vals[profile].pv_key != NULL ; profile++) { QStringList split_key = QString (vals[profile].pv_key).split ('.'); if (split_key.size() == 3) { if (split_key[0] != "clock" && split_key[1] == "alert" && split_key[2] == "tone") keys.push_back (vals[profile].pv_key); } } profile_free_values (vals); } QVector<QString> toneKeys (0); toneKeys << "ringing.alert.tone" << "voip.alert.tone" << "email.alert.tone" << "sms.alert.tone" << "im.alert.tone" << "calendar.alert.tone"; for (int i = 0 ; i < toneKeys.size() ; i++) { if (keys.contains (toneKeys.at (i))) { keys.removeOne (toneKeys.at (i)); v << new AlertTone (QString (toneKeys.at (i)) + "@general"); } } #else // do not WANT_PROFILED_CHECKS QVector<QString> toneKeys (0); toneKeys << "ringing.alert.tone@general" << "voip.alert.tone@general" << "email.alert.tone@general" << "sms.alert.tone@general" << "im.alert.tone@general" << "calendar.alert.tone@general"; for (int i = 0; i < toneKeys.size (); i++) { v << new AlertTone (toneKeys.at (i)); } #endif #endif // HAVE_LIBPROFILE return v; }
static krb5_error_code locate_srv_conf_1(krb5_context context, const krb5_data *realm, const char * name, struct serverlist *serverlist, k5_transport transport, int udpport) { const char *realm_srv_names[4]; char **hostlist = NULL, *realmstr = NULL, *host = NULL; const char *hostspec; krb5_error_code code; int i, default_port; Tprintf("looking in krb5.conf for realm %s entry %s; ports %d,%d\n", realm->data, name, udpport); realmstr = k5memdup0(realm->data, realm->length, &code); if (realmstr == NULL) goto cleanup; realm_srv_names[0] = KRB5_CONF_REALMS; realm_srv_names[1] = realmstr; realm_srv_names[2] = name; realm_srv_names[3] = 0; code = profile_get_values(context->profile, realm_srv_names, &hostlist); if (code) { Tprintf("config file lookup failed: %s\n", error_message(code)); if (code == PROF_NO_SECTION || code == PROF_NO_RELATION) code = 0; goto cleanup; } for (i = 0; hostlist[i]; i++) { int port_num; k5_transport this_transport = transport; const char *uri_path = NULL; hostspec = hostlist[i]; Tprintf("entry %d is '%s'\n", i, hostspec); parse_uri_if_https(hostspec, &this_transport, &hostspec, &uri_path); default_port = (this_transport == HTTPS) ? 443 : udpport; code = k5_parse_host_string(hostspec, default_port, &host, &port_num); if (code == 0 && host == NULL) code = EINVAL; if (code) goto cleanup; code = add_host_to_list(serverlist, host, port_num, this_transport, AF_UNSPEC, uri_path, -1); if (code) goto cleanup; free(host); host = NULL; } cleanup: free(realmstr); free(host); profile_free_list(hostlist); return code; }