Exemplo n.º 1
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;
}
Exemplo n.º 2
0
/*
 * Request:
 *	NameZ
 *
 * Response:
 *	Principal
 */
static krb5_error_code
kcm_op_get_principal(krb5_context context,
		     kcm_client *client,
		     kcm_operation opcode,
		     krb5_storage *request,
		     krb5_storage *response)
{
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;

    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);
    if (ret) {
	free(name);
	return ret;
    }

    if (ccache->client == NULL)
	ret = KRB5_CC_NOTFOUND;
    else
	ret = krb5_store_principal(response, ccache->client);

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

    return 0;
}
Exemplo n.º 3
0
static krb5_error_code
kcm_op_get_kdc_offset(krb5_context context,
		      kcm_client *client,
		      kcm_operation opcode,
		      krb5_storage *request,
		      krb5_storage *response)
{
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;

    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;

    HEIMDAL_MUTEX_lock(&ccache->mutex);
    ret = krb5_store_int32(response, ccache->kdc_offset);
    HEIMDAL_MUTEX_unlock(&ccache->mutex);

    kcm_release_ccache(context, ccache);

    return ret;
}
Exemplo n.º 4
0
static krb5_error_code
kcm_op_get_cache_by_uuid(krb5_context context,
			 kcm_client *client,
			 kcm_operation opcode,
			 krb5_storage *request,
			 krb5_storage *response)
{
    krb5_error_code ret;
    kcmuuid_t uuid;
    ssize_t sret;
    kcm_ccache cache;

    KCM_LOG_REQUEST(context, client, opcode);

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

    ret = kcm_ccache_resolve_by_uuid(context, uuid, &cache);
    if (ret)
	return ret;

    ret = kcm_access(context, client, opcode, cache);
    if (ret)
	ret = KRB5_FCC_NOFILE;

    if (ret == 0)
	ret = krb5_store_stringz(response, cache->name);

    kcm_release_ccache(context, cache);

    return ret;
}
Exemplo n.º 5
0
krb5_error_code
kcm_ccache_destroy_client(krb5_context context,
			  kcm_client *client,
			  const char *name)
{
    krb5_error_code ret;
    kcm_ccache ccache;
    const char *estr;

    ret = kcm_ccache_resolve(context, name, &ccache);
    if (ret) {
	estr = krb5_get_error_message(context, ret);
	kcm_log(1, "Failed to resolve cache %s: %s", name, estr);
	krb5_free_error_message(context, estr);
	return ret;
    }

    ret = kcm_access(context, client, KCM_OP_DESTROY, ccache);
    kcm_cleanup_events(context, ccache);
    kcm_release_ccache(context, ccache);
    if (ret)
	return ret;

    return kcm_ccache_destroy(context, name);
}
Exemplo n.º 6
0
krb5_error_code
kcm_ccache_resolve_client(krb5_context context,
			  kcm_client *client,
			  kcm_operation opcode,
			  const char *name,
			  kcm_ccache *ccache)
{
    krb5_error_code ret;
    const char *estr;

    ret = kcm_ccache_resolve(context, name, ccache);
    if (ret) {
	estr = krb5_get_error_message(context, ret);
	kcm_log(1, "Failed to resolve cache %s: %s", name, estr);
	krb5_free_error_message(context, estr);
	return ret;
    }

    ret = kcm_access(context, client, opcode, *ccache);
    if (ret) {
	ret = KRB5_FCC_NOFILE; /* don't disclose */
	kcm_release_ccache(context, *ccache);
    }

    return ret;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
/*
 * Request:
 *	NameZ
 *	Creds
 *	
 * Response:
 *	
 */
static krb5_error_code
kcm_op_store(krb5_context context,
	     kcm_client *client,
	     kcm_operation opcode,
	     krb5_storage *request,
	     krb5_storage *response)
{
    krb5_creds creds;
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;

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

    KCM_LOG_REQUEST_NAME(context, client, opcode, name);

    ret = krb5_ret_creds(request, &creds);
    if (ret) {
	free(name);
	return ret;
    }

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

    ret = kcm_ccache_store_cred(context, ccache, &creds, 0);
    if (ret) {
	free(name);
	krb5_free_cred_contents(context, &creds);
	kcm_release_ccache(context, ccache);
	return ret;
    }

    kcm_ccache_enqueue_default(context, ccache, &creds);

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

    return 0;
}
Exemplo n.º 9
0
/*
 * Request:
 *	NameZ
 *	Principal
 *	
 * Response:
 *	
 */
static krb5_error_code
kcm_op_initialize(krb5_context context,
		  kcm_client *client,
		  kcm_operation opcode,
		  krb5_storage *request,
		  krb5_storage *response)
{
    kcm_ccache ccache;
    krb5_principal principal;
    krb5_error_code ret;
    char *name;
#if 0
    kcm_event event;
#endif

    KCM_LOG_REQUEST(context, client, opcode);

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

    ret = krb5_ret_principal(request, &principal);
    if (ret) {
	free(name);
	return ret;
    }

    ret = kcm_ccache_new_client(context, client, name, &ccache);
    if (ret) {
	free(name);
	krb5_free_principal(context, principal);
	return ret;
    }

    ccache->client = principal;

    free(name);

#if 0
    /*
     * Create a new credentials cache. To mitigate DoS attacks we will
     * expire it in 30 minutes unless it has some credentials added
     * to it
     */

    event.fire_time = 30 * 60;
    event.expire_time = 0;
    event.backoff_time = 0;
    event.action = KCM_EVENT_DESTROY_EMPTY_CACHE;
    event.ccache = ccache;

    ret = kcm_enqueue_event_relative(context, &event);
#endif

    kcm_release_ccache(context, ccache);

    return ret;
}
Exemplo n.º 10
0
/*
 * Request:
 *	NameZ
 *
 * Response:
 *	Cursor
 *	
 */
static krb5_error_code
kcm_op_get_first(krb5_context context,
		 kcm_client *client,
		 kcm_operation opcode,
		 krb5_storage *request,
		 krb5_storage *response)
{
    krb5_error_code ret;
    kcm_ccache ccache;
    u_int32_t cursor;
    char *name;

    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);
    if (ret) {
	free(name);
	return ret;
    }

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

    ret = krb5_store_int32(response, cursor);

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

    return ret;
}
Exemplo n.º 11
0
/*
 * Request:
 *	NameZ
 *	WhichFields
 *	MatchCreds
 *
 * Response:
 *	
 */
