/*
 * Request:
 *      NameZ
 *      Creds
 *
 * Response:
 *
 */
static krb5_error_code
kcm_store_cred(krb5_context context,
	       krb5_ccache id,
	       krb5_creds *creds)
{
    krb5_error_code ret;
    krb5_kcmcache *k = KCMCACHE(id);
    krb5_storage *request;

    ret = krb5_kcm_storage_request(context, KCM_OP_STORE, &request);
    if (ret)
	return ret;

    ret = krb5_store_stringz(request, k->name);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_store_creds(request, creds);
    if (ret) {
	krb5_storage_free(request);
	return ret;
    }

    ret = krb5_kcm_call(context, request, NULL, NULL);

    krb5_storage_free(request);
    return ret;
}
Exemple #2
0
static krb5_error_code
encode_creds(krb5_context context, krb5_creds *creds, krb5_data *data)
{
    krb5_error_code ret;
    krb5_storage *sp;

    sp = krb5_storage_emem();
    if (sp == NULL) {
	krb5_set_error_message(context, ENOMEM,
			       N_("malloc: out of memory", ""));
	return ENOMEM;
    }

    ret = krb5_store_creds(sp, creds);
    if (ret) {
	krb5_set_error_message(context, ret,
			       N_("Failed to store credential in scache", ""));
	krb5_storage_free(sp);
	return ret;
    }

    ret = krb5_storage_to_data(sp, data);
    krb5_storage_free(sp);
    if (ret)
	krb5_set_error_message(context, ret,
			       N_("Failed to encode credential in scache", ""));
    return ret;
}
Exemple #3
0
static krb5_error_code
encode_creds(krb5_context context, krb5_creds *creds, krb5_data *data)
{
    krb5_error_code ret;
    krb5_storage *sp;

    krb5_data_zero(data);
    sp = krb5_storage_emem();
    if (sp == NULL)
	return krb5_enomem(context);

    ret = krb5_store_creds(sp, creds);
    if (ret) {
	krb5_set_error_message(context, ret,
			       N_("Failed to store credential in scache", ""));
	krb5_storage_free(sp);
	return ret;
    }

    ret = krb5_storage_to_data(sp, data);
    krb5_storage_free(sp);
    if (ret)
	krb5_set_error_message(context, ret,
			       N_("Failed to encode credential in scache", ""));
    return ret;
}
Exemple #4
0
/*
 * Request:
 *	NameZ
 *	Cursor
 *
 * Response:
 *	Creds
 */
static krb5_error_code
kcm_op_get_next(krb5_context context,
		kcm_client *client,
		kcm_operation opcode,
		krb5_storage *request,
		krb5_storage *response)
{
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;
    u_int32_t cursor;
    kcm_cursor *c;

    ret = krb5_ret_stringz(request, &name);
    if (ret)
	return ret;

    KCM_LOG_REQUEST_NAME(context, client, opcode, name);

    ret = krb5_ret_int32(request, &cursor);
    if (ret) {
	free(name);
	return ret;
    }

    ret = kcm_ccache_resolve_client(context, client, opcode,
				    name, &ccache);
    if (ret) {
	free(name);
	return ret;
    }

    ret = kcm_cursor_find(context, client->pid, ccache, cursor, &c);
    if (ret) {
	kcm_release_ccache(context, &ccache);
	free(name);
	return ret;
    }

    HEIMDAL_MUTEX_lock(&ccache->mutex);
    if (c->credp == NULL) {
	ret = KRB5_CC_END;
    } else {
	ret = krb5_store_creds(response, &c->credp->cred);
	c->credp = c->credp->next;
    }
    HEIMDAL_MUTEX_unlock(&ccache->mutex);

    free(name);
    kcm_release_ccache(context, &ccache);

    return ret;
}
Exemple #5
0
/*
 * Request:
 *	NameZ
 *	Cursor
 *
 * Response:
 *	Creds
 */
