Viewing file: svcauth.c (3.55 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/* * linux/net/sunrpc/svcauth.c * * The generic interface for RPC authentication on the server side. * * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> * * CHANGES * 19-Apr-2000 Chris Evans - Security fix */
#include <linux/types.h> #include <linux/sched.h> #include <linux/sunrpc/types.h> #include <linux/sunrpc/xdr.h> #include <linux/sunrpc/svcauth.h> #include <linux/sunrpc/svcsock.h>
#define RPCDBG_FACILITY RPCDBG_AUTH
/* * Type of authenticator function */ typedef void (*auth_fn_t)(struct svc_rqst *rqstp, u32 *statp, u32 *authp);
/* * Builtin auth flavors */ static void svcauth_null(struct svc_rqst *rqstp, u32 *statp, u32 *authp); static void svcauth_unix(struct svc_rqst *rqstp, u32 *statp, u32 *authp);
/* * Max number of authentication flavors we support */ #define RPC_SVCAUTH_MAX 8
/* * Table of authenticators */ static auth_fn_t authtab[RPC_SVCAUTH_MAX] = { svcauth_null, svcauth_unix, NULL, };
void svc_authenticate(struct svc_rqst *rqstp, u32 *statp, u32 *authp) { u32 flavor; auth_fn_t func;
*statp = rpc_success; *authp = rpc_auth_ok;
svc_getlong(&rqstp->rq_argbuf, flavor); flavor = ntohl(flavor);
dprintk("svc: svc_authenticate (%d)\n", flavor); if (flavor >= RPC_SVCAUTH_MAX || !(func = authtab[flavor])) { *authp = rpc_autherr_badcred; return; }
rqstp->rq_cred.cr_flavor = flavor; func(rqstp, statp, authp); }
int svc_auth_register(u32 flavor, auth_fn_t func) { if (flavor >= RPC_SVCAUTH_MAX || authtab[flavor]) return -EINVAL; authtab[flavor] = func; return 0; }
void svc_auth_unregister(u32 flavor) { if (flavor < RPC_SVCAUTH_MAX) authtab[flavor] = NULL; }
static void svcauth_null(struct svc_rqst *rqstp, u32 *statp, u32 *authp) { struct svc_buf *argp = &rqstp->rq_argbuf; struct svc_buf *resp = &rqstp->rq_resbuf;
if ((argp->len -= 3) < 0) { *statp = rpc_garbage_args; return; } if (*(argp->buf)++ != 0) { /* we already skipped the flavor */ dprintk("svc: bad null cred\n"); *authp = rpc_autherr_badcred; return; } if (*(argp->buf)++ != RPC_AUTH_NULL || *(argp->buf)++ != 0) { dprintk("svc: bad null verf\n"); *authp = rpc_autherr_badverf; return; }
/* Signal that mapping to nobody uid/gid is required */ rqstp->rq_cred.cr_uid = (uid_t) -1; rqstp->rq_cred.cr_gid = (gid_t) -1; rqstp->rq_cred.cr_groups[0] = NOGROUP;
/* Put NULL verifier */ rqstp->rq_verfed = 1; svc_putlong(resp, RPC_AUTH_NULL); svc_putlong(resp, 0); }
static void svcauth_unix(struct svc_rqst *rqstp, u32 *statp, u32 *authp) { struct svc_buf *argp = &rqstp->rq_argbuf; struct svc_buf *resp = &rqstp->rq_resbuf; struct svc_cred *cred = &rqstp->rq_cred; u32 *bufp = argp->buf, slen, i; int len = argp->len;
if ((len -= 3) < 0) { *statp = rpc_garbage_args; return; }
bufp++; /* length */ bufp++; /* time stamp */ slen = (ntohl(*bufp++) + 3) >> 2; /* machname length */ if (slen > 64 || (len -= slen + 3) < 0) goto badcred; bufp += slen; /* skip machname */
cred->cr_uid = ntohl(*bufp++); /* uid */ cred->cr_gid = ntohl(*bufp++); /* gid */
slen = ntohl(*bufp++); /* gids length */ if (slen > 16 || (len -= slen + 2) < 0) goto badcred; for (i = 0; i < NGROUPS && i < slen; i++) cred->cr_groups[i] = ntohl(*bufp++); if (i < NGROUPS) cred->cr_groups[i] = NOGROUP; bufp += (slen - i);
if (*bufp++ != RPC_AUTH_NULL || *bufp++ != 0) { *authp = rpc_autherr_badverf; return; }
argp->buf = bufp; argp->len = len;
/* Put NULL verifier */ rqstp->rq_verfed = 1; svc_putlong(resp, RPC_AUTH_NULL); svc_putlong(resp, 0);
return;
badcred: *authp = rpc_autherr_badcred; }
|