2 * linux/net/sunrpc/rpcauth_unix.c
4 * UNIX-style authentication; no AUTH_SHORT support
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
8 * Modified May 1999 Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
11 #include <linux/types.h>
12 #include <linux/string.h>
13 #include <linux/malloc.h>
14 #include <linux/socket.h>
16 #include <linux/sunrpc/clnt.h>
17 #include <linux/sunrpc/auth.h>
19 #define NFS_NGROUPS 16
21 struct rpc_cred uc_base
;
23 gid_t uc_gid
, uc_fsgid
;
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_auth
*
40 unx_create(struct rpc_clnt
*clnt
)
42 struct rpc_auth
*auth
;
44 dprintk("RPC: creating UNIX authenticator for client %p\n", clnt
);
45 if (!(auth
= (struct rpc_auth
*) rpc_allocate(0, sizeof(*auth
))))
47 auth
->au_cslack
= UNX_WRITESLACK
;
48 auth
->au_rslack
= 2; /* assume AUTH_NULL verf */
49 auth
->au_expire
= UNX_CRED_EXPIRE
;
50 auth
->au_ops
= &authunix_ops
;
52 rpcauth_init_credcache(auth
);
58 unx_destroy(struct rpc_auth
*auth
)
60 dprintk("RPC: destroying UNIX authenticator %p\n", auth
);
61 rpcauth_free_credcache(auth
);
65 static struct rpc_cred
*
66 unx_create_cred(struct rpc_task
*task
)
68 struct unx_cred
*cred
;
71 dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
72 current
->uid
, current
->gid
);
74 if (!(cred
= (struct unx_cred
*) rpc_malloc(task
, sizeof(*cred
)))) {
75 task
->tk_status
= -ENOMEM
;
80 cred
->uc_flags
= RPCAUTH_CRED_UPTODATE
;
81 if (RPC_DO_ROOTOVERRIDE(task
)) {
82 cred
->uc_uid
= cred
->uc_fsuid
= 0;
83 cred
->uc_gid
= cred
->uc_fsgid
= 0;
84 cred
->uc_gids
[0] = NOGROUP
;
86 int groups
= current
->ngroups
;
87 if (groups
> NFS_NGROUPS
)
90 cred
->uc_uid
= current
->uid
;
91 cred
->uc_gid
= current
->gid
;
92 cred
->uc_fsuid
= current
->fsuid
;
93 cred
->uc_fsgid
= current
->fsgid
;
94 for (i
= 0; i
< groups
; i
++)
95 cred
->uc_gids
[i
] = (gid_t
) current
->groups
[i
];
97 cred
->uc_gids
[i
] = NOGROUP
;
100 return (struct rpc_cred
*) cred
;
104 authunix_fake_cred(struct rpc_task
*task
, uid_t uid
, gid_t gid
)
106 struct unx_cred
*cred
;
108 dprintk("RPC: allocating fake UNIX cred for uid %d gid %d\n",
111 if (!(cred
= (struct unx_cred
*) rpc_malloc(task
, sizeof(*cred
))))
115 cred
->uc_flags
= RPCAUTH_CRED_DEAD
|RPCAUTH_CRED_UPTODATE
;
118 cred
->uc_fsuid
= uid
;
119 cred
->uc_fsgid
= gid
;
120 cred
->uc_gids
[0] = (gid_t
) NOGROUP
;
122 return task
->tk_cred
= (struct rpc_cred
*) cred
;
126 unx_destroy_cred(struct rpc_cred
*cred
)
132 * Match credentials against current process creds.
133 * The root_override argument takes care of cases where the caller may
134 * request root creds (e.g. for NFS swapping).
137 unx_match(struct rpc_task
* task
, struct rpc_cred
*rcred
)
139 struct unx_cred
*cred
= (struct unx_cred
*) rcred
;
142 if (!RPC_DO_ROOTOVERRIDE(task
)) {
145 if (cred
->uc_uid
!= current
->uid
146 || cred
->uc_gid
!= current
->gid
147 || cred
->uc_fsuid
!= current
->fsuid
148 || cred
->uc_fsgid
!= current
->fsgid
)
151 groups
= current
->ngroups
;
152 if (groups
> NFS_NGROUPS
)
153 groups
= NFS_NGROUPS
;
154 for (i
= 0; i
< groups
; i
++)
155 if (cred
->uc_gids
[i
] != (gid_t
) current
->groups
[i
])
159 return (cred
->uc_uid
== 0 && cred
->uc_fsuid
== 0
160 && cred
->uc_gid
== 0 && cred
->uc_fsgid
== 0
161 && cred
->uc_gids
[0] == (gid_t
) NOGROUP
);
165 * Marshal credentials.
166 * Maybe we should keep a cached credential for performance reasons.
169 unx_marshal(struct rpc_task
*task
, u32
*p
, int ruid
)
171 struct rpc_clnt
*clnt
= task
->tk_client
;
172 struct unx_cred
*cred
= (struct unx_cred
*) task
->tk_cred
;
176 *p
++ = htonl(RPC_AUTH_UNIX
);
178 *p
++ = htonl(jiffies
/HZ
);
181 * Copy the UTS nodename captured when the client was created.
183 n
= clnt
->cl_nodelen
;
185 memcpy(p
, clnt
->cl_nodename
, n
);
189 *p
++ = htonl((u32
) cred
->uc_uid
);
190 *p
++ = htonl((u32
) cred
->uc_gid
);
192 *p
++ = htonl((u32
) cred
->uc_fsuid
);
193 *p
++ = htonl((u32
) cred
->uc_fsgid
);
196 for (i
= 0; i
< 16 && cred
->uc_gids
[i
] != (gid_t
) NOGROUP
; i
++)
197 *p
++ = htonl((u32
) cred
->uc_gids
[i
]);
198 *hold
= htonl(p
- hold
- 1); /* gid array length */
199 *base
= htonl((p
- base
- 1) << 2); /* cred length */
201 *p
++ = htonl(RPC_AUTH_NULL
);
208 * Refresh credentials. This is a no-op for AUTH_UNIX
211 unx_refresh(struct rpc_task
*task
)
213 task
->tk_cred
->cr_flags
|= RPCAUTH_CRED_UPTODATE
;
214 return task
->tk_status
= -EACCES
;
218 unx_validate(struct rpc_task
*task
, u32
*p
)
222 if (n
!= RPC_AUTH_NULL
&& n
!= RPC_AUTH_UNIX
&& n
!= RPC_AUTH_SHORT
) {
223 printk("RPC: bad verf flavor: %ld\n", (unsigned long) n
);
226 if ((n
= ntohl(*p
++)) > 400) {
227 printk("RPC: giant verf size: %ld\n", (unsigned long) n
);
230 task
->tk_auth
->au_rslack
= (n
>> 2) + 2;
236 struct rpc_authops authunix_ops
= {