static krb5_error_code
kcm_op_get_cred_by_uuid(krb5_context context,
			kcm_client *client,
			kcm_operation opcode,
			krb5_storage *request,
			krb5_storage *response)
{
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;
    struct kcm_creds *c;
    kcmuuid_t uuid;
    ssize_t sret;

    ret = krb5_ret_stringz(request, &name);
    if (ret)
	return ret;

    KCM_LOG_REQUEST_NAME(context, client, opcode, name);

    ret = kcm_ccache_resolve_client(context, client, opcode,
				    name, &ccache);
    free(name);
    if (ret)
	return ret;

    sret = krb5_storage_read(request, &uuid, sizeof(uuid));
    if (sret != sizeof(uuid)) {
	kcm_release_ccache(context, ccache);
	krb5_clear_error_message(context);
	return KRB5_CC_IO;
    }

    c = kcm_ccache_find_cred_uuid(context, ccache, uuid);
    if (c == NULL) {
	kcm_release_ccache(context, ccache);
	return KRB5_CC_END;
    }

    HEIMDAL_MUTEX_lock(&ccache->mutex);
    ret = krb5_store_creds(response, &c->cred);
    HEIMDAL_MUTEX_unlock(&ccache->mutex);

    kcm_release_ccache(context, ccache);

    return ret;
}
Exemple #6
0
static krb5_error_code
fcc_store_cred(krb5_context context,
	       krb5_ccache id,
	       krb5_creds *creds)
{
    int ret;
    int fd;

    ret = fcc_open(context, id, &fd, O_WRONLY | O_APPEND | O_BINARY | O_CLOEXEC, 0);
    if(ret)
	return ret;
    {
	krb5_storage *sp;

	sp = krb5_storage_emem();
	krb5_storage_set_eof_code(sp, KRB5_CC_END);
	storage_set_flags(context, sp, FCACHE(id)->version);
	if (!krb5_config_get_bool_default(context, NULL, TRUE,
					  "libdefaults",
					  "fcc-mit-ticketflags",
					  NULL))
	    krb5_storage_set_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER);
	ret = krb5_store_creds(sp, creds);
	if (ret == 0)
	    ret = write_storage(context, sp, fd);
	krb5_storage_free(sp);
    }
    fcc_unlock(context, fd);
    if (close(fd) < 0) {
	if (ret == 0) {
	    ret = errno;
	    krb5_set_error_message (context, ret, N_("close %s: %s", ""),
				    FILENAME(id), strerror(ret));
	}
    }
    return ret;
}
Exemple #7
0
/*
 * Request:
 *	NameZ
 *	WhichFields
 *	MatchCreds
 *
 * Response:
 *	Creds
 *	
 */