static krb5_error_code
kcm_op_remove_cred(krb5_context context,
		   kcm_client *client,
		   kcm_operation opcode,
		   krb5_storage *request,
		   krb5_storage *response)
{
    uint32_t whichfields;
    krb5_creds mcreds;
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;

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

    KCM_LOG_REQUEST_NAME(context, client, opcode, name);

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

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

    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_remove_cred(context, ccache, whichfields, &mcreds);

    /* XXX need to remove any events that match */

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

    return ret;
}
Exemplo n.º 12
0
/*
 * Request:
 *	NameZ
 * Response:
 *	NameZ
 *
 */
static krb5_error_code
kcm_op_get_name(krb5_context context,
		kcm_client *client,
		kcm_operation opcode,
		krb5_storage *request,
		krb5_storage *response)

{
    krb5_error_code ret;
    char *name = NULL;
    kcm_ccache ccache;

    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);
    if (ret) {
	free(name);
	return ret;
    }

    ret = krb5_store_stringz(response, ccache->name);
    if (ret) {
	kcm_release_ccache(context, ccache);
	free(name);
	return ret;
    }

    free(name);
    kcm_release_ccache(context, ccache);
    return 0;
}
Exemplo n.º 13
0
/*
 * Request:
 *	NameZ
 *	UID
 *	GID
 *
 * Response:
 *	
 */
static krb5_error_code
kcm_op_chown(krb5_context context,
	     kcm_client *client,
	     kcm_operation opcode,
	     krb5_storage *request,
	     krb5_storage *response)
{
    uint32_t uid;
    uint32_t gid;
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;

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

    KCM_LOG_REQUEST_NAME(context, client, opcode, name);

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

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

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

    ret = kcm_chown(context, client, ccache, uid, gid);

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

    return ret;
}
Exemplo n.º 14
0
krb5_error_code
kcm_ccache_destroy_client(krb5_context context,
			  kcm_client *client,
			  const char *name)
{
    krb5_error_code ret;
    kcm_ccache ccache;

    ret = kcm_ccache_resolve_by_name(context, name, &ccache);
    if (ret) {
	kcm_log(1, "Failed to resolve cache %s", name);
	return ret;
    }

    ret = kcm_access(context, client, KCM_OP_DESTROY, ccache);
    kcm_release_ccache(context, ccache);
    if (ret)
	return ret;

    return kcm_ccache_destroy(context, name);
}
Exemplo n.º 15
0
static krb5_error_code
kcm_remove_event_internal(krb5_context context,
			  kcm_event **e)
{
    kcm_event *next;

    next = (*e)->next;

    (*e)->valid = 0;
    (*e)->fire_time = 0;
    (*e)->fire_count = 0;
    (*e)->expire_time = 0;
    (*e)->backoff_time = 0;
    kcm_release_ccache(context, &(*e)->ccache);
    (*e)->next = NULL;
    free(*e);

    *e = next;

    return 0;
}
Exemplo n.º 16
0
/*
 * Request:
 *	NameZ
 *	Mode
 *
 * Response:
 *	
 */
