Example #1
0
File: klist.c Project: INNOAUS/krb5
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;
}
Example #2
0
File: sss_krb5.c Project: 3van/sssd
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 */
}
Example #3
0
/* 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);
}
Example #4
0
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds_opt_set_fast_ccache(krb5_context context,
                                        krb5_get_init_creds_opt *opt,
                                        krb5_ccache ccache)
{
    krb5_error_code ret;
    char *name;

    ret = krb5_cc_get_full_name(context, ccache, &name);
    if (ret)
        return ret;
    ret = krb5_get_init_creds_opt_set_fast_ccache_name(context, opt, name);
    free(name);
    return ret;
}
Example #5
0
OM_uint32 GSSAPI_CALLCONV _gsskrb5_inquire_cred_by_oid
	   (OM_uint32 * minor_status,
	    const gss_cred_id_t cred_handle,
	    const gss_OID desired_object,
	    gss_buffer_set_t *data_set)
{
    krb5_context context;
    gsskrb5_cred cred = (gsskrb5_cred)cred_handle;
    krb5_error_code ret;
    gss_buffer_desc buffer;
    char *str;

    GSSAPI_KRB5_INIT (&context);

    if (gss_oid_equal(desired_object, GSS_KRB5_COPY_CCACHE_X) == 0) {
	*minor_status = EINVAL;
	return GSS_S_FAILURE;
    }

    HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);

    if (cred->ccache == NULL) {
	HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
	*minor_status = EINVAL;
	return GSS_S_FAILURE;
    }

    ret = krb5_cc_get_full_name(context, cred->ccache, &str);
    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
    if (ret) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }

    buffer.value = str;
    buffer.length = strlen(str);

    ret = gss_add_buffer_set_member(minor_status, &buffer, data_set);
    if (ret != GSS_S_COMPLETE)
	_gsskrb5_clear_status ();

    free(str);

    *minor_status = 0;
    return GSS_S_COMPLETE;
}
Example #6
0
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;
}
Example #7
0
/* Construct a list of the names of each credential cache in the collection. */
static void
get_collection_names(char ***list_out, size_t *count_out)
{
    krb5_cccol_cursor cursor;
    krb5_ccache cache;
    char **list = NULL;
    size_t count = 0;
    char *name;

    check(krb5_cccol_cursor_new(ctx, &cursor));
    while (1) {
        check(krb5_cccol_cursor_next(ctx, cursor, &cache));
        if (cache == NULL)
            break;
        check(krb5_cc_get_full_name(ctx, cache, &name));
        krb5_cc_close(ctx, cache);
        list = realloc(list, (count + 1) * sizeof(*list));
        assert(list != NULL);
        list[count++] = name;
    }
    krb5_cccol_cursor_free(ctx, &cursor);
    *list_out = list;
    *count_out = count;
}
Example #8
0
OM_uint32
_gsskrb5_krb5_import_cred(OM_uint32 *minor_status,
			  krb5_ccache id,
			  krb5_principal keytab_principal,
			  krb5_keytab keytab,
			  gss_cred_id_t *cred)
{
    krb5_context context;
    krb5_error_code kret;
    gsskrb5_cred handle;
    OM_uint32 ret;

    *cred = NULL;

    GSSAPI_KRB5_INIT (&context);

    handle = calloc(1, sizeof(*handle));
    if (handle == NULL) {
	_gsskrb5_clear_status ();
	*minor_status = ENOMEM;
        return (GSS_S_FAILURE);
    }
    HEIMDAL_MUTEX_init(&handle->cred_id_mutex);

    handle->usage = 0;

    if (id) {
	char *str;

	handle->usage |= GSS_C_INITIATE;

	kret = krb5_cc_get_principal(context, id,
				     &handle->principal);
	if (kret) {
	    free(handle);
	    *minor_status = kret;
	    return GSS_S_FAILURE;
	}

	if (keytab_principal) {
	    krb5_boolean match;

	    match = krb5_principal_compare(context,
					   handle->principal,
					   keytab_principal);
	    if (match == FALSE) {
		krb5_free_principal(context, handle->principal);
		free(handle);
		_gsskrb5_clear_status ();
		*minor_status = EINVAL;
		return GSS_S_FAILURE;
	    }
	}

	ret = __gsskrb5_ccache_lifetime(minor_status,
					context,
					id,
					handle->principal,
					&handle->lifetime);
	if (ret != GSS_S_COMPLETE) {
	    krb5_free_principal(context, handle->principal);
	    free(handle);
	    return ret;
	}


	kret = krb5_cc_get_full_name(context, id, &str);
	if (kret)
	    goto out;

	kret = krb5_cc_resolve(context, str, &handle->ccache);
	free(str);
	if (kret)
	    goto out;
    }


    if (keytab) {
	char *str;

	handle->usage |= GSS_C_ACCEPT;

	if (keytab_principal && handle->principal == NULL) {
	    kret = krb5_copy_principal(context,
				       keytab_principal,
				       &handle->principal);
	    if (kret)
		goto out;
	}

	kret = krb5_kt_get_full_name(context, keytab, &str);
	if (kret)
	    goto out;

	kret = krb5_kt_resolve(context, str, &handle->keytab);
	free(str);
	if (kret)
	    goto out;
    }


    if (id || keytab) {
	ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
	if (ret == GSS_S_COMPLETE)
	    ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
					 &handle->mechanisms);
	if (ret != GSS_S_COMPLETE) {
	    kret = *minor_status;
	    goto out;
	}
    }

    *minor_status = 0;
    *cred = (gss_cred_id_t)handle;
    return GSS_S_COMPLETE;

