2 * linux/net/sunrpc/auth_unix.c
4 * UNIX-style authentication; no AUTH_SHORT support
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
9 #include <linux/types.h>
10 #include <linux/sched.h>
11 #include <linux/module.h>
12 #include <linux/sunrpc/clnt.h>
13 #include <linux/sunrpc/auth.h>
15 #define NFS_NGROUPS 16
18 struct rpc_cred uc_base
;
20 gid_t uc_gids
[NFS_NGROUPS
];
22 #define uc_uid uc_base.cr_uid
23 #define uc_count uc_base.cr_count
24 #define uc_flags uc_base.cr_flags
25 #define uc_expire uc_base.cr_expire
27 #define UNX_CRED_EXPIRE (60 * HZ)
29 #define UNX_WRITESLACK (21 + (UNX_MAXNODENAME >> 2))
32 # define RPCDBG_FACILITY RPCDBG_AUTH
35 static struct rpc_auth unix_auth
;
36 static struct rpc_cred_cache unix_cred_cache
;
37 static struct rpc_credops unix_credops
;
39 static struct rpc_auth
*
40 unx_create(struct rpc_clnt
*clnt
, rpc_authflavor_t flavor
)
42 dprintk("RPC: creating UNIX authenticator for client %p\n",
44 if (atomic_inc_return(&unix_auth
.au_count
) == 0)
45 unix_cred_cache
.nextgc
= jiffies
+ (unix_cred_cache
.expire
>> 1);
50 unx_destroy(struct rpc_auth
*auth
)
52 dprintk("RPC: destroying UNIX authenticator %p\n", auth
);
53 rpcauth_free_credcache(auth
);
57 * Lookup AUTH_UNIX creds for current process
59 static struct rpc_cred
*
60 unx_lookup_cred(struct rpc_auth
*auth
, struct auth_cred
*acred
, int flags
)
62 return rpcauth_lookup_credcache(auth
, acred
, flags
);
65 static struct rpc_cred
*
66 unx_create_cred(struct rpc_auth
*auth
, struct auth_cred
*acred
, int flags
)
68 struct unx_cred
*cred
;
71 dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
72 acred
->uid
, acred
->gid
);
74 if (!(cred
= kmalloc(sizeof(*cred
), GFP_KERNEL
)))
75 return ERR_PTR(-ENOMEM
);
77 atomic_set(&cred
->uc_count
, 1);
78 cred
->uc_flags
= RPCAUTH_CRED_UPTODATE
;
79 if (flags
& RPCAUTH_LOOKUP_ROOTCREDS
) {
82 cred
->uc_gids
[0] = NOGROUP
;
84 int groups
= acred
->group_info
->ngroups
;
85 if (groups
> NFS_NGROUPS
)
88 cred
->uc_uid
= acred
->uid
;
89 cred
->uc_gid
= acred
->gid
;
90 for (i
= 0; i
< groups
; i
++)
91 cred
->uc_gids
[i
] = GROUP_AT(acred
->group_info
, i
);
93 cred
->uc_gids
[i
] = NOGROUP
;
95 cred
->uc_base
.cr_ops
= &unix_credops
;
97 return (struct rpc_cred
*) cred
;
101 unx_destroy_cred(struct rpc_cred
*cred
)
107 * Match credentials against current process creds.
108 * The root_override argument takes care of cases where the caller may
109 * request root creds (e.g. for NFS swapping).
112 unx_match(struct auth_cred
*acred
, struct rpc_cred
*rcred
, int flags
)
114 struct unx_cred
*cred
= (struct unx_cred
*) rcred
;
117 if (!(flags
& RPCAUTH_LOOKUP_ROOTCREDS
)) {
120 if (cred
->uc_uid
!= acred
->uid
121 || cred
->uc_gid
!= acred
->gid
)
124 groups
= acred
->group_info
->ngroups
;
125 if (groups
> NFS_NGROUPS
)
126 groups
= NFS_NGROUPS
;
127 for (i
= 0; i
< groups
; i
++)
128 if (cred
->uc_gids
[i
] != GROUP_AT(acred
->group_info
, i
))
132 return (cred
->uc_uid
== 0
134 && cred
->uc_gids
[0] == (gid_t
) NOGROUP
);
138 * Marshal credentials.
139 * Maybe we should keep a cached credential for performance reasons.
142 unx_marshal(struct rpc_task
*task
, __be32
*p
)
144 struct rpc_clnt
*clnt
= task
->tk_client
;
145 struct unx_cred
*cred
= (struct unx_cred
*) task
->tk_msg
.rpc_cred
;
149 *p
++ = htonl(RPC_AUTH_UNIX
);
151 *p
++ = htonl(jiffies
/HZ
);
154 * Copy the UTS nodename captured when the client was created.
156 p
= xdr_encode_array(p
, clnt
->cl_nodename
, clnt
->cl_nodelen
);
158 *p
++ = htonl((u32
) cred
->uc_uid
);
159 *p
++ = htonl((u32
) cred
->uc_gid
);
161 for (i
= 0; i
< 16 && cred
->uc_gids
[i
] != (gid_t
) NOGROUP
; i
++)
162 *p
++ = htonl((u32
) cred
->uc_gids
[i
]);
163 *hold
= htonl(p
- hold
- 1); /* gid array length */
164 *base
= htonl((p
- base
- 1) << 2); /* cred length */
166 *p
++ = htonl(RPC_AUTH_NULL
);
173 * Refresh credentials. This is a no-op for AUTH_UNIX
176 unx_refresh(struct rpc_task
*task
)
178 task
->tk_msg
.rpc_cred
->cr_flags
|= RPCAUTH_CRED_UPTODATE
;
183 unx_validate(struct rpc_task
*task
, __be32
*p
)
185 rpc_authflavor_t flavor
;
188 flavor
= ntohl(*p
++);
189 if (flavor
!= RPC_AUTH_NULL
&&
190 flavor
!= RPC_AUTH_UNIX
&&
191 flavor
!= RPC_AUTH_SHORT
) {
192 printk("RPC: bad verf flavor: %u\n", flavor
);
197 if (size
> RPC_MAX_AUTH_SIZE
) {
198 printk("RPC: giant verf size: %u\n", size
);
201 task
->tk_auth
->au_rslack
= (size
>> 2) + 2;
207 struct rpc_authops authunix_ops
= {
208 .owner
= THIS_MODULE
,
209 .au_flavor
= RPC_AUTH_UNIX
,
213 .create
= unx_create
,
214 .destroy
= unx_destroy
,
215 .lookup_cred
= unx_lookup_cred
,
216 .crcreate
= unx_create_cred
,
220 struct rpc_cred_cache unix_cred_cache
= {
221 .expire
= UNX_CRED_EXPIRE
,
225 struct rpc_auth unix_auth
= {
226 .au_cslack
= UNX_WRITESLACK
,
227 .au_rslack
= 2, /* assume AUTH_NULL verf */
228 .au_ops
= &authunix_ops
,
229 .au_flavor
= RPC_AUTH_UNIX
,
230 .au_count
= ATOMIC_INIT(0),
231 .au_credcache
= &unix_cred_cache
,
235 struct rpc_credops unix_credops
= {
236 .cr_name
= "AUTH_UNIX",
237 .crdestroy
= unx_destroy_cred
,
238 .crmatch
= unx_match
,
239 .crmarshal
= unx_marshal
,
240 .crrefresh
= unx_refresh
,
241 .crvalidate
= unx_validate
,