static krb5_error_code
kcm_op_chmod(krb5_context context,
	     kcm_client *client,
	     kcm_operation opcode,
	     krb5_storage *request,
	     krb5_storage *response)
{
    u_int16_t mode;
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;

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

    KCM_LOG_REQUEST_NAME(context, client, opcode, name);

    ret = krb5_ret_int16(request, &mode);
    if (ret) {
	free(name);
	return ret;
    }

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

    ret = kcm_chmod(context, client, ccache, mode);

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

    return ret;
}
Exemplo n.º 17
0
krb5_error_code
kcm_ccache_resolve_client(krb5_context context,
			  kcm_client *client,
			  kcm_operation opcode,
			  const char *name,
			  kcm_ccache *ccache)
{
    krb5_error_code ret;

    ret = kcm_ccache_resolve_by_name(context, name, ccache);
    if (ret) {
	kcm_log(1, "Failed to resolve cache %s", name);
	return ret;
    }

    ret = kcm_access(context, client, opcode, *ccache);
    if (ret) {
	ret = KRB5_FCC_NOFILE; /* don't disclose */
	kcm_release_ccache(context, *ccache);
    }

    return ret;
}
Exemplo n.º 18
0
/*
 * Request:
 *	NameZ
 *	Flags
 *
 * Response:
 *	
 */
static krb5_error_code
kcm_op_set_flags(krb5_context context,
		 kcm_client *client,
		 kcm_operation opcode,
		 krb5_storage *request,
		 krb5_storage *response)
{
    uint32_t flags;
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;

    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 = kcm_ccache_resolve_client(context, client, opcode,
				    name, &ccache);
    if (ret) {
	free(name);
	return ret;
    }

    /* we don't really support any flags yet */
    free(name);
    kcm_release_ccache(context, ccache);

    return 0;
}
Exemplo n.º 19
0
/*
 * Request:
 *	NameZ
 *
 * Response:
 *	UUIDs
 *	
 */
