static int gssx_dec_option(struct xdr_stream *xdr, struct gssx_option *opt) { int err; err = gssx_dec_buffer(xdr, &opt->option); if (err) return err; err = gssx_dec_buffer(xdr, &opt->value); return err; }
int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, struct xdr_stream *xdr, void *data) { struct gssx_res_accept_sec_context *res = data; u32 value_follows; int err; struct page *scratch; scratch = alloc_page(GFP_KERNEL); if (!scratch) return -ENOMEM; xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE); /* res->status */ err = gssx_dec_status(xdr, &res->status); if (err) goto out_free; /* res->context_handle */ err = gssx_dec_bool(xdr, &value_follows); if (err) goto out_free; if (value_follows) { err = gssx_dec_ctx(xdr, res->context_handle); if (err) goto out_free; } else { res->context_handle = NULL; } /* res->output_token */ err = gssx_dec_bool(xdr, &value_follows); if (err) goto out_free; if (value_follows) { err = gssx_dec_buffer(xdr, res->output_token); if (err) goto out_free; } else { res->output_token = NULL; } /* res->delegated_cred_handle */ err = gssx_dec_bool(xdr, &value_follows); if (err) goto out_free; if (value_follows) { /* we do not support upcall servers sending this data. */ err = -EINVAL; goto out_free; } /* res->options */ err = gssx_dec_option_array(xdr, &res->options); out_free: __free_page(scratch); return err; }
static int gssx_dec_status(struct xdr_stream *xdr, struct gssx_status *status) { __be32 *p; int err; /* status->major_status */ p = xdr_inline_decode(xdr, 8); if (unlikely(p == NULL)) return -ENOSPC; p = xdr_decode_hyper(p, &status->major_status); /* status->mech */ err = gssx_dec_buffer(xdr, &status->mech); if (err) return err; /* status->minor_status */ p = xdr_inline_decode(xdr, 8); if (unlikely(p == NULL)) return -ENOSPC; p = xdr_decode_hyper(p, &status->minor_status); /* status->major_status_string */ err = gssx_dec_buffer(xdr, &status->major_status_string); if (err) return err; /* status->minor_status_string */ err = gssx_dec_buffer(xdr, &status->minor_status_string); if (err) return err; /* status->server_ctx */ err = gssx_dec_buffer(xdr, &status->server_ctx); if (err) return err; /* we assume we have no options for now, so simply consume them */ /* status->options */ err = dummy_dec_opt_array(xdr, &status->options); return err; }
static int gssx_dec_name_attr(struct xdr_stream *xdr, struct gssx_name_attr *attr) { int err; /* attr->attr */ err = gssx_dec_buffer(xdr, &attr->attr); if (err) return err; /* attr->value */ err = gssx_dec_buffer(xdr, &attr->value); if (err) return err; /* attr->extensions */ err = dummy_dec_opt_array(xdr, &attr->extensions); return err; }
int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, struct xdr_stream *xdr, struct gssx_res_accept_sec_context *res) { u32 value_follows; int err; /* res->status */ err = gssx_dec_status(xdr, &res->status); if (err) return err; /* res->context_handle */ err = gssx_dec_bool(xdr, &value_follows); if (err) return err; if (value_follows) { err = gssx_dec_ctx(xdr, res->context_handle); if (err) return err; } else { res->context_handle = NULL; } /* res->output_token */ err = gssx_dec_bool(xdr, &value_follows); if (err) return err; if (value_follows) { err = gssx_dec_buffer(xdr, res->output_token); if (err) return err; } else { res->output_token = NULL; } /* res->delegated_cred_handle */ err = gssx_dec_bool(xdr, &value_follows); if (err) return err; if (value_follows) { /* we do not support upcall servers sending this data. */ return -EINVAL; } /* res->options */ err = gssx_dec_option_array(xdr, &res->options); return err; }
static int gssx_dec_ctx(struct xdr_stream *xdr, struct gssx_ctx *ctx) { __be32 *p; int err; /* ctx->exported_context_token */ err = gssx_dec_buffer(xdr, &ctx->exported_context_token); if (err) return err; /* ctx->state */ err = gssx_dec_buffer(xdr, &ctx->state); if (err) return err; /* ctx->need_release */ err = gssx_dec_bool(xdr, &ctx->need_release); if (err) return err; /* ctx->mech */ err = gssx_dec_buffer(xdr, &ctx->mech); if (err) return err; /* ctx->src_name */ err = gssx_dec_name(xdr, &ctx->src_name); if (err) return err; /* ctx->targ_name */ err = gssx_dec_name(xdr, &ctx->targ_name); if (err) return err; /* ctx->lifetime */ p = xdr_inline_decode(xdr, 8+8); if (unlikely(p == NULL)) return -ENOSPC; p = xdr_decode_hyper(p, &ctx->lifetime); /* ctx->ctx_flags */ p = xdr_decode_hyper(p, &ctx->ctx_flags); /* ctx->locally_initiated */ err = gssx_dec_bool(xdr, &ctx->locally_initiated); if (err) return err; /* ctx->open */ err = gssx_dec_bool(xdr, &ctx->open); if (err) return err; /* we assume we have no options for now, so simply consume them */ /* ctx->options */ err = dummy_dec_opt_array(xdr, &ctx->options); return err; }
static int gssx_dec_name(struct xdr_stream *xdr, struct gssx_name *name) { struct xdr_netobj dummy_netobj = { .len = 0 }; struct gssx_name_attr_array dummy_name_attr_array = { .count = 0 }; struct gssx_option_array dummy_option_array = { .count = 0 }; int err; /* name->display_name */ err = gssx_dec_buffer(xdr, &name->display_name); if (err) return err; /* name->name_type */ err = gssx_dec_buffer(xdr, &dummy_netobj); if (err) return err; /* name->exported_name */ err = gssx_dec_buffer(xdr, &dummy_netobj); if (err) return err; /* name->exported_composite_name */ err = gssx_dec_buffer(xdr, &dummy_netobj); if (err) return err; /* we assume we have no attributes for now, so simply consume them */ /* name->name_attributes */ err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array); if (err) return err; /* we assume we have no options for now, so simply consume them */ /* name->extensions */ err = dummy_dec_opt_array(xdr, &dummy_option_array); return err; } static int dummy_enc_credel_array(struct xdr_stream *xdr, struct gssx_cred_element_array *cea) { __be32 *p; if (cea->count != 0) return -EINVAL; p = xdr_reserve_space(xdr, 4); if (!p) return -ENOSPC; *p = 0; return 0; } static int gssx_enc_cred(struct xdr_stream *xdr, struct gssx_cred *cred) { int err; /* cred->desired_name */ err = gssx_enc_name(xdr, &cred->desired_name); if (err) return err; /* cred->elements */ err = dummy_enc_credel_array(xdr, &cred->elements); if (err) return err; /* cred->cred_handle_reference */ err = gssx_enc_buffer(xdr, &cred->cred_handle_reference); if (err) return err; /* cred->needs_release */ err = gssx_enc_bool(xdr, cred->needs_release); return err; } static int gssx_enc_ctx(struct xdr_stream *xdr, struct gssx_ctx *ctx) { __be32 *p; int err; /* ctx->exported_context_token */ err = gssx_enc_buffer(xdr, &ctx->exported_context_token); if (err) return err; /* ctx->state */ err = gssx_enc_buffer(xdr, &ctx->state); if (err) return err; /* ctx->need_release */ err = gssx_enc_bool(xdr, ctx->need_release); if (err) return err; /* ctx->mech */ err = gssx_enc_buffer(xdr, &ctx->mech); if (err) return err; /* ctx->src_name */ err = gssx_enc_name(xdr, &ctx->src_name); if (err) return err; /* ctx->targ_name */ err = gssx_enc_name(xdr, &ctx->targ_name); if (err) return err; /* ctx->lifetime */ p = xdr_reserve_space(xdr, 8+8); if (!p) return -ENOSPC; p = xdr_encode_hyper(p, ctx->lifetime); /* ctx->ctx_flags */ p = xdr_encode_hyper(p, ctx->ctx_flags); /* ctx->locally_initiated */ err = gssx_enc_bool(xdr, ctx->locally_initiated); if (err) return err; /* ctx->open */ err = gssx_enc_bool(xdr, ctx->open); if (err) return err; /* leave options empty for now, will add once we have any options * to pass up at all */ /* ctx->options */ err = dummy_enc_opt_array(xdr, &ctx->options); return err; }
static int gssx_dec_option_array(struct xdr_stream *xdr, struct gssx_option_array *oa) { struct svc_cred *creds; u32 count, i; __be32 *p; int err; p = xdr_inline_decode(xdr, 4); if (unlikely(p == NULL)) return -ENOSPC; count = be32_to_cpup(p++); if (!count) return 0; /* we recognize only 1 currently: CREDS_VALUE */ oa->count = 1; oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL); if (!oa->data) return -ENOMEM; creds = kzalloc(sizeof(struct svc_cred), GFP_KERNEL); if (!creds) { kfree(oa->data); return -ENOMEM; } oa->data[0].option.data = CREDS_VALUE; oa->data[0].option.len = sizeof(CREDS_VALUE); oa->data[0].value.data = (void *)creds; oa->data[0].value.len = 0; for (i = 0; i < count; i++) { gssx_buffer dummy = { 0, NULL }; u32 length; /* option buffer */ p = xdr_inline_decode(xdr, 4); if (unlikely(p == NULL)) return -ENOSPC; length = be32_to_cpup(p); p = xdr_inline_decode(xdr, length); if (unlikely(p == NULL)) return -ENOSPC; if (length == sizeof(CREDS_VALUE) && memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) { /* We have creds here. parse them */ err = gssx_dec_linux_creds(xdr, creds); if (err) return err; oa->data[0].value.len = 1; /* presence */ } else { /* consume uninteresting buffer */ err = gssx_dec_buffer(xdr, &dummy); if (err) return err; } } return 0; }