diff options
author | Simo Sorce <simo@redhat.com> | 2012-01-19 14:49:22 -0500 |
---|---|---|
committer | Simo Sorce <simo@redhat.com> | 2012-01-20 00:38:16 -0500 |
commit | 8e4d1ddfcd496a38aa5ea07b2d0d60f2833a98fa (patch) | |
tree | ded0026d15463ea8af68552cb16a57c39db23d69 | |
parent | 81090c3159fed8efd2184ebb7d0d9acf3c2914ff (diff) | |
download | gss-proxy-8e4d1ddfcd496a38aa5ea07b2d0d60f2833a98fa.tar.gz gss-proxy-8e4d1ddfcd496a38aa5ea07b2d0d60f2833a98fa.tar.xz gss-proxy-8e4d1ddfcd496a38aa5ea07b2d0d60f2833a98fa.zip |
Add rpc processing infrastructure
-rw-r--r-- | proxy/Makefile.am | 1 | ||||
-rw-r--r-- | proxy/src/gp_rpc_process.c | 413 | ||||
-rw-r--r-- | proxy/src/gp_rpc_process.h | 107 | ||||
-rw-r--r-- | proxy/src/gp_socket.c | 3 | ||||
-rw-r--r-- | proxy/src/gp_utils.h | 8 | ||||
-rw-r--r-- | proxy/src/gp_workers.c | 19 |
6 files changed, 543 insertions, 8 deletions
diff --git a/proxy/Makefile.am b/proxy/Makefile.am index 37ef362..0728c6d 100644 --- a/proxy/Makefile.am +++ b/proxy/Makefile.am @@ -90,6 +90,7 @@ gssproxy_SOURCES = \ src/gp_socket.c \ src/gp_workers.c \ $(GP_RPCGEN_OBJ) \ + src/gp_rpc_process.c \ src/gssproxy.c gssproxy_LDADD = \ diff --git a/proxy/src/gp_rpc_process.c b/proxy/src/gp_rpc_process.c new file mode 100644 index 0000000..f93b69d --- /dev/null +++ b/proxy/src/gp_rpc_process.c @@ -0,0 +1,413 @@ +/* + GSS-PROXY + + Copyright (C) 2011 Red Hat, Inc. + Copyright (C) 2011 Simo Sorce <simo.sorce@redhat.com> + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#include "config.h" +#include <stdint.h> +#include <errno.h> +#include "gp_utils.h" +#include "gp_rpc_process.h" + +struct gp_rpc_fn_set gp_xdr_set[] = { + { /* NULLPROC */ + (xdrproc_t)xdr_void, + (xdrproc_t)xdr_void, + NULL + }, + { /* GSSX_INDICATE_MECHS */ + (xdrproc_t)xdr_gssx_arg_indicate_mechs, + (xdrproc_t)xdr_gssx_res_indicate_mechs, + gp_indicate_mechs + }, + { /* GSSX_GET_CALL_CONTEXT */ + (xdrproc_t)xdr_gssx_arg_get_call_context, + (xdrproc_t)xdr_gssx_res_get_call_context, + gp_get_call_context + }, + { /* GSSX_IMPORT_AND_CANON_NAME */ + (xdrproc_t)xdr_gssx_arg_import_and_canon_name, + (xdrproc_t)xdr_gssx_res_import_and_canon_name, + gp_import_and_canon_name + }, + { /* GSSX_EXPORT_CRED */ + (xdrproc_t)xdr_gssx_arg_export_cred, + (xdrproc_t)xdr_gssx_res_export_cred, + gp_export_cred + }, + { /* GSSX_IMPORT_CRED */ + (xdrproc_t)xdr_gssx_arg_import_cred, + (xdrproc_t)xdr_gssx_res_import_cred, + gp_import_cred + }, + { /* GSSX_ACQUIRE_CRED */ + (xdrproc_t)xdr_gssx_arg_acquire_cred, + (xdrproc_t)xdr_gssx_res_acquire_cred, + gp_acquire_cred + }, + { /* GSSX_STORE_CRED */ + (xdrproc_t)xdr_gssx_arg_store_cred, + (xdrproc_t)xdr_gssx_res_store_cred, + gp_store_cred + }, + { /* GSSX_INIT_SEC_CONTEXT */ + (xdrproc_t)xdr_gssx_arg_init_sec_context, + (xdrproc_t)xdr_gssx_res_init_sec_context, + gp_init_sec_context + }, + { /* GSSX_ACCEPT_SEC_CONTEXT */ + (xdrproc_t)xdr_gssx_arg_accept_sec_context, + (xdrproc_t)xdr_gssx_res_accept_sec_context, + gp_accept_sec_context + }, + { /* GSSX_RELEASE_HANDLE */ + (xdrproc_t)xdr_gssx_arg_release_handle, + (xdrproc_t)xdr_gssx_res_release_handle, + gp_release_handle + }, + { /* GSSX_GET_MIC */ + (xdrproc_t)xdr_gssx_arg_get_mic, + (xdrproc_t)xdr_gssx_res_get_mic, + gp_get_mic + }, + { /* GSSX_VERIFY */ + (xdrproc_t)xdr_gssx_arg_verify_mic, + (xdrproc_t)xdr_gssx_res_verify_mic, + gp_verify + }, + { /* GSSX_WRAP */ + (xdrproc_t)xdr_gssx_arg_wrap, + (xdrproc_t)xdr_gssx_res_wrap, + gp_wrap + }, + { /* GSSX_UNWRAP */ + (xdrproc_t)xdr_gssx_arg_unwrap, + (xdrproc_t)xdr_gssx_res_unwrap, + gp_unwrap + }, + { /* GSSX_WRAP_SIZE_LIMIT */ + (xdrproc_t)xdr_gssx_arg_wrap_size_limit, + (xdrproc_t)xdr_gssx_res_wrap_size_limit, + gp_wrap_size_limit + } +}; + +static int gp_rpc_decode_call_header(struct gp_rpc_call *call, + uint32_t *xid, + uint32_t *proc, + gp_rpc_accept_status *acc, + gp_rpc_reject_status *rej) +{ + struct gp_rpc_call_header *chdr; + bool decoded; + + decoded = xdr_gp_rpc_msg(&call->xdr_ctx, &call->msg); + if (!decoded) { + return EFAULT; + } + + *xid = call->msg.xid; + + if (call->msg.header.type != GP_RPC_CALL) { + *acc = GP_RPC_GARBAGE_ARGS; + return EINVAL; + } + + chdr = &call->msg.header.gp_rpc_msg_union_u.chdr; + + if (chdr->rpcvers != 2) { + *rej = GP_RPC_RPC_MISMATCH; + return EACCES; + } + if (chdr->prog != GSSPROXY) { + *acc = GP_RPC_PROG_UNAVAIL; + return EINVAL; + } + if (chdr->vers != GSSPROXYVERS) { + *acc = GP_RPC_PROG_MISMATCH; + return EINVAL; + } + if (chdr->proc < 1 || chdr->proc > 15) { + *acc = GP_RPC_PROC_UNAVAIL; + return EINVAL; + } + if (chdr->cred.flavor != GP_RPC_AUTH_NONE) { + *rej = GP_RPC_AUTH_ERROR; + return EACCES; + } + + *proc = chdr->proc; + *acc = GP_RPC_SUCCESS; + return 0; +} + +static int gp_rpc_decode_call(struct gp_rpc_call *call, + uint32_t *xid, + uint32_t *proc, + union gp_rpc_arg *arg, + gp_rpc_accept_status *acc, + gp_rpc_reject_status *rej) +{ + bool xdrok; + int ret; + + ret = gp_rpc_decode_call_header(call, xid, proc, acc, rej); + if (ret) { + return ret; + } + + xdrok = gp_xdr_set[*proc].arg_fn(&call->xdr_ctx, (char *)arg); + if (!xdrok) { + *acc = GP_RPC_GARBAGE_ARGS; + return EINVAL; + } + + return 0; +} + +static int gp_rpc_encode_reply_header(struct gp_rpc_reply *reply, + uint32_t xid, int err, + gp_rpc_accept_status acc, + gp_rpc_reject_status rej) +{ + gp_rpc_reply_header *rhdr; + gp_rpc_accepted_reply *accepted; + gp_rpc_rejected_reply *rejected; + bool encoded; + + reply->msg.xid = xid; + reply->msg.header.type = GP_RPC_REPLY; + + rhdr = &reply->msg.header.gp_rpc_msg_union_u.rhdr; + accepted = &rhdr->gp_rpc_reply_header_u.accepted; + rejected = &rhdr->gp_rpc_reply_header_u.rejected; + + switch (err) { + case EFAULT: + return EFAULT; + case EACCES: + rhdr->status = GP_RPC_MSG_DENIED; + rejected->status = rej; + if (rej == GP_RPC_RPC_MISMATCH) { + rejected->gp_rpc_rejected_reply_u.mismatch_info.high = 2; + rejected->gp_rpc_rejected_reply_u.mismatch_info.low = 2; + } else { + rejected->gp_rpc_rejected_reply_u.status = GP_RPC_AUTH_FAILED; + } + break; + case EINVAL: + rhdr->status = GP_RPC_MSG_ACCEPTED; + accepted->reply_data.status = acc; + if (acc == GP_RPC_PROG_MISMATCH) { + accepted->reply_data.gp_rpc_reply_union_u.mismatch_info.high = GSSPROXYVERS; + accepted->reply_data.gp_rpc_reply_union_u.mismatch_info.low = GSSPROXYVERS; + } + break; + case 0: + rhdr->status = GP_RPC_MSG_ACCEPTED; + accepted->reply_data.status = GP_RPC_SUCCESS; + break; + default: + rhdr->status = GP_RPC_MSG_ACCEPTED; + accepted->reply_data.status = GP_RPC_SYSTEM_ERR; + break; + } + + /* always reset xdr_ctx position, as this function may be called + * multiple times in case errors occurred after the initial header + * was created */ + xdr_setpos(&reply->xdr_ctx, 0); + + encoded = xdr_gp_rpc_msg(&reply->xdr_ctx, &reply->msg); + if (!encoded) { + return EFAULT; + } + + return 0; +} + +static int gp_rpc_encode_reply(struct gp_rpc_reply *reply, + uint32_t xid, uint32_t proc, + union gp_rpc_res *res, int err, + gp_rpc_accept_status acc, + gp_rpc_reject_status rej) +{ + bool xdrok; + int ret; + + ret = gp_rpc_encode_reply_header(reply, xid, err, acc, rej); + if (ret != 0 || err != 0) { + return ret; + } + + xdrok = gp_xdr_set[proc].res_fn(&reply->xdr_ctx, (char *)res); + + if (!xdrok) { + return gp_rpc_encode_reply_header(reply, xid, EINVAL, + GP_RPC_SYSTEM_ERR, 0); + } + + return 0; +} + +static int gp_rpc_execute(struct gssproxy_ctx *gpctx, uint32_t proc, + union gp_rpc_arg *arg, union gp_rpc_res *res) +{ + return gp_xdr_set[proc].exec_fn(gpctx, arg, res); +} + +static int gp_rpc_return_buffer(struct gp_rpc_reply *reply, + uint8_t **outbuf, size_t *outlen) +{ + unsigned int length; + uint8_t *buffer; + + length = xdr_getpos(&reply->xdr_ctx); + + buffer = malloc(length); + if (!buffer) { + return ENOMEM; + } + memcpy(buffer, reply->buffer, length); + + *outbuf = buffer; + *outlen = length; + return 0; +} + +static void gp_rpc_free_xdrs(struct gp_rpc_call *call, + struct gp_rpc_reply *reply, + int proc, + union gp_rpc_arg *arg, + union gp_rpc_res *res) +{ + + xdr_free(gp_xdr_set[proc].arg_fn, (char *)arg); + xdr_free(gp_xdr_set[proc].res_fn, (char *)res); + xdr_destroy(&call->xdr_ctx); + xdr_destroy(&reply->xdr_ctx); +} + +int gp_rpc_process_call(struct gssproxy_ctx *gpctx, + uint8_t *inbuf, size_t inlen, + uint8_t **outbuf, size_t *outlen) +{ + struct gp_rpc_call call; + struct gp_rpc_reply reply; + gp_rpc_accept_status acc = 0; + gp_rpc_reject_status rej = 0; + union gp_rpc_arg arg; + union gp_rpc_res res; + uint32_t xid = 0; + uint32_t proc; + int ret; + + memset(&arg, 0, sizeof(union gp_rpc_arg)); + memset(&res, 0, sizeof(union gp_rpc_res)); + proc = 0; + + xdrmem_create(&call.xdr_ctx, (caddr_t)inbuf, inlen, XDR_DECODE); + xdrmem_create(&reply.xdr_ctx, reply.buffer, MAX_RPC_SIZE, XDR_ENCODE); + + /* decode request */ + ret = gp_rpc_decode_call(&call, &xid, &proc, &arg, &acc, &rej); + if (!ret) { + /* execute request */ + ret = gp_rpc_execute(gpctx, proc, &arg, &res); + if (ret) { + acc = GP_RPC_SYSTEM_ERR; + ret = EINVAL; + } + } + + /* encode reply */ + ret = gp_rpc_encode_reply(&reply, xid, proc, &res, ret, acc, rej); + if (ret == 0) { + /* return encoded buffer */ + ret = gp_rpc_return_buffer(&reply, outbuf, outlen); + } + /* free resources */ + gp_rpc_free_xdrs(&call, &reply, proc, &arg, &res); + return ret; +} + +int gp_indicate_mechs(gp_exec_std_args) +{ + return 0; +} +int gp_get_call_context(gp_exec_std_args) +{ + return 0; +} +int gp_import_and_canon_name(gp_exec_std_args) +{ + return 0; +} +int gp_export_cred(gp_exec_std_args) +{ + return 0; +} +int gp_import_cred(gp_exec_std_args) +{ + return 0; +} +int gp_acquire_cred(gp_exec_std_args) +{ + return 0; +} +int gp_store_cred(gp_exec_std_args) +{ + return 0; +} +int gp_init_sec_context(gp_exec_std_args) +{ + return 0; +} +int gp_accept_sec_context(gp_exec_std_args) +{ + return 0; +} +int gp_release_handle(gp_exec_std_args) +{ + return 0; +} +int gp_get_mic(gp_exec_std_args) +{ + return 0; +} +int gp_verify(gp_exec_std_args) +{ + return 0; +} +int gp_wrap(gp_exec_std_args) +{ + return 0; +} +int gp_unwrap(gp_exec_std_args) +{ + return 0; +} +int gp_wrap_size_limit(gp_exec_std_args) +{ + return 0; +} diff --git a/proxy/src/gp_rpc_process.h b/proxy/src/gp_rpc_process.h new file mode 100644 index 0000000..bef1074 --- /dev/null +++ b/proxy/src/gp_rpc_process.h @@ -0,0 +1,107 @@ +/* + GSS-PROXY + + Copyright (C) 2011 Red Hat, Inc. + Copyright (C) 2011 Simo Sorce <simo.sorce@redhat.com> + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#ifndef _GP_RPC_PROCESS_H_ +#define _GP_RPC_PROCESS_H_ + +#include "rpcgen/gss_proxy.h" +#include "rpcgen/gp_rpc.h" + +struct gp_rpc_call { + XDR xdr_ctx; + gp_rpc_msg msg; +}; + +struct gp_rpc_reply { + XDR xdr_ctx; + gp_rpc_msg msg; + char buffer[MAX_RPC_SIZE]; +}; + +union gp_rpc_arg { + gssx_arg_release_handle gssx_arg_release_handle_arg; + gssx_arg_indicate_mechs gssx_arg_indicate_mechs_arg; + gssx_arg_import_and_canon_name gssx_arg_import_and_canon_name_arg; + gssx_arg_get_call_context gssx_arg_get_call_context_arg; + gssx_arg_acquire_cred gssx_arg_acquire_cred_arg; + gssx_arg_export_cred gssx_arg_export_cred_arg; + gssx_arg_import_cred gssx_arg_import_cred_arg; + gssx_arg_store_cred gssx_arg_store_cred_arg; + gssx_arg_init_sec_context gssx_arg_init_sec_context_arg; + gssx_arg_accept_sec_context gssx_arg_accept_sec_context_arg; + gssx_arg_get_mic gssx_arg_get_mic_arg; + gssx_arg_verify_mic gssx_arg_verify_mic_arg; + gssx_arg_wrap gssx_arg_wrap_arg; + gssx_arg_unwrap gssx_arg_unwrap_arg; + gssx_arg_wrap_size_limit gssx_arg_wrap_size_limit_arg; +}; + +union gp_rpc_res { + gssx_res_release_handle gssx_res_release_handle_res; + gssx_res_indicate_mechs gssx_res_indicate_mechs_res; + gssx_res_import_and_canon_name gssx_res_import_and_canon_name_res; + gssx_res_get_call_context gssx_res_get_call_context_res; + gssx_res_acquire_cred gssx_res_acquire_cred_res; + gssx_res_export_cred gssx_res_export_cred_res; + gssx_res_import_cred gssx_res_import_cred_res; + gssx_res_store_cred gssx_res_store_cred_res; + gssx_res_init_sec_context gssx_res_init_sec_context_res; + gssx_res_accept_sec_context gssx_res_accept_sec_context_res; + gssx_res_get_mic gssx_res_get_mic_res; + gssx_res_verify_mic gssx_res_verify_mic_res; + gssx_res_wrap gssx_res_wrap_res; + gssx_res_unwrap gssx_res_unwrap_res; + gssx_res_wrap_size_limit gssx_res_wrap_size_limit_res; +}; + +#define gp_exec_std_args struct gssproxy_ctx *gpctx, \ + union gp_rpc_arg *arg, \ + union gp_rpc_res *res + +typedef int (*gp_exec_fn)(gp_exec_std_args); + +int gp_indicate_mechs(gp_exec_std_args); +int gp_get_call_context(gp_exec_std_args); +int gp_import_and_canon_name(gp_exec_std_args); +int gp_export_cred(gp_exec_std_args); +int gp_import_cred(gp_exec_std_args); +int gp_acquire_cred(gp_exec_std_args); +int gp_store_cred(gp_exec_std_args); +int gp_init_sec_context(gp_exec_std_args); +int gp_accept_sec_context(gp_exec_std_args); +int gp_release_handle(gp_exec_std_args); +int gp_get_mic(gp_exec_std_args); +int gp_verify(gp_exec_std_args); +int gp_wrap(gp_exec_std_args); +int gp_unwrap(gp_exec_std_args); +int gp_wrap_size_limit(gp_exec_std_args); + +struct gp_rpc_fn_set { + xdrproc_t arg_fn; + xdrproc_t res_fn; + gp_exec_fn exec_fn; +}; + +#endif /* _GP_RPC_PROCESS_H_ */ diff --git a/proxy/src/gp_socket.c b/proxy/src/gp_socket.c index ea8ae19..664d6f4 100644 --- a/proxy/src/gp_socket.c +++ b/proxy/src/gp_socket.c @@ -40,9 +40,6 @@ #define CRED_TYPE_UNIX 0x01 #define CRED_TYPE_SELINUX 0x02 -/* max out at 1MB for now */ -#define MAX_RPC_SIZE 1024*1024 - struct gp_creds { int type; #ifdef HAVE_UCRED diff --git a/proxy/src/gp_utils.h b/proxy/src/gp_utils.h index fb77cd7..37ad602 100644 --- a/proxy/src/gp_utils.h +++ b/proxy/src/gp_utils.h @@ -96,4 +96,12 @@ void gp_workers_free(struct gp_workers *w); int gp_query_new(struct gp_workers *w, struct gp_conn *conn, uint8_t *buffer, size_t buflen); +/* max out at 1MB for now */ +#define MAX_RPC_SIZE 1024*1024 + +/* from gp_rpc.c */ +int gp_rpc_process_call(struct gssproxy_ctx *gpctx, + uint8_t *inbuf, size_t inlen, + uint8_t **outbuf, size_t *outlen); + #endif /* _SRV_UTILS_H_ */ diff --git a/proxy/src/gp_workers.c b/proxy/src/gp_workers.c index 3d5467b..47cab34 100644 --- a/proxy/src/gp_workers.c +++ b/proxy/src/gp_workers.c @@ -430,11 +430,20 @@ static void *gp_worker_main(void *pvt) static void gp_handle_query(struct gp_workers *w, struct gp_query *q) { - /* TODO */ + uint8_t *buffer; + size_t buflen; + int ret; - free(q->buffer); - q->buffer = strdup("WHATS UP?"); - q->buflen = strlen(q->buffer); - q->status = GP_QUERY_OUT; + ret = gp_rpc_process_call(w->gpctx, + q->buffer, q->buflen, + &buffer, &buflen); + if (ret) { + q->status = GP_QUERY_ERR; + } else { + q->status = GP_QUERY_OUT; + free(q->buffer); + q->buffer = buffer; + q->buflen = buflen; + } } |