static krb5_error_code
kcm_op_get_cred_uuid_list(krb5_context context,
			  kcm_client *client,
			  kcm_operation opcode,
			  krb5_storage *request,
			  krb5_storage *response)
{
    struct kcm_creds *creds;
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;

    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;

    for (creds = ccache->creds ; creds ; creds = creds->next) {
	ssize_t sret;
	sret = krb5_storage_write(response, &creds->uuid, sizeof(creds->uuid));
	if (sret != sizeof(creds->uuid)) {
	    ret = ENOMEM;
	    break;
	}
    }

    kcm_release_ccache(context, ccache);

    return ret;
}
Exemplo n.º 20
0
krb5_error_code
kcm_ccache_new_client(krb5_context context,
		      kcm_client *client,
		      const char *name,
		      kcm_ccache *ccache_p)
{
    krb5_error_code ret;
    kcm_ccache ccache;

    /* We insist the ccache name starts with UID or UID: */
    if (name_constraints != 0) {
	char prefix[64];
	size_t prefix_len;
	int bad = 1;

	snprintf(prefix, sizeof(prefix), "%ld:", (long)client->uid);
	prefix_len = strlen(prefix);

	if (strncmp(name, prefix, prefix_len) == 0)
	    bad = 0;
	else {
	    prefix[prefix_len - 1] = '\0';
	    if (strcmp(name, prefix) == 0)
		bad = 0;
	}

	/* Allow root to create badly-named ccaches */
	if (bad && !CLIENT_IS_ROOT(client))
	    return KRB5_CC_BADNAME;
    }

    ret = kcm_ccache_resolve(context, name, &ccache);
    if (ret == 0) {
	if ((ccache->uid != client->uid ||
	     ccache->gid != client->gid) && !CLIENT_IS_ROOT(client))
	    return KRB5_FCC_PERM;
    } else if (ret != KRB5_FCC_NOFILE && !(CLIENT_IS_ROOT(client) && ret == KRB5_FCC_PERM)) {
		return ret;
    }

    if (ret == KRB5_FCC_NOFILE) {
	ret = kcm_ccache_new(context, name, &ccache);
	if (ret) {
	    kcm_log(1, "Failed to initialize cache %s: %s",
		    name, krb5_get_err_text(context, ret));
	    return ret;
	}

	/* bind to current client */
	ccache->uid = client->uid;
	ccache->gid = client->gid;
	ccache->session = client->session;
    } else {
	ret = kcm_zero_ccache_data(context, ccache);
	if (ret) {
	    kcm_log(1, "Failed to empty cache %s: %s",
		    name, krb5_get_err_text(context, ret));
	    kcm_release_ccache(context, ccache);
	    return ret;
	}
	kcm_cleanup_events(context, ccache);
    }

    ret = kcm_access(context, client, KCM_OP_INITIALIZE, ccache);
    if (ret) {
	kcm_release_ccache(context, ccache);
	kcm_ccache_destroy(context, name);
	return ret;
    }

    /*
     * Finally, if the user is root and the cache was created under
     * another user's name, chown the cache to that user and their
     * default gid.
     */
    if (CLIENT_IS_ROOT(client)) {
	unsigned long uid;
	int matches = sscanf(name,"%ld:",&uid);
	if (matches == 0)
	    matches = sscanf(name,"%ld",&uid);
	if (matches == 1) {
	    struct passwd *pwd = getpwuid(uid);
	    if (pwd != NULL) {
		gid_t gid = pwd->pw_gid;
		kcm_chown(context, client, ccache, uid, gid);
	    }
	}
    }

    *ccache_p = ccache;
    return 0;
}
Exemplo n.º 21
0
/*
 * Request:
 *	OldNameZ
 *	NewNameZ
 *
 * Repsonse:
 *
 */
static krb5_error_code
kcm_op_move_cache(krb5_context context,
		  kcm_client *client,
		  kcm_operation opcode,
		  krb5_storage *request,
		  krb5_storage *response)
{
    krb5_error_code ret;
    kcm_ccache oldid, newid;
    char *oldname, *newname;

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

    KCM_LOG_REQUEST_NAME(context, client, opcode, oldname);

    ret = krb5_ret_stringz(request, &newname);
    if (ret) {
	free(oldname);
	return ret;
    }

    /* move to ourself is simple, done! */
    if (strcmp(oldname, newname) == 0) {
	free(oldname);
	free(newname);
	return 0;
    }

    ret = kcm_ccache_resolve_client(context, client, opcode, oldname, &oldid);
    if (ret) {
	free(oldname);
	free(newname);
	return ret;
    }

    /* Check if new credential cache exists, if not create one. */
    ret = kcm_ccache_resolve_client(context, client, opcode, newname, &newid);
    if (ret == KRB5_FCC_NOFILE)
	ret = kcm_ccache_new_client(context, client, newname, &newid);
    free(newname);

    if (ret) {
	free(oldname);
	kcm_release_ccache(context, oldid);
	return ret;
    }

    HEIMDAL_MUTEX_lock(&oldid->mutex);
    HEIMDAL_MUTEX_lock(&newid->mutex);

    /* move content */
    {
	kcm_ccache_data tmp;

#define MOVE(n,o,f) { tmp.f = n->f ; n->f = o->f; o->f = tmp.f; }

	MOVE(newid, oldid, flags);
	MOVE(newid, oldid, client);
	MOVE(newid, oldid, server);
	MOVE(newid, oldid, creds);
	MOVE(newid, oldid, tkt_life);
	MOVE(newid, oldid, renew_life);
	MOVE(newid, oldid, key);
	MOVE(newid, oldid, kdc_offset);
#undef MOVE
    }

    HEIMDAL_MUTEX_unlock(&oldid->mutex);
    HEIMDAL_MUTEX_unlock(&newid->mutex);

    kcm_release_ccache(context, oldid);
    kcm_release_ccache(context, newid);

    ret = kcm_ccache_destroy_client(context, client, oldname);
    if (ret == 0)
	kcm_drop_default_cache(context, client, oldname);

    free(oldname);

    return ret;
}
Exemplo n.º 22
0
/*
 * Request:
 *	NameZ
 *	ServerPrincipal
 *	KDCFlags
 *	EncryptionType
 *
 * Repsonse:
 *
 */