static krb5_error_code
kcm_op_retrieve(krb5_context context,
		kcm_client *client,
		kcm_operation opcode,
		krb5_storage *request,
		krb5_storage *response)
{
    uint32_t flags;
    krb5_creds mcreds;
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;
    krb5_creds *credp;
    int free_creds = 0;

    ret = krb5_ret_stringz(request, &name);
    if (ret)
	return ret;

    KCM_LOG_REQUEST_NAME(context, client, opcode, name);

    ret = krb5_ret_uint32(request, &flags);
    if (ret) {
	free(name);
	return ret;
    }

    ret = krb5_ret_creds_tag(request, &mcreds);
    if (ret) {
	free(name);
	return ret;
    }

    if (disallow_getting_krbtgt &&
	mcreds.server->name.name_string.len == 2 &&
	strcmp(mcreds.server->name.name_string.val[0], KRB5_TGS_NAME) == 0)
    {
	free(name);
	krb5_free_cred_contents(context, &mcreds);
	return KRB5_FCC_PERM;
    }

    ret = kcm_ccache_resolve_client(context, client, opcode,
				    name, &ccache);
    if (ret) {
	free(name);
	krb5_free_cred_contents(context, &mcreds);
	return ret;
    }

    ret = kcm_ccache_retrieve_cred(context, ccache, flags,
				   &mcreds, &credp);
    if (ret && ((flags & KRB5_GC_CACHED) == 0) &&
	!krb5_is_config_principal(context, mcreds.server)) {
	krb5_ccache_data ccdata;

	/* try and acquire */
	HEIMDAL_MUTEX_lock(&ccache->mutex);

	/* Fake up an internal ccache */
	kcm_internal_ccache(context, ccache, &ccdata);

	/* glue cc layer will store creds */
	ret = krb5_get_credentials(context, 0, &ccdata, &mcreds, &credp);
	if (ret == 0)
	    free_creds = 1;

	HEIMDAL_MUTEX_unlock(&ccache->mutex);
    }

    if (ret == 0) {
	ret = krb5_store_creds(response, credp);
    }

    free(name);
    krb5_free_cred_contents(context, &mcreds);
    kcm_release_ccache(context, ccache);

    if (free_creds)
	krb5_free_cred_contents(context, credp);

    return ret;
}
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;
}
Exemple #9
0
static krb5_error_code KRB5_CALLCONV
xcc_store_cred(krb5_context context,
	       krb5_ccache id,
	       krb5_creds *creds)
{
    krb5_xcc *x = XCACHE(id);
    krb5_storage *sp = NULL;
    CFDataRef dref = NULL;
    krb5_data data;
    CFStringRef principal = NULL;
    CFDictionaryRef query = NULL;
    krb5_error_code ret;
    CFBooleanRef is_tgt = kCFBooleanFalse;
    CFDateRef authtime = NULL;
    
    krb5_data_zero(&data);
    
    if (creds->times.starttime) {
	authtime = CFDateCreate(NULL, (CFTimeInterval)creds->times.starttime - kCFAbsoluteTimeIntervalSince1970);
    } else if (creds->times.authtime) {
	authtime = CFDateCreate(NULL, (CFTimeInterval)creds->times.authtime - kCFAbsoluteTimeIntervalSince1970);
    } else {
	authtime = CFDateCreate(NULL, CFAbsoluteTimeGetCurrent());
    }
    if (authtime == NULL) {
	ret = krb5_enomem(context);
	goto out;
    }

    sp = krb5_storage_emem();
    if (sp == NULL) {
	ret = krb5_enomem(context);
	goto out;
    }
    
    ret = krb5_store_creds(sp, creds);
    if (ret)
	goto out;
    
    krb5_storage_to_data(sp, &data);
    
    dref = CFDataCreateWithBytesNoCopy(NULL, data.data, data.length, kCFAllocatorNull);
    if (dref == NULL) {
	ret = krb5_enomem(context);
	goto out;
    }
    
    if (krb5_principal_is_root_krbtgt(context, creds->server))
	is_tgt = kCFBooleanTrue;

    principal = CFStringCreateFromPrincipal(context, creds->server);
    if (principal == NULL) {
	ret = krb5_enomem(context);
	goto out;
    }
    
    const void *add_keys[] = {
	(void *)kHEIMObjectType,
	kHEIMAttrType,
	kHEIMAttrClientName,
	kHEIMAttrServerName,
	kHEIMAttrData,
	kHEIMAttrParentCredential,
	kHEIMAttrLeadCredential,
	kHEIMAttrAuthTime,
    };
    const void *add_values[] = {
	(void *)kHEIMObjectKerberos,
	kHEIMTypeKerberos,
	x->clientName,
	principal,
	dref,
	x->uuid,
	is_tgt,
	authtime,
    };
    
    query = CFDictionaryCreate(NULL, add_keys, add_values, sizeof(add_keys) / sizeof(add_keys[0]), NULL, NULL);
    heim_assert(query != NULL, "Failed to create dictionary");
    
    HeimCredRef ccred = HeimCredCreate(query, NULL);
    if (ccred) {
	CFRelease(ccred);
    } else {
	_krb5_debugx(context, 5, "failed to add credential to %s\n", x->cache_name);
	ret = EINVAL;
	krb5_set_error_message(context, ret, "failed to store credential to %s", x->cache_name);
	goto out;
    }
    
out:
    if (sp)
	krb5_storage_free(sp);
    CFRELEASE_NULL(query);
    CFRELEASE_NULL(dref);
    CFRELEASE_NULL(principal);
    CFRELEASE_NULL(authtime);
    krb5_data_free(&data);
    
    return ret;
}