diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /net/sunrpc/auth_unix.c | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'net/sunrpc/auth_unix.c')
-rw-r--r-- | net/sunrpc/auth_unix.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c new file mode 100644 index 000000000..761bfd242 --- /dev/null +++ b/net/sunrpc/auth_unix.c @@ -0,0 +1,238 @@ +/* + * linux/net/sunrpc/rpcauth_unix.c + * + * UNIX-style authentication; no AUTH_SHORT support + * + * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> + */ + +#include <linux/types.h> +#include <linux/malloc.h> +#include <linux/socket.h> +#include <linux/in.h> +#include <linux/utsname.h> +#include <linux/sunrpc/clnt.h> +#include <linux/sunrpc/auth.h> + +struct unx_cred { + struct rpc_cred uc_base; + uid_t uc_fsuid; + gid_t uc_gid, uc_fsgid; + gid_t uc_gids[16]; +}; +#define uc_uid uc_base.cr_uid +#define uc_count uc_base.cr_count +#define uc_flags uc_base.cr_flags +#define uc_expire uc_base.cr_expire + +#define UNX_CRED_EXPIRE (60 * HZ) + +#ifndef DONT_FILLIN_HOSTNAME +/* # define UNX_MAXNODENAME (sizeof(system_utsname.nodename)-1) */ +# define UNX_MAXNODENAME 32 +# define UNX_WRITESLACK (21 + (UNX_MAXNODENAME >> 2)) +#else +# define UNX_WRITESLACK 20 +#endif + +#ifdef RPC_DEBUG +# define RPCDBG_FACILITY RPCDBG_AUTH +#endif + +static struct rpc_auth * +unx_create(struct rpc_clnt *clnt) +{ + struct rpc_auth *auth; + + dprintk("RPC: creating UNIX authenticator for client %p\n", clnt); + if (!(auth = (struct rpc_auth *) rpc_allocate(0, sizeof(*auth)))) + return NULL; + auth->au_cslack = UNX_WRITESLACK; + auth->au_rslack = 2; /* assume AUTH_NULL verf */ + auth->au_expire = UNX_CRED_EXPIRE; + auth->au_ops = &authunix_ops; + + rpcauth_init_credcache(auth); + + return auth; +} + +static void +unx_destroy(struct rpc_auth *auth) +{ + dprintk("RPC: destroying UNIX authenticator %p\n", auth); + rpcauth_free_credcache(auth); + rpc_free(auth); +} + +static struct rpc_cred * +unx_create_cred(struct rpc_task *task) +{ + struct unx_cred *cred; + int i; + + dprintk("RPC: allocating UNIX cred for uid %d gid %d\n", + current->uid, current->gid); + + if (!(cred = (struct unx_cred *) rpc_malloc(task, sizeof(*cred)))) + return NULL; + + cred->uc_count = 0; + cred->uc_flags = RPCAUTH_CRED_UPTODATE; + if (RPC_DO_ROOTOVERRIDE(task)) { + cred->uc_uid = cred->uc_fsuid = 0; + cred->uc_gid = cred->uc_fsgid = 0; + cred->uc_gids[0] = NOGROUP; + } else { + cred->uc_uid = current->uid; + cred->uc_gid = current->gid; + cred->uc_fsuid = current->fsuid; + cred->uc_fsgid = current->fsgid; + for (i = 0; i < 16 && i < NGROUPS; i++) + cred->uc_gids[i] = (gid_t) current->groups[i]; + } + + return (struct rpc_cred *) cred; +} + +struct rpc_cred * +authunix_fake_cred(struct rpc_task *task, uid_t uid, gid_t gid) +{ + struct unx_cred *cred; + + dprintk("RPC: allocating fake UNIX cred for uid %d gid %d\n", + uid, gid); + + if (!(cred = (struct unx_cred *) rpc_malloc(task, sizeof(*cred)))) + return NULL; + + cred->uc_count = 1; + cred->uc_flags = RPCAUTH_CRED_DEAD|RPCAUTH_CRED_UPTODATE; + cred->uc_uid = uid; + cred->uc_gid = gid; + cred->uc_fsuid = uid; + cred->uc_fsgid = gid; + cred->uc_gids[0] = (gid_t) NOGROUP; + + return task->tk_cred = (struct rpc_cred *) cred; +} + +static void +unx_destroy_cred(struct rpc_cred *cred) +{ + rpc_free(cred); +} + +/* + * 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 +unx_match(struct rpc_task * task, struct rpc_cred *rcred) +{ + struct unx_cred *cred = (struct unx_cred *) rcred; + int i; + + if (!RPC_DO_ROOTOVERRIDE(task)) { + if (cred->uc_uid != current->uid + || cred->uc_gid != current->gid + || cred->uc_fsuid != current->fsuid + || cred->uc_fsgid != current->fsgid) + return 0; + + for (i = 0; i < 16 && i < NGROUPS; i++) + if (cred->uc_gids[i] != (gid_t) current->groups[i]) + return 0; + return 1; + } + return (cred->uc_uid == 0 && cred->uc_fsuid == 0 + && cred->uc_gid == 0 && cred->uc_fsgid == 0 + && cred->uc_gids[0] == (gid_t) NOGROUP); +} + +/* + * Marshal credentials. + * Maybe we should keep a cached credential for performance reasons. + */ +static u32 * +unx_marshal(struct rpc_task *task, u32 *p, int ruid) +{ + struct unx_cred *cred = (struct unx_cred *) task->tk_cred; + u32 *base, *hold; + int i, n; + + *p++ = htonl(RPC_AUTH_UNIX); + base = p++; + *p++ = htonl(jiffies/HZ); +#ifndef DONT_FILLIN_HOSTNAME + if ((n = strlen((char *) system_utsname.nodename)) > UNX_MAXNODENAME) + n = UNX_MAXNODENAME; + *p++ = htonl(n); + memcpy(p, system_utsname.nodename, n); + p += (n + 3) >> 2; +#else + *p++ = 0; +#endif + if (ruid) { + *p++ = htonl((u32) cred->uc_uid); + *p++ = htonl((u32) cred->uc_gid); + } else { + *p++ = htonl((u32) cred->uc_fsuid); + *p++ = htonl((u32) cred->uc_fsgid); + } + 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) +{ + task->tk_cred->cr_flags |= RPCAUTH_CRED_UPTODATE; + return task->tk_status = -EACCES; +} + +static u32 * +unx_validate(struct rpc_task *task, u32 *p) +{ + u32 n = ntohl(*p++); + + if (n != RPC_AUTH_NULL && n != RPC_AUTH_UNIX && n != RPC_AUTH_SHORT) { + printk("RPC: bad verf flavor: %ld\n", (unsigned long) n); + return NULL; + } + if ((n = ntohl(*p++)) > 400) { + printk("RPC: giant verf size: %ld\n", (unsigned long) n); + return NULL; + } + task->tk_auth->au_rslack = (n >> 2) + 2; + p += (n >> 2); + + return p; +} + +struct rpc_authops authunix_ops = { + RPC_AUTH_UNIX, +#ifdef RPC_DEBUG + "UNIX", +#endif + unx_create, + unx_destroy, + unx_create_cred, + unx_destroy_cred, + unx_match, + unx_marshal, + unx_refresh, + unx_validate +}; |