static krb5_error_code
kcm_op_get_ticket(krb5_context context,
		  kcm_client *client,
		  kcm_operation opcode,
		  krb5_storage *request,
		  krb5_storage *response)
{
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;
    krb5_principal server = NULL;
    krb5_ccache_data ccdata;
    krb5_creds in, *out;
    krb5_kdc_flags flags;

    memset(&in, 0, sizeof(in));

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

    KCM_LOG_REQUEST_NAME(context, client, opcode, name);

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

    ret = krb5_ret_int32(request, &in.session.keytype);
    if (ret) {
	free(name);
	return ret;
    }

    ret = krb5_ret_principal(request, &server);
    if (ret) {
	free(name);
	return ret;
    }

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

    HEIMDAL_MUTEX_lock(&ccache->mutex);

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

    in.client = ccache->client;
    in.server = server;
    in.times.endtime = 0;

    /* glue cc layer will store creds */
    ret = krb5_get_credentials_with_flags(context, 0, flags,
					  &ccdata, &in, &out);

    HEIMDAL_MUTEX_unlock(&ccache->mutex);

    krb5_free_principal(context, server);

    if (ret == 0)
	krb5_free_cred_contents(context, out);

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

    return ret;
}
Exemplo n.º 23
0
/*
 * Request:
 *	NameZ
 *	ServerPrincipalPresent
 *	ServerPrincipal OPTIONAL
 *	Key
 *
 * Repsonse:
 *
 */
