static void cockpit_creds_free (gpointer data) { CockpitCreds *creds = data; cockpit_creds_poison (creds); g_list_free_full (creds->bytes, (GDestroyNotify)g_bytes_unref); g_free (creds->user); g_free (creds->application); g_free (creds->rhost); g_free (creds->gssapi_creds); g_free (creds->csrf_token); if (creds->krb5_ctx) { if (creds->krb5_ccache) krb5_cc_destroy (creds->krb5_ctx, creds->krb5_ccache); if (creds->krb5_ccache_name) krb5_free_string (creds->krb5_ctx, creds->krb5_ccache_name); krb5_free_context (creds->krb5_ctx); } if (creds->login_data) json_object_unref (creds->login_data); g_free (creds); }
static int list_ccache(krb5_ccache cache) { krb5_error_code ret; krb5_principal princ = NULL; char *princname = NULL, *ccname = NULL; int expired, status = 1; ret = krb5_cc_get_principal(context, cache, &princ); if (ret) /* Uninitialized cache file, probably. */ goto cleanup; ret = krb5_unparse_name(context, princ, &princname); if (ret) goto cleanup; ret = krb5_cc_get_full_name(context, cache, &ccname); if (ret) goto cleanup; expired = check_ccache(cache); printf("%-30.30s %s", princname, ccname); if (expired) printf(" %s", _("(Expired)")); printf("\n"); status = 0; cleanup: krb5_free_principal(context, princ); krb5_free_unparsed_name(context, princname); krb5_free_string(context, ccname); return status; }
/* Construct a host-based principal, similar to krb5_sname_to_principal() but * with a specified realm. */ krb5_error_code sn2princ_realm(krb5_context context, const char *hostname, const char *sname, const char *realm, krb5_principal *princ_out) { krb5_error_code ret; char *canonhost, localname[MAXHOSTNAMELEN]; *princ_out = NULL; assert(sname != NULL && realm != NULL); /* If hostname is NULL, use the local hostname. */ if (hostname == NULL) { if (gethostname(localname, MAXHOSTNAMELEN) != 0) return SOCKET_ERRNO; hostname = localname; } ret = krb5_expand_hostname(context, hostname, &canonhost); if (ret) return ret; ret = krb5_build_principal(context, princ_out, strlen(realm), realm, sname, canonhost, (char *)NULL); krb5_free_string(context, canonhost); if (!ret) (*princ_out)->type = KRB5_NT_SRV_HST; return ret; }
/* * Function: add_admin_princs * * Purpose: create admin principals * * Arguments: * * rseed (input) random seed * realm (input) realm, or NULL for default realm * <return value> (output) status, 0 for success, 1 for serious error * * Requires: * * Effects: * * add_admin_princs creates KADM5_ADMIN_SERVICE, * KADM5_CHANGEPW_SERVICE. If any of these exist a message is * printed. If any of these existing principal do not have the proper * attributes, a warning message is printed. */ static int add_admin_princs(void *handle, krb5_context context, char *realm) { krb5_error_code ret = 0; char *service_name = 0, *kiprop_name = 0, *canonhost = 0; char localname[MAXHOSTNAMELEN]; if (gethostname(localname, MAXHOSTNAMELEN)) { ret = errno; perror("gethostname"); goto clean_and_exit; } ret = krb5_expand_hostname(context, localname, &canonhost); if (ret) { com_err(progname, ret, _("while canonicalizing local hostname")); goto clean_and_exit; } if (asprintf(&service_name, "kadmin/%s", canonhost) < 0) { ret = ENOMEM; fprintf(stderr, _("Out of memory\n")); goto clean_and_exit; } if (asprintf(&kiprop_name, "kiprop/%s", canonhost) < 0) { ret = ENOMEM; fprintf(stderr, _("Out of memory\n")); goto clean_and_exit; } if ((ret = add_admin_princ(handle, context, service_name, realm, KRB5_KDB_DISALLOW_TGT_BASED | KRB5_KDB_LOCKDOWN_KEYS, ADMIN_LIFETIME))) goto clean_and_exit; if ((ret = add_admin_princ(handle, context, KADM5_ADMIN_SERVICE, realm, KRB5_KDB_DISALLOW_TGT_BASED | KRB5_KDB_LOCKDOWN_KEYS, ADMIN_LIFETIME))) goto clean_and_exit; if ((ret = add_admin_princ(handle, context, KADM5_CHANGEPW_SERVICE, realm, KRB5_KDB_DISALLOW_TGT_BASED | KRB5_KDB_PWCHANGE_SERVICE | KRB5_KDB_LOCKDOWN_KEYS, CHANGEPW_LIFETIME))) goto clean_and_exit; ret = add_admin_princ(handle, context, kiprop_name, realm, 0, 0); clean_and_exit: krb5_free_string(context, canonhost); free(service_name); free(kiprop_name); return ret; }
char * sss_get_ccache_name_for_principal(TALLOC_CTX *mem_ctx, krb5_context ctx, krb5_principal principal, const char *location) { #ifdef HAVE_KRB5_CC_COLLECTION krb5_error_code kerr; krb5_ccache tmp_cc = NULL; char *tmp_ccname = NULL; char *ret_ccname = NULL; DEBUG(SSSDBG_TRACE_ALL, "Location: [%s]\n", location); kerr = krb5_cc_set_default_name(ctx, location); if (kerr != 0) { KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr); return NULL; } kerr = krb5_cc_cache_match(ctx, principal, &tmp_cc); if (kerr != 0) { const char *err_msg = sss_krb5_get_error_message(ctx, kerr); DEBUG(SSSDBG_TRACE_INTERNAL, "krb5_cc_cache_match failed: [%d][%s]\n", kerr, err_msg); sss_krb5_free_error_message(ctx, err_msg); return NULL; } kerr = krb5_cc_get_full_name(ctx, tmp_cc, &tmp_ccname); if (kerr != 0) { KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr); goto done; } DEBUG(SSSDBG_TRACE_ALL, "tmp_ccname: [%s]\n", tmp_ccname); ret_ccname = talloc_strdup(mem_ctx, tmp_ccname); if (ret_ccname == NULL) { DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed (ENOMEM).\n"); } done: if (tmp_cc != NULL) { kerr = krb5_cc_close(ctx, tmp_cc); if (kerr != 0) { KRB5_DEBUG(SSSDBG_MINOR_FAILURE, ctx, kerr); } } krb5_free_string(ctx, tmp_ccname); return ret_ccname; #else return NULL; #endif /* HAVE_KRB5_CC_COLLECTION */ }
/* Release the memory for a list of credential cache names. */ static void free_list(char **list, size_t count) { size_t i; for (i = 0; i < count; i++) krb5_free_string(ctx, list[i]); free(list); }
/* Check that the name of cache matches expected_name. */ static void check_name(krb5_ccache cache, const char *expected_name) { char *name; check(krb5_cc_get_full_name(ctx, cache, &name)); assert(strcmp(name, expected_name) == 0); krb5_free_string(ctx, name); }
/* * Free an error string if necessary. If we returned a static string, make * sure we don't free it. * * This code assumes that the set of implementations that have * krb5_free_error_message is a subset of those with krb5_get_error_message. * If this assumption ever breaks, we may call the wrong free function. */ void krb5_free_error_message(krb5_context ctx UNUSED, const char *msg) { if (msg == error_unknown) return; # if defined(HAVE_KRB5_GET_ERROR_STRING) krb5_free_error_string(ctx, (char *) msg); # elif defined(HAVE_KRB5_SVC_GET_MSG) krb5_free_string(ctx, (char *) msg); # endif }
int main(int argc, char **argv) { krb5_error_code ret; krb5_context ctx; krb5_cccol_cursor cursor; krb5_ccache cache, hold[64]; int i; char *name; assert(krb5_init_context(&ctx) == 0); if (argc > 1) assert(krb5_cc_set_default_name(ctx, argv[1]) == 0); if (argc > 2) { assert(argc < 60); for (i = 2; i < argc; i++) { if (strcmp(argv[i], "CONTENT") == 0) { ret = krb5_cccol_have_content(ctx); krb5_free_context(ctx); return ret != 0; } assert(krb5_cc_resolve(ctx, argv[i], &hold[i - 2]) == 0); } } assert(krb5_cccol_cursor_new(ctx, &cursor) == 0); while (1) { assert(krb5_cccol_cursor_next(ctx, cursor, &cache) == 0); if (cache == NULL) break; assert(krb5_cc_get_full_name(ctx, cache, &name) == 0); printf("%s\n", name); krb5_free_string(ctx, name); krb5_cc_close(ctx, cache); } assert(krb5_cccol_cursor_free(ctx, &cursor) == 0); for (i = 2; i < argc; i++) krb5_cc_close(ctx, hold[i - 2]); krb5_free_context(ctx); return 0; }
/* * Load a string option from Kerberos appdefaults. Takes the Kerberos * context, the option, and the result location. * * This requires an annoying workaround because one cannot specify a default * value of NULL with MIT Kerberos, since MIT Kerberos unconditionally calls * strdup on the default value. There's also no way to determine if memory * allocation failed while parsing or while setting the default value, so we * don't return an error code. */ void sync_config_string(krb5_context ctx, const char *opt, char **result) { realm_type realm; char *value = NULL; /* Obtain the string from [appdefaults]. */ realm = default_realm(ctx); krb5_appdefault_string(ctx, "krb5-sync", realm, opt, "", &value); free_default_realm(ctx, realm); /* If we got something back, store it in result. */ if (value != NULL) { if (value[0] != '\0') { free(*result); *result = strdup(value); } krb5_free_string(ctx, value); } }
/* * Load a list option from Kerberos appdefaults. Takes the Kerberos context, * the option, and the result location. The option is read as a string and * the split on spaces and tabs into a list. * * This requires an annoying workaround because one cannot specify a default * value of NULL with MIT Kerberos, since MIT Kerberos unconditionally calls * strdup on the default value. There's also no way to determine if memory * allocation failed while parsing or while setting the default value. */ krb5_error_code sync_config_list(krb5_context ctx, const char *opt, struct vector **result) { realm_type realm; char *value = NULL; /* Obtain the string from [appdefaults]. */ realm = default_realm(ctx); krb5_appdefault_string(ctx, "krb5-sync", realm, opt, "", &value); free_default_realm(ctx, realm); /* If we got something back, store it in result. */ if (value != NULL) { if (value[0] != '\0') { *result = sync_vector_split_multi(value, " \t", *result); if (*result == NULL) return sync_error_system(ctx, "cannot allocate memory"); } krb5_free_string(ctx, value); } return 0; }
int aklog_authenticate(char *userName, char *response, int *reenter, char **message) { char *reason, *pword, prompt[256]; struct passwd *pwd; int code, unixauthneeded, password_expires = -1; int status; krb5_context context; krb5_init_context(&context); *reenter = 0; *message = (char *)0; status = auth_to_cell(context, userName, NULL, NULL); if (status) { char *str = afs_error_message(status); *message = (char *)malloc(1024); #ifdef HAVE_KRB5_SVC_GET_MSG if (strncmp(str, "unknown", strlen("unknown")) == 0) { krb5_svc_get_msg(status,&str); sprintf(*message, "Unable to obtain AFS tokens: %s.\n", str); krb5_free_string(context, str); } else #endif sprintf(*message, "Unable to obtain AFS tokens: %s.\n", str); return AUTH_FAILURE; /* NOTFOUND? */ } #if 0 /* * Local hack - if the person has a file in their home * directory called ".xlog", read that for a list of * extra cells to authenticate to */ if ((pwd = getpwuid(getuid())) != NULL) { struct stat sbuf; FILE *f; char fcell[100], xlog_path[512]; strcpy(xlog_path, pwd->pw_dir); strcat(xlog_path, "/.xlog"); if ((stat(xlog_path, &sbuf) == 0) && ((f = fopen(xlog_path, "r")) != NULL)) { while (fgets(fcell, 100, f) != NULL) { int auth_status; fcell[strlen(fcell) - 1] = '\0'; auth_status = auth_to_cell(context, userName, fcell, NULL); if (status == AKLOG_SUCCESS) status = auth_status; else status = AKLOG_SOMETHINGSWRONG; } } } #endif return AUTH_SUCCESS; }
int main(int argc, char **argv) { krb5_ccache ccinitial, ccu1, ccu2; krb5_principal princ1, princ2, princ3; const char *collection_name, *typename; char *initial_primary_name, *unique1_name, *unique2_name; /* * Get the collection name from the command line. This is a ccache name * with collection semantics, like DIR:/path/to/directory. This test * program assumes that the collection is empty to start with. */ assert(argc == 2); collection_name = argv[1]; /* * Set the default ccache for the context to be the collection name, so the * library can find the collection. */ check(krb5_init_context(&ctx)); check(krb5_cc_set_default_name(ctx, collection_name)); /* * Resolve the collection name. Since the collection is empty, this should * generate a subsidiary name of an uninitialized cache. Getting the name * of the resulting cache should give us the subsidiary name, not the * collection name. This resulting subsidiary name should be consistent if * we resolve the collection name again, and the collection should still be * empty since we haven't initialized the cache. */ check(krb5_cc_resolve(ctx, collection_name, &ccinitial)); check(krb5_cc_get_full_name(ctx, ccinitial, &initial_primary_name)); assert(strcmp(initial_primary_name, collection_name) != 0); check_primary_name(collection_name, initial_primary_name); check_collection(NULL, 0); check_princ(collection_name, NULL); check_princ(initial_primary_name, NULL); /* * Before initializing the primary ccache, generate and initialize two * unique caches of the collection's type. Check that the cache names * resolve to the generated caches and appear in the collection. (They * might appear before being initialized; that's not currently considered * important). The primary cache for the collection should remain as the * unitialized cache from the previous step. */ typename = krb5_cc_get_type(ctx, ccinitial); check(krb5_cc_new_unique(ctx, typename, NULL, &ccu1)); check(krb5_cc_get_full_name(ctx, ccu1, &unique1_name)); check(krb5_parse_name(ctx, "princ1@X", &princ1)); check(krb5_cc_initialize(ctx, ccu1, princ1)); check_princ(unique1_name, princ1); check_match(princ1, unique1_name); check_collection(NULL, 1, unique1_name); check(krb5_cc_new_unique(ctx, typename, NULL, &ccu2)); check(krb5_cc_get_full_name(ctx, ccu2, &unique2_name)); check(krb5_parse_name(ctx, "princ2@X", &princ2)); check(krb5_cc_initialize(ctx, ccu2, princ2)); check_princ(unique2_name, princ2); check_match(princ1, unique1_name); check_match(princ2, unique2_name); check_collection(NULL, 2, unique1_name, unique2_name); assert(strcmp(unique1_name, initial_primary_name) != 0); assert(strcmp(unique1_name, collection_name) != 0); assert(strcmp(unique2_name, initial_primary_name) != 0); assert(strcmp(unique2_name, collection_name) != 0); assert(strcmp(unique2_name, unique1_name) != 0); check_primary_name(collection_name, initial_primary_name); /* * Initialize the initial primary cache. Make sure it didn't change names, * that the previously retrieved name and the collection name both resolve * to the initialized cache, and that it now appears first in the * collection. */ check(krb5_parse_name(ctx, "princ3@X", &princ3)); check(krb5_cc_initialize(ctx, ccinitial, princ3)); check_name(ccinitial, initial_primary_name); check_princ(initial_primary_name, princ3); check_princ(collection_name, princ3); check_match(princ3, initial_primary_name); check_collection(initial_primary_name, 2, unique1_name, unique2_name); /* * Switch the primary cache to each cache we have open. One each switch, * check the primary name, check that the collection resolves to the * expected cache, and check that the new primary name appears first in the * collection. */ check(krb5_cc_switch(ctx, ccu1)); check_primary_name(collection_name, unique1_name); check_princ(collection_name, princ1); check_collection(unique1_name, 2, initial_primary_name, unique2_name); check(krb5_cc_switch(ctx, ccu2)); check_primary_name(collection_name, unique2_name); check_princ(collection_name, princ2); check_collection(unique2_name, 2, initial_primary_name, unique1_name); check(krb5_cc_switch(ctx, ccinitial)); check_primary_name(collection_name, initial_primary_name); check_princ(collection_name, princ3); check_collection(initial_primary_name, 2, unique1_name, unique2_name); /* * Temporarily set the context default ccache to a subsidiary name, and * check that iterating over the collection yields that subsidiary cache * and no others. */ check(krb5_cc_set_default_name(ctx, unique1_name)); check_collection(unique1_name, 0); check(krb5_cc_set_default_name(ctx, collection_name)); /* * Destroy the primary cache. Make sure this causes both the initial * primary name and the collection name to resolve to an uninitialized * cache. Make sure the primary name doesn't change and doesn't appear in * the collection any more. */ check(krb5_cc_destroy(ctx, ccinitial)); check_princ(initial_primary_name, NULL); check_princ(collection_name, NULL); check_primary_name(collection_name, initial_primary_name); check_match(princ1, unique1_name); check_match(princ2, unique2_name); check_match(princ3, NULL); check_collection(NULL, 2, unique1_name, unique2_name); /* * Switch to the first unique cache after destroying the primary cache. * Check that the collection name resolves to this cache and that the new * primary name appears first in the collection. */ check(krb5_cc_switch(ctx, ccu1)); check_primary_name(collection_name, unique1_name); check_princ(collection_name, princ1); check_collection(unique1_name, 1, unique2_name); /* * Destroy the second unique cache (which is not the current primary), * check that it is on longer initialized, and check that it no longer * appears in the collection. Check that destroying the non-primary cache * doesn't affect the primary name. */ check(krb5_cc_destroy(ctx, ccu2)); check_princ(unique2_name, NULL); check_match(princ2, NULL); check_collection(unique1_name, 0); check_primary_name(collection_name, unique1_name); check_match(princ1, unique1_name); check_princ(collection_name, princ1); /* * Destroy the first unique cache. Check that the collection is empty and * still has the same primary name. */ check(krb5_cc_destroy(ctx, ccu1)); check_princ(unique1_name, NULL); check_princ(collection_name, NULL); check_primary_name(collection_name, unique1_name); check_match(princ1, NULL); check_collection(NULL, 0); krb5_free_string(ctx, initial_primary_name); krb5_free_string(ctx, unique1_name); krb5_free_string(ctx, unique2_name); krb5_free_principal(ctx, princ1); krb5_free_principal(ctx, princ2); krb5_free_principal(ctx, princ3); krb5_free_context(ctx); return 0; }