aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/key-ui.h
blob: cc326174a80886d8c6aba40e11055455de84a60f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* key-ui.h: key userspace interface stuff
 *
 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#ifndef _LINUX_KEY_UI_H
#define _LINUX_KEY_UI_H

#include <linux/key.h>

/* the key tree */
extern struct rb_root key_serial_tree;
extern spinlock_t key_serial_lock;

/* required permissions */
#define	KEY_VIEW	0x01	/* require permission to view attributes */
#define	KEY_READ	0x02	/* require permission to read content */
#define	KEY_WRITE	0x04	/* require permission to update / modify */
#define	KEY_SEARCH	0x08	/* require permission to search (keyring) or find (key) */
#define	KEY_LINK	0x10	/* require permission to link */
#define	KEY_ALL		0x1f	/* all the above permissions */

/*
 * the keyring payload contains a list of the keys to which the keyring is
 * subscribed
 */
struct keyring_list {
	struct rcu_head	rcu;		/* RCU deletion hook */
	unsigned short	maxkeys;	/* max keys this list can hold */
	unsigned short	nkeys;		/* number of keys currently held */
	unsigned short	delkey;		/* key to be unlinked by RCU */
	struct key	*keys[0];
};


/*
 * check to see whether permission is granted to use a key in the desired way
 */
static inline int key_permission(const struct key *key, key_perm_t perm)
{
	key_perm_t kperm;

	if (key->uid == current->fsuid)
		kperm = key->perm >> 16;
	else if (key->gid != -1 &&
		 key->perm & KEY_GRP_ALL &&
		 in_group_p(key->gid)
		 )
		kperm = key->perm >> 8;
	else
		kperm = key->perm;

	kperm = kperm & perm & KEY_ALL;

	return kperm == perm;
}

/*
 * check to see whether permission is granted to use a key in at least one of
 * the desired ways
 */
static inline int key_any_permission(const struct key *key, key_perm_t perm)
{
	key_perm_t kperm;

	if (key->uid == current->fsuid)
		kperm = key->perm >> 16;
	else if (key->gid != -1 &&
		 key->perm & KEY_GRP_ALL &&
		 in_group_p(key->gid)
		 )
		kperm = key->perm >> 8;
	else
		kperm = key->perm;

	kperm = kperm & perm & KEY_ALL;

	return kperm != 0;
}

static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid)
{
	int ret;

	task_lock(tsk);
	ret = groups_search(tsk->group_info, gid);
	task_unlock(tsk);
	return ret;
}

static inline int key_task_permission(const struct key *key,
				      struct task_struct *context,
				      key_perm_t perm)
{
	key_perm_t kperm;

	if (key->uid == context->fsuid) {
		kperm = key->perm >> 16;
	}
	else if (key->gid != -1 &&
		 key->perm & KEY_GRP_ALL && (
			 key->gid == context->fsgid ||
			 key_task_groups_search(context, key->gid)
			 )
		 ) {
		kperm = key->perm >> 8;
	}
	else {
		kperm = key->perm;
	}

	kperm = kperm & perm & KEY_ALL;

	return kperm == perm;

}

extern struct key *lookup_user_key(struct task_struct *context,
				   key_serial_t id, int create, int partial,
				   key_perm_t perm);

extern long join_session_keyring(const char *name);

extern struct key_type *key_type_lookup(const char *type);
extern void key_type_put(struct key_type *ktype);

#define key_negative_timeout	60	/* default timeout on a negative key's existence */


#endif /* _LINUX_KEY_UI_H */