static krb5_error_code
kcm_op_get_initial_ticket(krb5_context context,
			  kcm_client *client,
			  kcm_operation opcode,
			  krb5_storage *request,
			  krb5_storage *response)
{
    krb5_error_code ret;
    kcm_ccache ccache;
    char *name;
    int8_t not_tgt = 0;
    krb5_principal server = NULL;
    krb5_keyblock key;

    krb5_keyblock_zero(&key);

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

    KCM_LOG_REQUEST_NAME(context, client, opcode, name);

    ret = krb5_ret_int8(request, &not_tgt);
    if (ret) {
	free(name);
	return ret;
    }

    if (not_tgt) {
	ret = krb5_ret_principal(request, &server);
	if (ret) {
	    free(name);
	    return ret;
	}
    }

    ret = krb5_ret_keyblock(request, &key);
    if (ret) {
	free(name);
	if (server != NULL)
	    krb5_free_principal(context, server);
	return ret;
    }

    ret = kcm_ccache_resolve_client(context, client, opcode,
				    name, &ccache);
    if (ret == 0) {
	HEIMDAL_MUTEX_lock(&ccache->mutex);

	if (ccache->server != NULL) {
	    krb5_free_principal(context, ccache->server);
	    ccache->server = NULL;
	}

	krb5_free_keyblock(context, &ccache->key.keyblock);

	ccache->server = server;
	ccache->key.keyblock = key;
    	ccache->flags |= KCM_FLAGS_USE_CACHED_KEY;

	ret = kcm_ccache_enqueue_default(context, ccache, NULL);
	if (ret) {
	    ccache->server = NULL;
	    krb5_keyblock_zero(&ccache->key.keyblock);
	    ccache->flags &= ~(KCM_FLAGS_USE_CACHED_KEY);
	}

	HEIMDAL_MUTEX_unlock(&ccache->mutex);
    }

    free(name);

    if (ret != 0) {
	krb5_free_principal(context, server);
	krb5_free_keyblock(context, &key);
    }

    kcm_release_ccache(context, ccache);

    return ret;
}
Exemplo n.º 24
0
krb5_error_code
kcm_ccache_new_client(krb5_context context,
		      kcm_client *client,
		      const char *name,
		      kcm_ccache *ccache_p)
{
    krb5_error_code ret;
    kcm_ccache ccache;

    ret = kcm_ccache_resolve_by_name(context, name, &ccache);
    if (ret == 0) {
	if ((ccache->uid != client->uid) && !CLIENT_IS_ROOT(client))
	    return KRB5_FCC_PERM;
    } else if (ret != KRB5_FCC_NOFILE && !(CLIENT_IS_ROOT(client) && ret == KRB5_FCC_PERM)) {
		return ret;
    }

    if (ret == KRB5_FCC_NOFILE) {
	ret = kcm_ccache_new(context, name, &ccache);
	if (ret) {
	    kcm_log(1, "Failed to initialize cache %s", name);
	    return ret;
	}

	/* bind to current client */
	ccache->uid = client->uid;
	ccache->session = client->session;

	/* 
	 * add notification when the session goes away, so we can
	 * remove the credential
	 */
	kcm_session_add(client->session);

    } else {
	ret = kcm_zero_ccache_data(context, ccache);
	if (ret) {
	    kcm_log(1, "Failed to empty cache %s", name);
	    kcm_release_ccache(context, ccache);
	    return ret;
	}
	heim_ipc_event_cancel(ccache->renew_event);
	heim_ipc_event_cancel(ccache->expire_event);
    }

    ret = kcm_access(context, client, KCM_OP_INITIALIZE, ccache);
    if (ret) {
	kcm_release_ccache(context, ccache);
	kcm_ccache_destroy(context, name);
	return ret;
    }

    /*
     * Finally, if the user is root and the cache was created under
     * another user's name, chown the cache to that user.
     */
    if (CLIENT_IS_ROOT(client)) {
	unsigned long uid;
	int matches = sscanf(name,"%ld:",&uid);
	if (matches == 0)
	    matches = sscanf(name,"%ld",&uid);
	if (matches == 1) {
	    kcm_chown(context, client, ccache, (uid_t)uid);
	}
    }

    *ccache_p = ccache;
    return 0;
}
Exemplo n.º 25
0
static krb5_error_code
ccache_init_system(void)
{
    kcm_ccache ccache;
    krb5_error_code ret;

    if (system_cache_name == NULL)
	system_cache_name = kcm_system_config_get_string("cc_name");

    ret = kcm_ccache_new(kcm_context,
			 system_cache_name ? system_cache_name : "SYSTEM",
			 &ccache);
    if (ret)
	return ret;

    ccache->flags |= KCM_FLAGS_OWNER_IS_SYSTEM;
    ccache->flags |= KCM_FLAGS_USE_KEYTAB;

    ret = parse_owners(ccache);
    if (ret)
	return ret;

    ret = krb5_parse_name(kcm_context, system_principal, &ccache->client);
    if (ret) {
	kcm_release_ccache(kcm_context, ccache);
	return ret;
    }

    if (system_server == NULL)
	system_server = kcm_system_config_get_string("server");

    if (system_server != NULL) {
	ret = krb5_parse_name(kcm_context, system_server, &ccache->server);
	if (ret) {
	    kcm_release_ccache(kcm_context, ccache);
	    return ret;
	}
    }

    if (system_keytab == NULL)
	system_keytab = kcm_system_config_get_string("keytab_name");

    if (system_keytab != NULL) {
	ret = krb5_kt_resolve(kcm_context, system_keytab, &ccache->key.keytab);
    } else {
	ret = krb5_kt_default(kcm_context, &ccache->key.keytab);
    }
    if (ret) {
	kcm_release_ccache(kcm_context, ccache);
	return ret;
    }

    if (renew_life == NULL)
	renew_life = kcm_system_config_get_string("renew_life");

    if (renew_life == NULL)
	renew_life = "1 month";

    if (renew_life != NULL) {
	ccache->renew_life = parse_time(renew_life, "s");
	if (ccache->renew_life < 0) {
	    kcm_release_ccache(kcm_context, ccache);
	    return EINVAL;
	}
    }

    if (ticket_life == NULL)
	ticket_life = kcm_system_config_get_string("ticket_life");

    if (ticket_life != NULL) {
	ccache->tkt_life = parse_time(ticket_life, "s");
	if (ccache->tkt_life < 0) {
	    kcm_release_ccache(kcm_context, ccache);
	    return EINVAL;
	}
    }

    if (system_perms == NULL)
	system_perms = kcm_system_config_get_string("mode");

    if (system_perms != NULL) {
	int mode;

	if (sscanf(system_perms, "%o", &mode) != 1)
	    return EINVAL;

	ccache->mode = mode;
    }

    if (disallow_getting_krbtgt == -1) {
	disallow_getting_krbtgt =
	    krb5_config_get_bool_default(kcm_context, NULL, FALSE, "kcm",
					 "disallow-getting-krbtgt", NULL);
    }

    /* enqueue default actions for credentials cache */
    ret = kcm_ccache_enqueue_default(kcm_context, ccache, NULL);

    kcm_release_ccache(kcm_context, ccache); /* retained by event queue */

    return ret;
}
Exemplo n.º 26
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;
}