more debug output
[linux-2.4.git] / net / sunrpc / svcauth.c
1 /*
2  * linux/net/sunrpc/svcauth.c
3  *
4  * The generic interface for RPC authentication on the server side.
5  * 
6  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7  *
8  * CHANGES
9  * 19-Apr-2000 Chris Evans      - Security fix
10  */
11
12 #include <linux/types.h>
13 #include <linux/sched.h>
14 #include <linux/sunrpc/types.h>
15 #include <linux/sunrpc/xdr.h>
16 #include <linux/sunrpc/svcauth.h>
17 #include <linux/sunrpc/svcsock.h>
18
19 #define RPCDBG_FACILITY RPCDBG_AUTH
20
21 /*
22  * Type of authenticator function
23  */
24 typedef void    (*auth_fn_t)(struct svc_rqst *rqstp, u32 *statp, u32 *authp);
25
26 /*
27  * Builtin auth flavors
28  */
29 static void     svcauth_null(struct svc_rqst *rqstp, u32 *statp, u32 *authp);
30 static void     svcauth_unix(struct svc_rqst *rqstp, u32 *statp, u32 *authp);
31
32 /*
33  * Max number of authentication flavors we support
34  */
35 #define RPC_SVCAUTH_MAX 8
36
37 /*
38  * Table of authenticators
39  */
40 static auth_fn_t        authtab[RPC_SVCAUTH_MAX] = {
41         svcauth_null,
42         svcauth_unix,
43         NULL,
44 };
45
46 void
47 svc_authenticate(struct svc_rqst *rqstp, u32 *statp, u32 *authp)
48 {
49         u32             flavor;
50         auth_fn_t       func;
51
52         *statp = rpc_success;
53         *authp = rpc_auth_ok;
54
55         svc_getlong(&rqstp->rq_argbuf, flavor);
56         flavor = ntohl(flavor);
57
58         dprintk("svc: svc_authenticate (%d)\n", flavor);
59         if (flavor >= RPC_SVCAUTH_MAX || !(func = authtab[flavor])) {
60                 *authp = rpc_autherr_badcred;
61                 return;
62         }
63
64         rqstp->rq_cred.cr_flavor = flavor;
65         func(rqstp, statp, authp);
66 }
67
68 int
69 svc_auth_register(u32 flavor, auth_fn_t func)
70 {
71         if (flavor >= RPC_SVCAUTH_MAX || authtab[flavor])
72                 return -EINVAL;
73         authtab[flavor] = func;
74         return 0;
75 }
76
77 void
78 svc_auth_unregister(u32 flavor)
79 {
80         if (flavor < RPC_SVCAUTH_MAX)
81                 authtab[flavor] = NULL;
82 }
83
84 static void
85 svcauth_null(struct svc_rqst *rqstp, u32 *statp, u32 *authp)
86 {
87         struct svc_buf  *argp = &rqstp->rq_argbuf;
88         struct svc_buf  *resp = &rqstp->rq_resbuf;
89
90         if ((argp->len -= 3) < 0) {
91                 *statp = rpc_garbage_args;
92                 return;
93         }
94         if (*(argp->buf)++ != 0) {      /* we already skipped the flavor */
95                 dprintk("svc: bad null cred\n");
96                 *authp = rpc_autherr_badcred;
97                 return;
98         }
99         if (*(argp->buf)++ != RPC_AUTH_NULL || *(argp->buf)++ != 0) {
100                 dprintk("svc: bad null verf\n");
101                 *authp = rpc_autherr_badverf;
102                 return;
103         }
104
105         /* Signal that mapping to nobody uid/gid is required */
106         rqstp->rq_cred.cr_uid = (uid_t) -1;
107         rqstp->rq_cred.cr_gid = (gid_t) -1;
108         rqstp->rq_cred.cr_groups[0] = NOGROUP;
109
110         /* Put NULL verifier */
111         rqstp->rq_verfed = 1;
112         svc_putlong(resp, RPC_AUTH_NULL);
113         svc_putlong(resp, 0);
114 }
115
116 static void
117 svcauth_unix(struct svc_rqst *rqstp, u32 *statp, u32 *authp)
118 {
119         struct svc_buf  *argp = &rqstp->rq_argbuf;
120         struct svc_buf  *resp = &rqstp->rq_resbuf;
121         struct svc_cred *cred = &rqstp->rq_cred;
122         u32             *bufp = argp->buf, slen, i;
123         int             len   = argp->len;
124
125         if ((len -= 3) < 0) {
126                 *statp = rpc_garbage_args;
127                 return;
128         }
129
130         bufp++;                                 /* length */
131         bufp++;                                 /* time stamp */
132         slen = (ntohl(*bufp++) + 3) >> 2;       /* machname length */
133         if (slen > 64 || (len -= slen + 3) < 0)
134                 goto badcred;
135         bufp += slen;                           /* skip machname */
136
137         cred->cr_uid = ntohl(*bufp++);          /* uid */
138         cred->cr_gid = ntohl(*bufp++);          /* gid */
139
140         slen = ntohl(*bufp++);                  /* gids length */
141         if (slen > 16 || (len -= slen + 2) < 0)
142                 goto badcred;
143         for (i = 0; i < NGROUPS && i < slen; i++)
144                 cred->cr_groups[i] = ntohl(*bufp++);
145         if (i < NGROUPS)
146                 cred->cr_groups[i] = NOGROUP;
147         bufp += (slen - i);
148
149         if (*bufp++ != RPC_AUTH_NULL || *bufp++ != 0) {
150                 *authp = rpc_autherr_badverf;
151                 return;
152         }
153
154         argp->buf = bufp;
155         argp->len = len;
156
157         /* Put NULL verifier */
158         rqstp->rq_verfed = 1;
159         svc_putlong(resp, RPC_AUTH_NULL);
160         svc_putlong(resp, 0);
161
162         return;
163
164 badcred:
165         *authp = rpc_autherr_badcred;
166 }