Blame view

net/sunrpc/auth_unix.c 5.53 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
  /*
   * linux/net/sunrpc/auth_unix.c
   *
   * UNIX-style authentication; no AUTH_SHORT support
   *
   * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
   */
5a0e3ad6a   Tejun Heo   include cleanup: ...
8
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
  #include <linux/types.h>
  #include <linux/sched.h>
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
12
13
14
15
16
17
18
19
20
21
22
  #include <linux/sunrpc/clnt.h>
  #include <linux/sunrpc/auth.h>
  
  #define NFS_NGROUPS	16
  
  struct unx_cred {
  	struct rpc_cred		uc_base;
  	gid_t			uc_gid;
  	gid_t			uc_gids[NFS_NGROUPS];
  };
  #define uc_uid			uc_base.cr_uid
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
28
29
30
  #define UNX_WRITESLACK		(21 + (UNX_MAXNODENAME >> 2))
  
  #ifdef RPC_DEBUG
  # define RPCDBG_FACILITY	RPCDBG_AUTH
  #endif
  
  static struct rpc_auth		unix_auth;
f1c0a8615   Trond Myklebust   SUNRPC: Mark auth...
31
  static const struct rpc_credops	unix_credops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
  
  static struct rpc_auth *
  unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
  {
46121cf7d   Chuck Lever   SUNRPC: fix print...
36
37
38
  	dprintk("RPC:       creating UNIX authenticator for client %p
  ",
  			clnt);
f5c2187cf   Trond Myklebust   SUNRPC: Convert t...
39
  	atomic_inc(&unix_auth.au_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
41
42
43
44
45
  	return &unix_auth;
  }
  
  static void
  unx_destroy(struct rpc_auth *auth)
  {
46121cf7d   Chuck Lever   SUNRPC: fix print...
46
47
  	dprintk("RPC:       destroying UNIX authenticator %p
  ", auth);
3ab9bb724   Trond Myklebust   SUNRPC: Fix a mem...
48
  	rpcauth_clear_credcache(auth->au_credcache);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
  }
  
  /*
   * Lookup AUTH_UNIX creds for current process
   */
  static struct rpc_cred *
  unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
  {
  	return rpcauth_lookup_credcache(auth, acred, flags);
  }
  
  static struct rpc_cred *
  unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
  {
  	struct unx_cred	*cred;
af0938357   Trond Myklebust   SUNRPC: Fix RPCAU...
64
65
  	unsigned int groups = 0;
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66

46121cf7d   Chuck Lever   SUNRPC: fix print...
67
68
69
  	dprintk("RPC:       allocating UNIX cred for uid %d gid %d
  ",
  			acred->uid, acred->gid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70

0f38b873a   Trond Myklebust   SUNRPC: Use GFP_N...
71
  	if (!(cred = kmalloc(sizeof(*cred), GFP_NOFS)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
  		return ERR_PTR(-ENOMEM);
5fe4755e2   Trond Myklebust   SUNRPC: Clean up ...
73
  	rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);
fc432dd90   Trond Myklebust   SUNRPC: Enforce a...
74
  	cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
af0938357   Trond Myklebust   SUNRPC: Fix RPCAU...
75
76
77
78
79
80
81
82
83
84
85
  
  	if (acred->group_info != NULL)
  		groups = acred->group_info->ngroups;
  	if (groups > NFS_NGROUPS)
  		groups = NFS_NGROUPS;
  
  	cred->uc_gid = acred->gid;
  	for (i = 0; i < groups; i++)
  		cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
  	if (i < NFS_NGROUPS)
  		cred->uc_gids[i] = NOGROUP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86

696e38df9   Trond Myklebust   SUNRPC: replace c...
87
  	return &cred->uc_base;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
  }
  
  static void
31be5bf15   Trond Myklebust   SUNRPC: Convert t...
91
  unx_free_cred(struct unx_cred *unx_cred)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
  {
31be5bf15   Trond Myklebust   SUNRPC: Convert t...
93
94
95
96
  	dprintk("RPC:       unx_free_cred %p
  ", unx_cred);
  	kfree(unx_cred);
  }
696e38df9   Trond Myklebust   SUNRPC: replace c...
97

31be5bf15   Trond Myklebust   SUNRPC: Convert t...
98
99
100
101
102
103
104
105
106
107
108
  static void
  unx_free_cred_callback(struct rcu_head *head)
  {
  	struct unx_cred *unx_cred = container_of(head, struct unx_cred, uc_base.cr_rcu);
  	unx_free_cred(unx_cred);
  }
  
  static void
  unx_destroy_cred(struct rpc_cred *cred)
  {
  	call_rcu(&cred->cr_rcu, unx_free_cred_callback);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
115
116
  }
  
  /*
   * Match credentials against current process creds.
   * The root_override argument takes care of cases where the caller may
   * request root creds (e.g. for NFS swapping).
   */
  static int
8a3177604   Trond Myklebust   SUNRPC: Fix a loc...
117
  unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  {
696e38df9   Trond Myklebust   SUNRPC: replace c...
119
  	struct unx_cred	*cred = container_of(rcred, struct unx_cred, uc_base);
af0938357   Trond Myklebust   SUNRPC: Fix RPCAU...
120
121
  	unsigned int groups = 0;
  	unsigned int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
123

af0938357   Trond Myklebust   SUNRPC: Fix RPCAU...
124
125
  	if (cred->uc_uid != acred->uid || cred->uc_gid != acred->gid)
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126

af0938357   Trond Myklebust   SUNRPC: Fix RPCAU...
127
  	if (acred->group_info != NULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  		groups = acred->group_info->ngroups;
af0938357   Trond Myklebust   SUNRPC: Fix RPCAU...
129
130
131
132
133
  	if (groups > NFS_NGROUPS)
  		groups = NFS_NGROUPS;
  	for (i = 0; i < groups ; i++)
  		if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
  			return 0;
dc6f55e9f   NeilBrown   NFS/sunrpc: don't...
134
135
136
  	if (groups < NFS_NGROUPS &&
  	    cred->uc_gids[groups] != NOGROUP)
  		return 0;
af0938357   Trond Myklebust   SUNRPC: Fix RPCAU...
137
  	return 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
141
142
143
  }
  
  /*
   * Marshal credentials.
   * Maybe we should keep a cached credential for performance reasons.
   */
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
144
145
  static __be32 *
  unx_marshal(struct rpc_task *task, __be32 *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
  {
  	struct rpc_clnt	*clnt = task->tk_client;
a17c2153d   Trond Myklebust   SUNRPC: Move the ...
148
  	struct unx_cred	*cred = container_of(task->tk_rqstp->rq_cred, struct unx_cred, uc_base);
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
149
  	__be32		*base, *hold;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  	int		i;
  
  	*p++ = htonl(RPC_AUTH_UNIX);
  	base = p++;
  	*p++ = htonl(jiffies/HZ);
  
  	/*
  	 * Copy the UTS nodename captured when the client was created.
  	 */
  	p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
  
  	*p++ = htonl((u32) cred->uc_uid);
  	*p++ = htonl((u32) cred->uc_gid);
  	hold = p++;
  	for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++)
  		*p++ = htonl((u32) cred->uc_gids[i]);
  	*hold = htonl(p - hold - 1);		/* gid array length */
  	*base = htonl((p - base - 1) << 2);	/* cred length */
  
  	*p++ = htonl(RPC_AUTH_NULL);
  	*p++ = htonl(0);
  
  	return p;
  }
  
  /*
   * Refresh credentials. This is a no-op for AUTH_UNIX
   */
  static int
  unx_refresh(struct rpc_task *task)
  {
a17c2153d   Trond Myklebust   SUNRPC: Move the ...
181
  	set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_rqstp->rq_cred->cr_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
182
183
  	return 0;
  }
d8ed029d6   Alexey Dobriyan   [SUNRPC]: trivial...
184
185
  static __be32 *
  unx_validate(struct rpc_task *task, __be32 *p)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  {
  	rpc_authflavor_t	flavor;
  	u32			size;
  
  	flavor = ntohl(*p++);
  	if (flavor != RPC_AUTH_NULL &&
  	    flavor != RPC_AUTH_UNIX &&
  	    flavor != RPC_AUTH_SHORT) {
  		printk("RPC: bad verf flavor: %u
  ", flavor);
  		return NULL;
  	}
  
  	size = ntohl(*p++);
  	if (size > RPC_MAX_AUTH_SIZE) {
  		printk("RPC: giant verf size: %u
  ", size);
  		return NULL;
  	}
a17c2153d   Trond Myklebust   SUNRPC: Move the ...
205
  	task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
206
207
208
209
  	p += (size >> 2);
  
  	return p;
  }
5d8d9a4d9   Trond Myklebust   NFS: Ensure the A...
210
  int __init rpc_init_authunix(void)
9499b4341   Trond Myklebust   SUNRPC: Give cred...
211
  {
5d8d9a4d9   Trond Myklebust   NFS: Ensure the A...
212
213
214
215
216
217
  	return rpcauth_init_credcache(&unix_auth);
  }
  
  void rpc_destroy_authunix(void)
  {
  	rpcauth_destroy_credcache(&unix_auth);
9499b4341   Trond Myklebust   SUNRPC: Give cred...
218
  }
f1c0a8615   Trond Myklebust   SUNRPC: Mark auth...
219
  const struct rpc_authops authunix_ops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
221
  	.owner		= THIS_MODULE,
  	.au_flavor	= RPC_AUTH_UNIX,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222
  	.au_name	= "UNIX",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
225
226
227
228
229
  	.create		= unx_create,
  	.destroy	= unx_destroy,
  	.lookup_cred	= unx_lookup_cred,
  	.crcreate	= unx_create_cred,
  };
  
  static
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
233
  struct rpc_auth		unix_auth = {
  	.au_cslack	= UNX_WRITESLACK,
  	.au_rslack	= 2,			/* assume AUTH_NULL verf */
  	.au_ops		= &authunix_ops,
81039f1f2   Trond Myklebust   NFS: Display the ...
234
  	.au_flavor	= RPC_AUTH_UNIX,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
  	.au_count	= ATOMIC_INIT(0),
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236
237
238
  };
  
  static
f1c0a8615   Trond Myklebust   SUNRPC: Mark auth...
239
  const struct rpc_credops unix_credops = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
240
241
  	.cr_name	= "AUTH_UNIX",
  	.crdestroy	= unx_destroy_cred,
5c691044e   Trond Myklebust   SUNRPC: Add an rp...
242
  	.crbind		= rpcauth_generic_bind_cred,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
243
244
245
246
247
  	.crmatch	= unx_match,
  	.crmarshal	= unx_marshal,
  	.crrefresh	= unx_refresh,
  	.crvalidate	= unx_validate,
  };