out:
    gss_release_oid_set(minor_status, &handle->mechanisms);
    if (handle->ccache)
	krb5_cc_close(context, handle->ccache);
    if (handle->keytab)
	krb5_kt_close(context, handle->keytab);
    if (handle->principal)
	krb5_free_principal(context, handle->principal);
    HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
    free(handle);
    *minor_status = kret;
    return GSS_S_FAILURE;
}
Example #9
0
static int
list_caches(krb5_context context)
{
    krb5_cc_cache_cursor cursor;
    const char *cdef_name;
    char *def_name;
    krb5_error_code ret;
    krb5_ccache id;
    rtbl_t ct;

    cdef_name = krb5_cc_default_name(context);
    if (cdef_name == NULL)
	krb5_errx(context, 1, "krb5_cc_default_name");
    def_name = strdup(cdef_name);

    ret = krb5_cc_cache_get_first (context, NULL, &cursor);
    if (ret == KRB5_CC_NOSUPP)
	return 0;
    else if (ret)
	krb5_err (context, 1, ret, "krb5_cc_cache_get_first");

    ct = rtbl_create();
    rtbl_add_column(ct, COL_NAME, 0);
    rtbl_add_column(ct, COL_CACHENAME, 0);
    rtbl_add_column(ct, COL_EXPIRES, 0);
    rtbl_add_column(ct, COL_DEFCACHE, 0);
    rtbl_set_prefix(ct, "   ");
    rtbl_set_column_prefix(ct, COL_NAME, "");

    while (krb5_cc_cache_next (context, cursor, &id) == 0) {
	krb5_principal principal = NULL;
	int expired = 0;
	char *name;
	time_t t;

	ret = krb5_cc_get_principal(context, id, &principal);
	if (ret)
	    continue;

	expired = check_for_tgt (context, id, principal, &t);

	ret = krb5_cc_get_friendly_name(context, id, &name);
	if (ret == 0) {
	    const char *str;
	    char *fname;
	    rtbl_add_column_entry(ct, COL_NAME, name);
	    rtbl_add_column_entry(ct, COL_CACHENAME,
				  krb5_cc_get_name(context, id));
	    if (expired)
		str = N_(">>> Expired <<<", "");
	    else
		str = printable_time(t);
	    rtbl_add_column_entry(ct, COL_EXPIRES, str);
	    free(name);

	    ret = krb5_cc_get_full_name(context, id, &fname);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_cc_get_full_name");

	    if (strcmp(fname, def_name) == 0)
		rtbl_add_column_entry(ct, COL_DEFCACHE, "*");
	    else
		rtbl_add_column_entry(ct, COL_DEFCACHE, "");

	    krb5_xfree(fname);
	}
	krb5_cc_close(context, id);

	krb5_free_principal(context, principal);
    }

    krb5_cc_cache_end_seq_get(context, cursor);

    free(def_name);
    rtbl_format(ct, stdout);
    rtbl_destroy(ct);

    return 0;
}
Example #10
0
OM_uint32
gss_krb5_import_cred(OM_uint32 *minor_status,
		     krb5_ccache id,
		     krb5_principal keytab_principal,
		     krb5_keytab keytab,
		     gss_cred_id_t *cred)
{
    gss_buffer_desc buffer;
    OM_uint32 major_status;
    krb5_context context;
    krb5_error_code ret;
    krb5_storage *sp;
    krb5_data data;
    char *str;

    *cred = GSS_C_NO_CREDENTIAL;

    ret = krb5_init_context(&context);
    if (ret) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }

    sp = krb5_storage_emem();
    if (sp == NULL) {
	*minor_status = ENOMEM;
	major_status = GSS_S_FAILURE;
	goto out;
    }

    if (id) {
	ret = krb5_cc_get_full_name(context, id, &str);
	if (ret == 0) {
	    ret = krb5_store_string(sp, str);
	    free(str);
	}
    } else
	ret = krb5_store_string(sp, "");
    if (ret) {
	*minor_status = ret;
	major_status = GSS_S_FAILURE;
	goto out;
    }

    if (keytab_principal) {
	ret = krb5_unparse_name(context, keytab_principal, &str);
	if (ret == 0) {
	    ret = krb5_store_string(sp, str);
	    free(str);
	}
    } else
	krb5_store_string(sp, "");
    if (ret) {
	*minor_status = ret;
	major_status = GSS_S_FAILURE;
	goto out;
    }


    if (keytab) {
	ret = krb5_kt_get_full_name(context, keytab, &str);
	if (ret == 0) {
	    ret = krb5_store_string(sp, str);
	    free(str);
	}
    } else
	krb5_store_string(sp, "");
    if (ret) {
	*minor_status = ret;
	major_status = GSS_S_FAILURE;
	goto out;
    }

    ret = krb5_storage_to_data(sp, &data);
    if (ret) {
	*minor_status = ret;
	major_status = GSS_S_FAILURE;
	goto out;
    }

    buffer.value = data.data;
    buffer.length = data.length;
    
    major_status = gss_set_cred_option(minor_status,
				       cred,
				       GSS_KRB5_IMPORT_CRED_X,
				       &buffer);
    krb5_data_free(&data);
