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>
9 #include <linux/types.h>
10 #include <linux/malloc.h>
11 #include <linux/socket.h>
13 #include <linux/utsname.h>
14 #include <linux/sunrpc/clnt.h>
15 #include <linux/sunrpc/auth.h>
17 #define NFS_NGROUPS 16
19 struct rpc_cred uc_base
;
21 gid_t uc_gid
, uc_fsgid
;
22 gid_t uc_gids
[NFS_NGROUPS
];
24 #define uc_uid uc_base.cr_uid
25 #define uc_count uc_base.cr_count
26 #define uc_flags uc_base.cr_flags
27 #define uc_expire uc_base.cr_expire
29 #define UNX_CRED_EXPIRE (60 * HZ)
31 #ifndef DONT_FILLIN_HOSTNAME
32 /* # define UNX_MAXNODENAME (sizeof(system_utsname.nodename)-1) */
33 # define UNX_MAXNODENAME 32
34 # define UNX_WRITESLACK (21 + (UNX_MAXNODENAME >> 2))
36 # define UNX_WRITESLACK 20
40 # define RPCDBG_FACILITY RPCDBG_AUTH
43 static struct rpc_auth
*
44 unx_create(struct rpc_clnt
*clnt
)
46 struct rpc_auth
*auth
;
48 dprintk("RPC: creating UNIX authenticator for client %p\n", clnt
);
49 if (!(auth
= (struct rpc_auth
*) rpc_allocate(0, sizeof(*auth
))))
51 auth
->au_cslack
= UNX_WRITESLACK
;
52 auth
->au_rslack
= 2; /* assume AUTH_NULL verf */
53 auth
->au_expire
= UNX_CRED_EXPIRE
;
54 auth
->au_ops
= &authunix_ops
;
56 rpcauth_init_credcache(auth
);
62 unx_destroy(struct rpc_auth
*auth
)
64 dprintk("RPC: destroying UNIX authenticator %p\n", auth
);
65 rpcauth_free_credcache(auth
);
69 static struct rpc_cred
*
70 unx_create_cred(struct rpc_task
*task
)
72 struct unx_cred
*cred
;
75 dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
76 current
->uid
, current
->gid
);
78 if (!(cred
= (struct unx_cred
*) rpc_malloc(task
, sizeof(*cred
))))
82 cred
->uc_flags
= RPCAUTH_CRED_UPTODATE
;
83 if (RPC_DO_ROOTOVERRIDE(task
)) {
84 cred
->uc_uid
= cred
->uc_fsuid
= 0;
85 cred
->uc_gid
= cred
->uc_fsgid
= 0;
86 cred
->uc_gids
[0] = NOGROUP
;
88 int groups
= current
->ngroups
;
89 if (groups
> NFS_NGROUPS
)
92 cred
->uc_uid
= current
->uid
;
93 cred
->uc_gid
= current
->gid
;
94 cred
->uc_fsuid
= current
->fsuid
;
95 cred
->uc_fsgid
= current
->fsgid
;
96 for (i
= 0; i
< groups
; i
++)
97 cred
->uc_gids
[i
] = (gid_t
) current
->groups
[i
];
99 cred
->uc_gids
[i
] = NOGROUP
;
102 return (struct rpc_cred
*) cred
;
106 authunix_fake_cred(struct rpc_task
*task
, uid_t uid
, gid_t gid
)
108 struct unx_cred
*cred
;
110 dprintk("RPC: allocating fake UNIX cred for uid %d gid %d\n",
113 if (!(cred
= (struct unx_cred
*) rpc_malloc(task
, sizeof(*cred
))))
117 cred
->uc_flags
= RPCAUTH_CRED_DEAD
|RPCAUTH_CRED_UPTODATE
;
120 cred
->uc_fsuid
= uid
;
121 cred
->uc_fsgid
= gid
;
122 cred
->uc_gids
[0] = (gid_t
) NOGROUP
;
124 return task
->tk_cred
= (struct rpc_cred
*) cred
;
128 unx_destroy_cred(struct rpc_cred
*cred
)
134 * Match credentials against current process creds.
135 * The root_override argument takes care of cases where the caller may
136 * request root creds (e.g. for NFS swapping).
139 unx_match(struct rpc_task
* task
, struct rpc_cred
*rcred
)
141 struct unx_cred
*cred
= (struct unx_cred
*) rcred
;
144 if (!RPC_DO_ROOTOVERRIDE(task
)) {
147 if (cred
->uc_uid
!= current
->uid
148 || cred
->uc_gid
!= current
->gid
149 || cred
->uc_fsuid
!= current
->fsuid
150 || cred
->uc_fsgid
!= current
->fsgid
)
153 groups
= current
->ngroups
;
154 if (groups
> NFS_NGROUPS
)
155 groups
= NFS_NGROUPS
;
156 for (i
= 0; i
< groups
; i
++)
157 if (cred
->uc_gids
[i
] != (gid_t
) current
->groups
[i
])
161 return (cred
->uc_uid
== 0 && cred
->uc_fsuid
== 0
162 && cred
->uc_gid
== 0 && cred
->uc_fsgid
== 0
163 && cred
->uc_gids
[0] == (gid_t
) NOGROUP
);
167 * Marshal credentials.
168 * Maybe we should keep a cached credential for performance reasons.
171 unx_marshal(struct rpc_task
*task
, u32
*p
, int ruid
)
173 struct unx_cred
*cred
= (struct unx_cred
*) task
->tk_cred
;
177 *p
++ = htonl(RPC_AUTH_UNIX
);
179 *p
++ = htonl(jiffies
/HZ
);
180 #ifndef DONT_FILLIN_HOSTNAME
182 * Problem: The UTS name could change under us. We can't lock
183 * here to handle this. On the other hand we can't really
184 * go building a bad RPC!
186 if ((n
= strlen((char *) system_utsname
.nodename
)) > UNX_MAXNODENAME
)
189 memcpy(p
, system_utsname
.nodename
, n
);
195 *p
++ = htonl((u32
) cred
->uc_uid
);
196 *p
++ = htonl((u32
) cred
->uc_gid
);
198 *p
++ = htonl((u32
) cred
->uc_fsuid
);
199 *p
++ = htonl((u32
) cred
->uc_fsgid
);
202 for (i
= 0; i
< 16 && cred
->uc_gids
[i
] != (gid_t
) NOGROUP
; i
++)
203 *p
++ = htonl((u32
) cred
->uc_gids
[i
]);
204 *hold
= htonl(p
- hold
- 1); /* gid array length */
205 *base
= htonl((p
- base
- 1) << 2); /* cred length */
207 *p
++ = htonl(RPC_AUTH_NULL
);
214 * Refresh credentials. This is a no-op for AUTH_UNIX
217 unx_refresh(struct rpc_task
*task
)
219 task
->tk_cred
->cr_flags
|= RPCAUTH_CRED_UPTODATE
;
220 return task
->tk_status
= -EACCES
;
224 unx_validate(struct rpc_task
*task
, u32
*p
)
228 if (n
!= RPC_AUTH_NULL
&& n
!= RPC_AUTH_UNIX
&& n
!= RPC_AUTH_SHORT
) {
229 printk("RPC: bad verf flavor: %ld\n", (unsigned long) n
);
232 if ((n
= ntohl(*p
++)) > 400) {
233 printk("RPC: giant verf size: %ld\n", (unsigned long) n
);
236 task
->tk_auth
->au_rslack
= (n
>> 2) + 2;
242 struct rpc_authops authunix_ops
= {