40 #include <linux/slab.h>
41 #include <linux/types.h>
42 #include <linux/module.h>
55 # define RPCDBG_FACILITY RPCDBG_AUTH
66 static int netobj_equal(
struct xdr_netobj *
a,
struct xdr_netobj *
b)
68 return a->len == b->len && 0 ==
memcmp(a->data, b->data, a->len);
71 #define RSI_HASHBITS 6
72 #define RSI_HASHMAX (1<<RSI_HASHBITS)
84 static void rsi_free(
struct rsi *rsii)
86 kfree(rsii->in_handle.data);
88 kfree(rsii->out_handle.data);
92 static void rsi_put(
struct kref *ref)
99 static inline int rsi_hash(
struct rsi *
item)
101 return hash_mem(item->in_handle.data, item->in_handle.len,
RSI_HASHBITS)
109 return netobj_equal(&item->in_handle, &tmp->in_handle) &&
113 static int dup_to_netobj(
struct xdr_netobj *
dst,
char *
src,
int len)
117 if (len && !dst->data)
122 static inline int dup_netobj(
struct xdr_netobj *dst,
struct xdr_netobj *src)
124 return dup_to_netobj(dst, src->data, src->len);
132 new->out_handle.data =
NULL;
133 new->out_handle.len = 0;
134 new->out_token.data =
NULL;
135 new->out_token.len = 0;
136 new->in_handle.len = item->in_handle.len;
137 item->in_handle.len = 0;
140 new->in_handle.data = item->in_handle.data;
141 item->in_handle.data =
NULL;
142 new->in_token.data = item->
in_token.data;
151 BUG_ON(new->out_handle.data || new->out_token.data);
152 new->out_handle.len = item->out_handle.len;
153 item->out_handle.len = 0;
156 new->out_handle.data = item->out_handle.data;
157 item->out_handle.data =
NULL;
158 new->out_token.data = item->
out_token.data;
176 char **
bpp,
int *blen)
180 qword_addhex(bpp, blen, rsii->in_handle.data, rsii->in_handle.len);
192 char *mesg,
int mlen)
202 memset(&rsii, 0,
sizeof(rsii));
208 if (dup_to_netobj(&rsii.in_handle, buf, len))
217 if (dup_to_netobj(&rsii.
in_token, buf, len))
220 rsip = rsi_lookup(cd, &rsii);
226 expiry = get_expiry(&mesg);
250 if (dup_to_netobj(&rsii.out_handle, buf, len))
259 if (dup_to_netobj(&rsii.
out_token, buf, len))
261 rsii.
h.expiry_time = expiry;
262 rsip = rsi_update(cd, &rsii, rsip);
267 cache_put(&rsip->
h, cd);
276 .name =
"auth.rpcsec.init",
277 .cache_put = rsi_put,
278 .cache_upcall = rsi_upcall,
279 .cache_parse = rsi_parse,
282 .update = update_rsi,
289 int hash = rsi_hash(item);
301 int hash = rsi_hash(
new);
319 #define RSC_HASHBITS 10
320 #define RSC_HASHMAX (1<<RSC_HASHBITS)
322 #define GSS_SEQ_WIN 128
344 static void rsc_free(
struct rsc *rsci)
349 free_svc_cred(&rsci->
cred);
352 static void rsc_put(
struct kref *ref)
361 rsc_hash(
struct rsc *rsci)
372 return netobj_equal(&new->handle, &tmp->
handle);
381 new->handle.len = tmp->
handle.len;
383 new->handle.data = tmp->
handle.data;
386 new->cred.cr_group_info =
NULL;
387 new->cred.cr_principal =
NULL;
398 memset(&new->seqdata, 0,
sizeof(new->seqdata));
400 new->cred = tmp->
cred;
402 new->cred.cr_principal = tmp->
cred.cr_principal;
417 char *mesg,
int mlen)
425 struct gss_api_mech *gm =
NULL;
427 memset(&rsci, 0,
sizeof(rsci));
430 if (len < 0)
goto out;
432 if (dup_to_netobj(&rsci.
handle, buf, len))
437 expiry = get_expiry(&mesg);
442 rscp = rsc_lookup(cd, &rsci);
447 rv = get_int(&mesg, &rsci.
cred.cr_uid);
456 if (get_int(&mesg, &rsci.
cred.cr_gid))
460 if (get_int(&mesg, &N))
464 if (rsci.
cred.cr_group_info ==
NULL)
469 for (i=0; i<
N; i++) {
472 if (get_int(&mesg, &gid))
475 if (!gid_valid(kgid))
502 if (!rsci.
cred.cr_principal)
507 rsci.
h.expiry_time = expiry;
508 rscp = rsc_update(cd, &rsci, rscp);
514 cache_put(&rscp->
h, cd);
523 .name =
"auth.rpcsec.context",
524 .cache_put = rsc_put,
525 .cache_parse = rsc_parse,
528 .update = update_rsc,
535 int hash = rsc_hash(item);
547 int hash = rsc_hash(
new);
564 memset(&rsci, 0,
sizeof(rsci));
565 if (dup_to_netobj(&rsci.
handle, handle->data, handle->len))
567 found = rsc_lookup(cd, &rsci);
578 gss_check_seq_num(
struct rsc *rsci,
int seq_num)
583 if (seq_num > sd->
sd_max) {
587 }
else while (sd->
sd_max < seq_num) {
607 static inline u32 round_up_to_quad(
u32 i)
609 return (i + 3 ) & ~3;
613 svc_safe_getnetobj(
struct kvec *argv,
struct xdr_netobj *o)
619 o->len = svc_getnl(argv);
620 l = round_up_to_quad(o->len);
630 svc_safe_putnetobj(
struct kvec *
resv,
struct xdr_netobj *o)
636 svc_putnl(resv, o->len);
638 resv->
iov_len += round_up_to_quad(o->len);
641 memcpy(p, o->data, o->len);
642 memset(p + o->len, 0, round_up_to_quad(o->len) - o->len);
652 gss_verify_header(
struct svc_rqst *rqstp,
struct rsc *rsci,
656 struct xdr_buf rpchdr;
667 *authp = rpc_autherr_badverf;
670 flavor = svc_getnl(argv);
671 if (flavor != RPC_AUTH_GSS)
673 if (svc_safe_getnetobj(argv, &
checksum))
679 *authp = rpcsec_gsserr_credproblem;
683 if (gc->gc_seq > MAXSEQ) {
684 dprintk(
"RPC: svcauth_gss: discarding request with "
685 "large sequence number %d\n", gc->gc_seq);
686 *authp = rpcsec_gsserr_ctxproblem;
689 if (!gss_check_seq_num(rsci, gc->gc_seq)) {
690 dprintk(
"RPC: svcauth_gss: discarding request with "
691 "old sequence number %d\n", gc->gc_seq);
698 gss_write_null_verf(
struct svc_rqst *rqstp)
702 svc_putnl(rqstp->
rq_res.head, RPC_AUTH_NULL);
703 p = rqstp->
rq_res.head->iov_base + rqstp->
rq_res.head->iov_len;
706 if (!xdr_ressize_check(rqstp, p))
712 gss_write_verf(
struct svc_rqst *rqstp,
struct gss_ctx *ctx_id,
u32 seq)
716 struct xdr_buf verf_data;
717 struct xdr_netobj
mic;
721 svc_putnl(rqstp->
rq_res.head, RPC_AUTH_GSS);
722 xdr_seq =
htonl(seq);
724 iov.iov_base = &xdr_seq;
725 iov.iov_len =
sizeof(xdr_seq);
727 p = rqstp->
rq_res.head->iov_base + rqstp->
rq_res.head->iov_len;
728 mic.data = (
u8 *)(p + 1);
730 if (maj_stat != GSS_S_COMPLETE)
734 p += XDR_QUADLEN(
mic.len);
735 if (!xdr_ressize_check(rqstp, p))
741 struct auth_domain
h;
745 static struct auth_domain *
746 find_gss_auth_domain(
struct gss_ctx *
ctx,
u32 svc)
756 static struct auth_ops svcauthops_gss;
771 struct auth_domain *
test;
777 kref_init(&new->h.ref);
781 new->h.flavour = &svcauthops_gss;
782 new->pseudoflavor = pseudoflavor;
786 if (test != &new->h) {
802 read_u32_from_xdr_buf(
struct xdr_buf *buf,
int base,
u32 *obj)
820 unwrap_integ_data(
struct xdr_buf *buf,
u32 seq,
struct gss_ctx *
ctx)
823 u32 integ_len, maj_stat;
824 struct xdr_netobj
mic;
825 struct xdr_buf integ_buf;
827 integ_len = svc_getnl(&buf->head[0]);
830 if (integ_len > buf->len)
835 if (read_u32_from_xdr_buf(buf, integ_len, &
mic.len))
837 if (
mic.len > RPC_MAX_AUTH_SIZE)
845 if (maj_stat != GSS_S_COMPLETE)
847 if (svc_getnl(&buf->head[0]) != seq)
856 total_buf_len(
struct xdr_buf *buf)
858 return buf->head[0].iov_len + buf->page_len + buf->tail[0].iov_len;
862 fix_priv_head(
struct xdr_buf *buf,
int pad)
864 if (buf->page_len == 0) {
868 buf->head[0].iov_len -=
pad;
873 unwrap_priv_data(
struct svc_rqst *rqstp,
struct xdr_buf *buf,
u32 seq,
struct gss_ctx *ctx)
875 u32 priv_len, maj_stat;
876 int pad, saved_len, remaining_len,
offset;
880 priv_len = svc_getnl(&buf->head[0]);
889 remaining_len = total_buf_len(buf);
890 if (priv_len > remaining_len)
892 pad = remaining_len - priv_len;
894 fix_priv_head(buf, pad);
897 saved_len = buf->len;
900 pad = priv_len - buf->len;
901 buf->len = saved_len;
909 offset = buf->head[0].iov_len % 4;
913 fix_priv_head(buf, pad);
915 if (maj_stat != GSS_S_COMPLETE)
918 if (svc_getnl(&buf->head[0]) != seq)
933 svcauth_gss_set_client(
struct svc_rqst *rqstp)
936 struct rsc *rsci = svcdata->
rsci;
937 struct rpc_gss_wire_cred *gc = &svcdata->
clcred;
953 if (stat == SVC_DROP || stat == SVC_CLOSE)
960 struct xdr_netobj *out_handle,
int *major_status)
965 if (*major_status != GSS_S_COMPLETE)
966 return gss_write_null_verf(rqstp);
967 rsci = gss_svc_searchbyctx(cd, out_handle);
969 *major_status = GSS_S_NO_CONTEXT;
970 return gss_write_null_verf(rqstp);
973 cache_put(&rsci->
h, cd);
978 gss_read_verf(
struct rpc_gss_wire_cred *gc,
980 struct xdr_netobj *in_handle,
981 struct xdr_netobj *in_token)
983 struct xdr_netobj tmpobj;
986 *authp = rpc_autherr_badverf;
989 if (svc_getnl(argv) != RPC_AUTH_NULL)
991 if (svc_getnl(argv) != 0)
994 *authp = rpc_autherr_badcred;
995 if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0)
997 if (dup_netobj(in_handle, &gc->gc_ctx))
999 *authp = rpc_autherr_badverf;
1000 if (svc_safe_getnetobj(argv, &tmpobj)) {
1001 kfree(in_handle->data);
1004 if (dup_netobj(in_token, &tmpobj)) {
1005 kfree(in_handle->data);
1013 gss_write_resv(
struct kvec *resv,
size_t size_limit,
1014 struct xdr_netobj *out_handle,
struct xdr_netobj *out_token,
1015 int major_status,
int minor_status)
1017 if (resv->
iov_len + 4 > size_limit)
1019 svc_putnl(resv, RPC_SUCCESS);
1020 if (svc_safe_putnetobj(resv, out_handle))
1022 if (resv->
iov_len + 3 * 4 > size_limit)
1024 svc_putnl(resv, major_status);
1025 svc_putnl(resv, minor_status);
1027 if (svc_safe_putnetobj(resv, out_token))
1039 static int svcauth_gss_handle_init(
struct svc_rqst *rqstp,
1040 struct rpc_gss_wire_cred *gc,
__be32 *authp)
1044 struct rsi *rsip, rsikey;
1048 memset(&rsikey, 0,
sizeof(rsikey));
1049 ret = gss_read_verf(gc, argv, authp,
1050 &rsikey.in_handle, &rsikey.
in_token);
1055 rsip = rsi_lookup(sn->
rsi_cache, &rsikey);
1065 if (gss_write_init_verf(sn->
rsc_cache, rqstp,
1094 struct rpc_gss_wire_cred *gc;
1101 dprintk(
"RPC: svcauth_gss: argv->iov_len = %zd\n",
1104 *authp = rpc_autherr_badcred;
1127 crlen = svc_getnl(argv);
1128 if (svc_getnl(argv) != RPC_GSS_VERSION)
1130 gc->gc_proc = svc_getnl(argv);
1131 gc->gc_seq = svc_getnl(argv);
1132 gc->gc_svc = svc_getnl(argv);
1133 if (svc_safe_getnetobj(argv, &gc->gc_ctx))
1135 if (crlen != round_up_to_quad(gc->gc_ctx.len) + 5 * 4)
1138 if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->
rq_proc != 0))
1141 *authp = rpc_autherr_badverf;
1142 switch (gc->gc_proc) {
1143 case RPC_GSS_PROC_INIT:
1144 case RPC_GSS_PROC_CONTINUE_INIT:
1145 return svcauth_gss_handle_init(rqstp, gc, authp);
1146 case RPC_GSS_PROC_DATA:
1147 case RPC_GSS_PROC_DESTROY:
1149 *authp = rpcsec_gsserr_credproblem;
1150 rsci = gss_svc_searchbyctx(sn->
rsc_cache, &gc->gc_ctx);
1153 switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) {
1163 *authp = rpc_autherr_rejectedcred;
1168 switch (gc->gc_proc) {
1169 case RPC_GSS_PROC_DESTROY:
1170 if (gss_write_verf(rqstp, rsci->
mechctx, gc->gc_seq))
1176 svc_putnl(resv, RPC_SUCCESS);
1178 case RPC_GSS_PROC_DATA:
1179 *authp = rpcsec_gsserr_ctxproblem;
1181 if (gss_write_verf(rqstp, rsci->
mechctx, gc->gc_seq))
1184 get_group_info(rsci->
cred.cr_group_info);
1185 *authp = rpc_autherr_badcred;
1186 switch (gc->gc_svc) {
1187 case RPC_GSS_SVC_NONE:
1189 case RPC_GSS_SVC_INTEGRITY:
1193 if (unwrap_integ_data(&rqstp->
rq_arg,
1197 case RPC_GSS_SVC_PRIVACY:
1201 if (unwrap_priv_data(rqstp, &rqstp->
rq_arg,
1208 svcdata->
rsci = rsci;
1209 cache_get(&rsci->
h);
1211 rsci->
mechctx->mech_type, gc->gc_svc);
1220 xdr_ressize_check(rqstp, reject_stat);
1235 svcauth_gss_prepare_to_wrap(
struct xdr_buf *resbuf,
struct gss_svc_data *gsd)
1244 if (*(p-1) != rpc_success)
1248 verf_len =
ntohl(*p++);
1249 p += XDR_QUADLEN(verf_len);
1253 if (*p != rpc_success) {
1254 resbuf->head[0].iov_len -= 2 * 4;
1262 svcauth_gss_wrap_resp_integ(
struct svc_rqst *rqstp)
1265 struct rpc_gss_wire_cred *gc = &gsd->
clcred;
1266 struct xdr_buf *resbuf = &rqstp->
rq_res;
1267 struct xdr_buf integ_buf;
1268 struct xdr_netobj
mic;
1271 int integ_offset, integ_len;
1274 p = svcauth_gss_prepare_to_wrap(resbuf, gsd);
1277 integ_offset = (
u8 *)(p + 1) - (
u8 *)resbuf->head[0].iov_base;
1278 integ_len = resbuf->len - integ_offset;
1280 *p++ =
htonl(integ_len);
1281 *p++ =
htonl(gc->gc_seq);
1285 if (resbuf->tail[0].iov_base ==
NULL) {
1286 if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE >
PAGE_SIZE)
1288 resbuf->tail[0].iov_base = resbuf->head[0].iov_base
1289 + resbuf->head[0].iov_len;
1290 resbuf->tail[0].iov_len = 0;
1291 resv = &resbuf->tail[0];
1293 resv = &resbuf->tail[0];
1298 svc_putnl(resv,
mic.len);
1300 round_up_to_quad(
mic.len) -
mic.len);
1303 resbuf->len += XDR_QUADLEN(
mic.len) << 2;
1312 svcauth_gss_wrap_resp_priv(
struct svc_rqst *rqstp)
1315 struct rpc_gss_wire_cred *gc = &gsd->
clcred;
1316 struct xdr_buf *resbuf = &rqstp->
rq_res;
1322 p = svcauth_gss_prepare_to_wrap(resbuf, gsd);
1326 offset = (
u8 *)p - (
u8 *)resbuf->head[0].iov_base;
1327 *p++ =
htonl(gc->gc_seq);
1328 inpages = resbuf->pages;
1339 if (resbuf->tail[0].iov_base) {
1340 BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base
1342 BUG_ON(resbuf->tail[0].iov_base < resbuf->head[0].iov_base);
1343 if (resbuf->tail[0].iov_len + resbuf->head[0].iov_len
1346 memmove(resbuf->tail[0].iov_base + RPC_MAX_AUTH_SIZE,
1347 resbuf->tail[0].iov_base,
1348 resbuf->tail[0].iov_len);
1349 resbuf->tail[0].iov_base += RPC_MAX_AUTH_SIZE;
1358 if (resbuf->tail[0].iov_base ==
NULL) {
1359 if (resbuf->head[0].iov_len + 2*RPC_MAX_AUTH_SIZE >
PAGE_SIZE)
1361 resbuf->tail[0].iov_base = resbuf->head[0].iov_base
1362 + resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE;
1363 resbuf->tail[0].iov_len = 0;
1365 if (
gss_wrap(gsd->
rsci->mechctx, offset, resbuf, inpages))
1367 *len =
htonl(resbuf->len - offset);
1368 pad = 3 - ((resbuf->len - offset - 1)&3);
1369 p = (
__be32 *)(resbuf->tail[0].iov_base + resbuf->tail[0].iov_len);
1371 resbuf->tail[0].iov_len +=
pad;
1377 svcauth_gss_release(
struct svc_rqst *rqstp)
1380 struct rpc_gss_wire_cred *gc = &gsd->
clcred;
1381 struct xdr_buf *resbuf = &rqstp->
rq_res;
1385 if (gc->gc_proc != RPC_GSS_PROC_DATA)
1393 resbuf->len = total_buf_len(resbuf);
1394 switch (gc->gc_svc) {
1395 case RPC_GSS_SVC_NONE:
1397 case RPC_GSS_SVC_INTEGRITY:
1398 stat = svcauth_gss_wrap_resp_integ(rqstp);
1402 case RPC_GSS_SVC_PRIVACY:
1403 stat = svcauth_gss_wrap_resp_priv(rqstp);
1422 if (rqstp->
rq_cred.cr_group_info)
1433 svcauth_gss_domain_release(
struct auth_domain *dom)
1441 static struct auth_ops svcauthops_gss = {
1442 .name =
"rpcsec_gss",
1444 .flavour = RPC_AUTH_GSS,
1445 .accept = svcauth_gss_accept,
1446 .release = svcauth_gss_release,
1447 .domain_release = svcauth_gss_domain_release,
1448 .set_client = svcauth_gss_set_client,
1451 static int rsi_cache_create_net(
struct net *
net)
1469 static void rsi_cache_destroy_net(
struct net *net)
1480 static int rsc_cache_create_net(
struct net *net)
1498 static void rsc_cache_destroy_net(
struct net *net)
1514 rv = rsc_cache_create_net(net);
1517 rv = rsi_cache_create_net(net);
1522 rsc_cache_destroy_net(net);
1529 rsi_cache_destroy_net(net);
1530 rsc_cache_destroy_net(net);