out:
    if (sp)
	krb5_storage_free(sp);
    krb5_free_context(context);
    return major_status;
}
Example #11
0
static int
list_caches(krb5_context context, struct klist_options *opt)
{
    krb5_cccol_cursor cursor;
    const char *cdef_name;
    char *def_name;
    krb5_error_code ret;
    krb5_ccache id;
    rtbl_t ct;

    cdef_name = krb5_cc_default_name(context);
    if (cdef_name == NULL)
	krb5_errx(context, 1, "krb5_cc_default_name");
    def_name = strdup(cdef_name);

    ret = krb5_cccol_cursor_new(context, &cursor);
    if (ret == KRB5_CC_NOSUPP)
	return 0;
    else if (ret)
	krb5_err (context, 1, ret, "krb5_cc_cache_get_first");

    ct = rtbl_create();
    rtbl_add_column(ct, COL_DEFCACHE, 0);
    rtbl_add_column(ct, COL_NAME, 0);
    rtbl_add_column(ct, COL_CACHENAME, 0);
    rtbl_add_column(ct, COL_EXPIRES, 0);
    rtbl_add_column(ct, COL_DEFCACHE, 0);
    rtbl_set_prefix(ct, "   ");
    rtbl_set_column_prefix(ct, COL_DEFCACHE, "");
    rtbl_set_column_prefix(ct, COL_NAME, " ");
    if (opt->json_flag)
	rtbl_set_flags(ct, RTBL_JSON);

    while (krb5_cccol_cursor_next(context, cursor, &id) == 0) {
	int expired = 0;
	char *name;
	time_t t;

	expired = check_expiration(context, id, &t);

	ret = krb5_cc_get_friendly_name(context, id, &name);
	if (ret == 0) {
	    const char *str;
	    char *fname;

	    rtbl_add_column_entry(ct, COL_NAME, name);
	    free(name);

	    if (expired)
		str = N_(">>> Expired <<<", "");
	    else
		str = printable_time(t);
	    rtbl_add_column_entry(ct, COL_EXPIRES, str);

	    ret = krb5_cc_get_full_name(context, id, &fname);
	    if (ret)
		krb5_err (context, 1, ret, "krb5_cc_get_full_name");

	    rtbl_add_column_entry(ct, COL_CACHENAME, fname);
	    if (opt->json_flag)
		;
	    else if (strcmp(fname, def_name) == 0)
		rtbl_add_column_entry(ct, COL_DEFCACHE, "*");
	    else
		rtbl_add_column_entry(ct, COL_DEFCACHE, "");

	    krb5_xfree(fname);
	}
	krb5_cc_close(context, id);
    }

    krb5_cccol_cursor_free(context, &cursor);

    free(def_name);
    rtbl_format(ct, stdout);
    rtbl_destroy(ct);

    if (opt->json_flag)
	printf("\n");

    return 0;
}
Example #12
0
static void
print_tickets (krb5_context context,
	       krb5_ccache ccache,
	       krb5_principal principal,
	       int do_verbose,
	       int do_flags,
	       int do_hidden,
	       int do_json)
{
    char *str, *name, *fullname;
    krb5_error_code ret;
    krb5_cc_cursor cursor;
    krb5_creds creds;
    krb5_deltat sec;

    rtbl_t ct = NULL;

    ret = krb5_unparse_name (context, principal, &str);
    if (ret)
	krb5_err (context, 1, ret, "krb5_unparse_name");

    ret = krb5_cc_get_full_name(context, ccache, &fullname);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_get_full_name");

    if (!do_json) {
	printf ("%17s: %s\n", N_("Credentials cache", ""), fullname);
	printf ("%17s: %s\n", N_("Principal", ""), str);
	
	ret = krb5_cc_get_friendly_name(context, ccache, &name);
	if (ret == 0) {
	    if (strcmp(name, str) != 0)
		printf ("%17s: %s\n", N_("Friendly name", ""), name);
	    free(name);
	}
	free (str);
	
	if(do_verbose) {
	    printf ("%17s: %d\n", N_("Cache version", ""),
		    krb5_cc_get_version(context, ccache));
	} else {
	    krb5_cc_set_flags(context, ccache, KRB5_TC_NOTICKET);
	}
	
	ret = krb5_cc_get_kdc_offset(context, ccache, &sec);
	
	if (ret == 0 && do_verbose && sec != 0) {
	    char buf[BUFSIZ];
	    int val;
	    int sig;
	    
	    val = (int)sec;
	    sig = 1;
	    if (val < 0) {
		sig = -1;
		val = -val;
	    }
	    
	    unparse_time (val, buf, sizeof(buf));

	    printf ("%17s: %s%s\n", N_("KDC time offset", ""),
		    sig == -1 ? "-" : "", buf);
	}
	printf("\n");
    } else {
	printf ("{ \"cache\" : \"%s\", \"principal\" : \"%s\", ", fullname, str);
    }

    ret = krb5_cc_start_seq_get (context, ccache, &cursor);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_start_seq_get");

    if(!do_verbose) {
	ct = rtbl_create();
	rtbl_add_column(ct, COL_ISSUED, 0);
	rtbl_add_column(ct, COL_EXPIRES, 0);
	if(do_flags)
	    rtbl_add_column(ct, COL_FLAGS, 0);
	rtbl_add_column(ct, COL_PRINCIPAL, 0);
	rtbl_set_separator(ct, "  ");
	if (do_json) {
	    rtbl_set_flags(ct, RTBL_JSON);
	    printf("\"tickets\" : ");
	}
    }
    if (do_verbose && do_json)
	printf("\"tickets\" : [");
    while ((ret = krb5_cc_next_cred (context,
				     ccache,
				     &cursor,
				     &creds)) == 0) {
	if (!do_hidden && krb5_is_config_principal(context, creds.server)) {
	    ;
	}else if(do_verbose){
	    print_cred_verbose(context, &creds, do_json);
	}else{
	    print_cred(context, &creds, ct, do_flags);
	}
	krb5_free_cred_contents (context, &creds);
    }
    if(ret != KRB5_CC_END)
	krb5_err(context, 1, ret, "krb5_cc_get_next");
    ret = krb5_cc_end_seq_get (context, ccache, &cursor);
    if (ret)
	krb5_err (context, 1, ret, "krb5_cc_end_seq_get");
    if(!do_verbose) {
	rtbl_format(ct, stdout);
	rtbl_destroy(ct);
    }
    if (do_json) {
	if (do_verbose)
	    printf("]");
	printf("}");
    }
}
OM_uint32 GSSAPI_CALLCONV
_gsskrb5_export_cred(OM_uint32 *minor_status,
		     gss_cred_id_t cred_handle,
		     gss_buffer_t cred_token)
{
    gsskrb5_cred handle = (gsskrb5_cred)cred_handle;
    krb5_context context;
    krb5_error_code ret;
    krb5_storage *sp;
    krb5_data data, mech;
    char *str;

    GSSAPI_KRB5_INIT (&context);

    if (handle->usage != GSS_C_INITIATE && handle->usage != GSS_C_BOTH) {
	*minor_status = GSS_KRB5_S_G_BAD_USAGE;
	return GSS_S_FAILURE;
    }

    sp = krb5_storage_emem();
    if (sp == NULL) {
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }

    /*
    type = krb5_cc_get_type(context, handle->ccache);
     *
     * XXX Always use reference keys since that makes it easier to
     * transport between processing in seprate authentication domain.
     *
     * We should encrypt credentials in KCM though using the kcm
     * session key.
     */
    if (1 /*strcmp(type, "MEMORY") == 0 */) {
	krb5_creds *creds;
	ret = krb5_store_uint32(sp, 0);
	if (ret) {
	    krb5_storage_free(sp);
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}

	ret = _krb5_get_krbtgt(context, handle->ccache,
			       handle->principal->realm,
			       &creds);
	if (ret) {
	    krb5_storage_free(sp);
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}

	ret = krb5_store_creds(sp, creds);
	krb5_free_creds(context, creds);
	if (ret) {
	    krb5_storage_free(sp);
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}

    } else {
	ret = krb5_store_uint32(sp, 1);
	if (ret) {
	    krb5_storage_free(sp);
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}

	ret = krb5_cc_get_full_name(context, handle->ccache, &str);
	if (ret) {
	    krb5_storage_free(sp);
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}

	ret = krb5_store_string(sp, str);
	free(str);
	if (ret) {
	    krb5_storage_free(sp);
	    *minor_status = ret;
	    return GSS_S_FAILURE;
	}
    }
    ret = krb5_storage_to_data(sp, &data);
    krb5_storage_free(sp);
    if (ret) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }
    sp = krb5_storage_emem();
    if (sp == NULL) {
	krb5_data_free(&data);
	*minor_status = ENOMEM;
	return GSS_S_FAILURE;
    }

    mech.data = GSS_KRB5_MECHANISM->elements;
    mech.length = GSS_KRB5_MECHANISM->length;

    ret = krb5_store_data(sp, mech);
    if (ret) {
	krb5_data_free(&data);
	krb5_storage_free(sp);
	*minor_status = ret;
	return GSS_S_FAILURE;
    }

    ret = krb5_store_data(sp, data);
    krb5_data_free(&data);
    if (ret) {
	krb5_storage_free(sp);
	*minor_status = ret;
	return GSS_S_FAILURE;
    }

    ret = krb5_storage_to_data(sp, &data);
    krb5_storage_free(sp);
    if (ret) {
	*minor_status = ret;
	return GSS_S_FAILURE;
    }

    cred_token->value = data.data;
    cred_token->length = data.length;

    return GSS_S_COMPLETE;
}
Example #14
0
static int
create_krb5_cred(krb5_context ctx, char *realm, char *user, char *password,
                 char *ktname, krb5_ccache *ccache, gss_cred_id_t *gsscred,
                 char **errmsg) {
    int rc = 0, len = 0;
    unsigned int minor_stat = 0, major_stat = 0;
    const char *errmsg_tmp = NULL;
    const char *cctype = NULL;
    char *cname = NULL;
    krb5_ccache defcc = NULL;
    krb5_creds creds;
    krb5_principal princ = NULL;
    krb5_keytab keytab = NULL;
    gss_key_value_element_desc elems[2];
    gss_key_value_set_desc store;
    gss_name_t sname = NULL;
    gss_buffer_desc pr_name;

    pr_name.value = NULL;
    pr_name.length = 0;

    store.count = 0;
    store.elements = elems;

    if (user == NULL || realm == NULL) return 1;
    len = strlen(realm);

    if (len == 0 || strlen(user) == 0) return 0;

    DEBUG("create_krb5_cred (ctx:%p, realm:%s, user:%s, password:%s, ktname: %s,"
        " ccache:%p, gsscred:%p)", ctx, realm, user, "****", ktname, ccache, gsscred);

    rc = krb5_cc_default(ctx, &defcc);
    if (rc != 0) goto end;

    cctype = krb5_cc_get_type(ctx, defcc);

    rc = krb5_cc_new_unique(ctx, cctype, NULL, ccache);
    if (rc != 0) goto end;

    rc = krb5_build_principal(ctx, &princ, len, realm, user, NULL);
    if (rc != 0) goto end;

    rc = krb5_cc_initialize(ctx, *ccache, princ);
    if (rc != 0) goto end;

    if (password != NULL && strlen(password) > 0) {
        rc = krb5_get_init_creds_password(ctx, &creds, princ, password,
                                          0, NULL, 0, NULL, NULL);
        if (rc != 0) goto end;

        rc = krb5_cc_store_cred(ctx, *ccache, &creds);
        if (rc != 0) goto end;

        rc = krb5_cc_get_full_name(ctx, *ccache, &cname);
        if (rc != 0) goto end;
        
        store.elements[store.count].key = "ccache";
        store.elements[store.count].value = cname;
        store.count++;
    }

    if (ktname != NULL && strlen(ktname) > 0) {
        rc = krb5_kt_resolve(ctx, ktname, &keytab);
        if (rc != 0) goto end;

        rc = krb5_get_init_creds_keytab(ctx, &creds, princ, keytab, 0, NULL, NULL);
        if (rc != 0) goto end;
        
        rc = krb5_cc_store_cred(ctx, *ccache, &creds);
        if (rc != 0) goto end;

        rc = krb5_cc_get_full_name(ctx, *ccache, &cname);
        if (rc != 0) goto end;

        store.elements[store.count].key = "client_keytab";
        store.elements[store.count].value = ktname;
        store.count++;

        store.elements[store.count].key = "ccache";
        store.elements[store.count].value = cname;
        store.count++;

        rc = krb5_unparse_name(ctx, princ, (char**)&pr_name.value);
        if (rc != 0) goto end;
        pr_name.length = strlen(pr_name.value);

        major_stat = gss_import_name(&minor_stat, &pr_name,
                                     GSS_KRB5_NT_PRINCIPAL_NAME, &sname);
        if (major_stat != 0) goto end;
    }

    // Does not work with GSS-SPENGO.
    //major_stat = gss_krb5_import_cred(&minor_stat, *ccache, princ, NULL, gsscred);
    major_stat = gss_acquire_cred_from(&minor_stat, sname, 0, GSS_C_NO_OID_SET,
                                       GSS_C_INITIATE, &store, gsscred,
                                       NULL, NULL);

end:
    if (keytab != NULL) krb5_kt_close(ctx, keytab);
    if (princ != NULL) krb5_free_principal(ctx, princ);
    if (defcc != NULL) krb5_cc_close(ctx, defcc);
    if (cname != NULL) free(cname);
    if (pr_name.value != NULL) krb5_free_unparsed_name(ctx, pr_name.value);
    if (sname != NULL) {
        major_stat = gss_release_name(&minor_stat, &sname);
    }

    if (rc != 0) {
        /* Create error message with the error code. */
        errmsg_tmp = krb5_get_error_message(ctx, rc);
        if (errmsg != NULL && errmsg_tmp != NULL) {
            len = strlen(errmsg_tmp) + 26;
            *errmsg = (char *)malloc(len);
            if (*errmsg == NULL) {
                krb5_free_error_message(ctx, errmsg_tmp);
                return -1;
            }
            snprintf(*errmsg, len,"%s. (KRB5_ERROR 0x%08x)", errmsg_tmp, rc);
        }
        krb5_free_error_message(ctx, errmsg_tmp);
    }
    if (major_stat != 0) return major_stat;
    return rc;
}
Example #15
0
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;
}