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/socket.h>
14 #include <linux/sunrpc/clnt.h>
15 #include <linux/sunrpc/auth.h>
17 #define NFS_NGROUPS 16
20 struct rpc_cred uc_base
;
22 uid_t uc_puid
; /* process uid */
23 gid_t uc_pgid
; /* process gid */
24 gid_t uc_gids
[NFS_NGROUPS
];
26 #define uc_uid uc_base.cr_uid
27 #define uc_count uc_base.cr_count
28 #define uc_flags uc_base.cr_flags
29 #define uc_expire uc_base.cr_expire
31 #define UNX_CRED_EXPIRE (60 * HZ)
33 #define UNX_WRITESLACK (21 + (UNX_MAXNODENAME >> 2))
36 # define RPCDBG_FACILITY RPCDBG_AUTH
39 static struct rpc_credops unix_credops
;
41 static struct rpc_auth
*
42 unx_create(struct rpc_clnt
*clnt
, rpc_authflavor_t flavor
)
44 struct rpc_auth
*auth
;
46 dprintk("RPC: creating UNIX authenticator for client %p\n", clnt
);
47 if (!(auth
= (struct rpc_auth
*) kmalloc(sizeof(*auth
), GFP_KERNEL
)))
49 auth
->au_cslack
= UNX_WRITESLACK
;
50 auth
->au_rslack
= 2; /* assume AUTH_NULL verf */
51 auth
->au_expire
= UNX_CRED_EXPIRE
;
52 auth
->au_ops
= &authunix_ops
;
54 rpcauth_init_credcache(auth
);
60 unx_destroy(struct rpc_auth
*auth
)
62 dprintk("RPC: destroying UNIX authenticator %p\n", auth
);
63 rpcauth_free_credcache(auth
);
66 static struct rpc_cred
*
67 unx_create_cred(struct rpc_auth
*auth
, struct auth_cred
*acred
, int flags
)
69 struct unx_cred
*cred
;
72 dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
73 acred
->uid
, acred
->gid
);
75 if (!(cred
= (struct unx_cred
*) kmalloc(sizeof(*cred
), GFP_KERNEL
)))
78 atomic_set(&cred
->uc_count
, 0);
79 cred
->uc_flags
= RPCAUTH_CRED_UPTODATE
;
80 if (flags
& RPC_TASK_ROOTCREDS
) {
81 cred
->uc_uid
= cred
->uc_puid
= 0;
82 cred
->uc_gid
= cred
->uc_pgid
= 0;
83 cred
->uc_gids
[0] = NOGROUP
;
85 int groups
= acred
->group_info
->ngroups
;
86 if (groups
> NFS_NGROUPS
)
89 cred
->uc_uid
= acred
->uid
;
90 cred
->uc_gid
= acred
->gid
;
91 cred
->uc_puid
= current
->uid
;
92 cred
->uc_pgid
= current
->gid
;
93 for (i
= 0; i
< groups
; i
++)
94 cred
->uc_gids
[i
] = GROUP_AT(acred
->group_info
, i
);
96 cred
->uc_gids
[i
] = NOGROUP
;
98 cred
->uc_base
.cr_ops
= &unix_credops
;
100 return (struct rpc_cred
*) cred
;
104 unx_destroy_cred(struct rpc_cred
*cred
)
110 * Match credentials against current process creds.
111 * The root_override argument takes care of cases where the caller may
112 * request root creds (e.g. for NFS swapping).
115 unx_match(struct auth_cred
*acred
, struct rpc_cred
*rcred
, int taskflags
)
117 struct unx_cred
*cred
= (struct unx_cred
*) rcred
;
120 if (!(taskflags
& RPC_TASK_ROOTCREDS
)) {
123 if (cred
->uc_uid
!= acred
->uid
124 || cred
->uc_gid
!= acred
->gid
125 || cred
->uc_puid
!= current
->uid
126 || cred
->uc_pgid
!= current
->gid
)
129 groups
= acred
->group_info
->ngroups
;
130 if (groups
> NFS_NGROUPS
)
131 groups
= NFS_NGROUPS
;
132 for (i
= 0; i
< groups
; i
++)
133 if (cred
->uc_gids
[i
] != GROUP_AT(acred
->group_info
, i
))
137 return (cred
->uc_uid
== 0 && cred
->uc_puid
== 0
138 && cred
->uc_gid
== 0 && cred
->uc_pgid
== 0
139 && cred
->uc_gids
[0] == (gid_t
) NOGROUP
);
143 * Marshal credentials.
144 * Maybe we should keep a cached credential for performance reasons.
147 unx_marshal(struct rpc_task
*task
, u32
*p
, int ruid
)
149 struct rpc_clnt
*clnt
= task
->tk_client
;
150 struct unx_cred
*cred
= (struct unx_cred
*) task
->tk_msg
.rpc_cred
;
154 *p
++ = htonl(RPC_AUTH_UNIX
);
156 *p
++ = htonl(jiffies
/HZ
);
159 * Copy the UTS nodename captured when the client was created.
161 p
= xdr_encode_array(p
, clnt
->cl_nodename
, clnt
->cl_nodelen
);
163 /* Note: we don't use real uid if it involves raising privilege */
164 if (ruid
&& cred
->uc_puid
!= 0 && cred
->uc_pgid
!= 0) {
165 *p
++ = htonl((u32
) cred
->uc_puid
);
166 *p
++ = htonl((u32
) cred
->uc_pgid
);
168 *p
++ = htonl((u32
) cred
->uc_uid
);
169 *p
++ = htonl((u32
) cred
->uc_gid
);
172 for (i
= 0; i
< 16 && cred
->uc_gids
[i
] != (gid_t
) NOGROUP
; i
++)
173 *p
++ = htonl((u32
) cred
->uc_gids
[i
]);
174 *hold
= htonl(p
- hold
- 1); /* gid array length */
175 *base
= htonl((p
- base
- 1) << 2); /* cred length */
177 *p
++ = htonl(RPC_AUTH_NULL
);
184 * Refresh credentials. This is a no-op for AUTH_UNIX
187 unx_refresh(struct rpc_task
*task
)
189 task
->tk_msg
.rpc_cred
->cr_flags
|= RPCAUTH_CRED_UPTODATE
;
190 return task
->tk_status
= -EACCES
;
194 unx_validate(struct rpc_task
*task
, u32
*p
)
196 rpc_authflavor_t flavor
;
199 flavor
= ntohl(*p
++);
200 if (flavor
!= RPC_AUTH_NULL
&&
201 flavor
!= RPC_AUTH_UNIX
&&
202 flavor
!= RPC_AUTH_SHORT
) {
203 printk("RPC: bad verf flavor: %u\n", flavor
);
208 if (size
> RPC_MAX_AUTH_SIZE
) {
209 printk("RPC: giant verf size: %u\n", size
);
212 task
->tk_auth
->au_rslack
= (size
>> 2) + 2;
218 struct rpc_authops authunix_ops
= {
219 .owner
= THIS_MODULE
,
220 .au_flavor
= RPC_AUTH_UNIX
,
224 .create
= unx_create
,
225 .destroy
= unx_destroy
,
226 .crcreate
= unx_create_cred
,
230 struct rpc_credops unix_credops
= {
231 .crdestroy
= unx_destroy_cred
,
232 .crmatch
= unx_match
,
233 .crmarshal
= unx_marshal
,
234 .crrefresh
= unx_refresh
,
235 .crvalidate
= unx_validate
,