summaryrefslogtreecommitdiff
path: root/src/lib/rpc/auth_gssapi_misc.c
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
committerCy Schubert <cy@FreeBSD.org>2017-07-07 17:03:42 +0000
commit33a9b234e7087f573ef08cd7318c6497ba08b439 (patch)
treed0ea40ad3bf5463a3c55795977c71bcb7d781b4b /src/lib/rpc/auth_gssapi_misc.c
Diffstat (limited to 'src/lib/rpc/auth_gssapi_misc.c')
-rw-r--r--src/lib/rpc/auth_gssapi_misc.c334
1 files changed, 334 insertions, 0 deletions
diff --git a/src/lib/rpc/auth_gssapi_misc.c b/src/lib/rpc/auth_gssapi_misc.c
new file mode 100644
index 000000000000..a05ea19eb7c4
--- /dev/null
+++ b/src/lib/rpc/auth_gssapi_misc.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ */
+
+#include <gssrpc/rpc.h>
+#include <stdio.h>
+
+#include <gssapi/gssapi.h>
+#include <gssrpc/auth_gssapi.h>
+
+#include "gssrpcint.h"
+
+#ifdef __CODECENTER__
+#define DEBUG_GSSAPI 1
+#endif
+
+#ifdef DEBUG_GSSAPI
+int misc_debug_gssapi = DEBUG_GSSAPI;
+extern void gssrpcint_printf(const char *, ...);
+#define L_PRINTF(l,args) if (misc_debug_gssapi >= l) gssrpcint_printf args
+#define PRINTF(args) L_PRINTF(99, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args) \
+ if (misc_debug_gssapi) auth_gssapi_display_status args
+#else
+#define PRINTF(args)
+#define L_PRINTF(l, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args)
+#endif
+
+static void auth_gssapi_display_status_1
+ (char *, OM_uint32, int, int);
+
+bool_t xdr_gss_buf(
+ XDR *xdrs,
+ gss_buffer_t buf)
+{
+ /*
+ * On decode, xdr_bytes will only allocate buf->value if the
+ * length read in is < maxsize (last arg). This is dumb, because
+ * the whole point of allocating memory is so that I don't *have*
+ * to know the maximum length. -1 effectively disables this
+ * braindamage.
+ */
+ bool_t result;
+ /* Fix type mismatches between APIs. */
+ unsigned int length = buf->length;
+ result = xdr_bytes(xdrs, (char **) &buf->value, &length,
+ (xdrs->x_op == XDR_DECODE && buf->value == NULL)
+ ? (unsigned int) -1 : (unsigned int) buf->length);
+ buf->length = length;
+ return result;
+}
+
+bool_t xdr_authgssapi_creds(
+ XDR *xdrs,
+ auth_gssapi_creds *creds)
+{
+ if (! xdr_u_int32(xdrs, &creds->version) ||
+ ! xdr_bool(xdrs, &creds->auth_msg) ||
+ ! xdr_gss_buf(xdrs, &creds->client_handle))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t xdr_authgssapi_init_arg(
+ XDR *xdrs,
+ auth_gssapi_init_arg *init_arg)
+{
+ if (! xdr_u_int32(xdrs, &init_arg->version) ||
+ ! xdr_gss_buf(xdrs, &init_arg->token))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t xdr_authgssapi_init_res(
+ XDR *xdrs,
+ auth_gssapi_init_res *init_res)
+{
+ if (! xdr_u_int32(xdrs, &init_res->version) ||
+ ! xdr_gss_buf(xdrs, &init_res->client_handle) ||
+ ! xdr_u_int32(xdrs, &init_res->gss_major) ||
+ ! xdr_u_int32(xdrs, &init_res->gss_minor) ||
+ ! xdr_gss_buf(xdrs, &init_res->token) ||
+ ! xdr_gss_buf(xdrs, &init_res->signed_isn))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t auth_gssapi_seal_seq(
+ gss_ctx_id_t context,
+ uint32_t seq_num,
+ gss_buffer_t out_buf)
+{
+ gss_buffer_desc in_buf;
+ OM_uint32 gssstat, minor_stat;
+ uint32_t nl_seq_num;
+
+ nl_seq_num = htonl(seq_num);
+
+ in_buf.length = sizeof(uint32_t);
+ in_buf.value = (char *) &nl_seq_num;
+ gssstat = gss_seal(&minor_stat, context, 0, GSS_C_QOP_DEFAULT,
+ &in_buf, NULL, out_buf);
+ if (gssstat != GSS_S_COMPLETE) {
+ PRINTF(("gssapi_seal_seq: failed\n"));
+ AUTH_GSSAPI_DISPLAY_STATUS(("sealing sequence number",
+ gssstat, minor_stat));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool_t auth_gssapi_unseal_seq(
+ gss_ctx_id_t context,
+ gss_buffer_t in_buf,
+ uint32_t *seq_num)
+{
+ gss_buffer_desc out_buf;
+ OM_uint32 gssstat, minor_stat;
+ uint32_t nl_seq_num;
+
+ gssstat = gss_unseal(&minor_stat, context, in_buf, &out_buf,
+ NULL, NULL);
+ if (gssstat != GSS_S_COMPLETE) {
+ PRINTF(("gssapi_unseal_seq: failed\n"));
+ AUTH_GSSAPI_DISPLAY_STATUS(("unsealing sequence number",
+ gssstat, minor_stat));
+ return FALSE;
+ } else if (out_buf.length != sizeof(uint32_t)) {
+ PRINTF(("gssapi_unseal_seq: unseal gave %d bytes\n",
+ (int) out_buf.length));
+ gss_release_buffer(&minor_stat, &out_buf);
+ return FALSE;
+ }
+
+ nl_seq_num = *((uint32_t *) out_buf.value);
+ *seq_num = (uint32_t) ntohl(nl_seq_num);
+ gss_release_buffer(&minor_stat, &out_buf);
+
+ return TRUE;
+}
+
+void auth_gssapi_display_status(
+ char *msg,
+ OM_uint32 major,
+ OM_uint32 minor)
+{
+ auth_gssapi_display_status_1(msg, major, GSS_C_GSS_CODE, 0);
+ auth_gssapi_display_status_1(msg, minor, GSS_C_MECH_CODE, 0);
+}
+
+static void auth_gssapi_display_status_1(
+ char *m,
+ OM_uint32 code,
+ int type,
+ int rec)
+{
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc msg;
+ OM_uint32 msg_ctx;
+
+ msg_ctx = 0;
+ while (1) {
+ gssstat = gss_display_status(&minor_stat, code,
+ type, GSS_C_NULL_OID,
+ &msg_ctx, &msg);
+ if (gssstat != GSS_S_COMPLETE) {
+ if (!rec) {
+ auth_gssapi_display_status_1(m,gssstat,GSS_C_GSS_CODE,1);
+ auth_gssapi_display_status_1(m, minor_stat,
+ GSS_C_MECH_CODE, 1);
+ } else {
+ fputs ("GSS-API authentication error ", stderr);
+ fwrite (msg.value, msg.length, 1, stderr);
+ fputs (": recursive failure!\n", stderr);
+ }
+ return;
+ }
+
+ fprintf (stderr, "GSS-API authentication error %s: ", m);
+ fwrite (msg.value, msg.length, 1, stderr);
+ putc ('\n', stderr);
+ if (misc_debug_gssapi)
+ gssrpcint_printf("GSS-API authentication error %s: %*s\n",
+ m, (int)msg.length, (char *) msg.value);
+ (void) gss_release_buffer(&minor_stat, &msg);
+
+ if (!msg_ctx)
+ break;
+ }
+}
+
+bool_t auth_gssapi_wrap_data(
+ OM_uint32 *major,
+ OM_uint32 *minor,
+ gss_ctx_id_t context,
+ uint32_t seq_num,
+ XDR *out_xdrs,
+ bool_t (*xdr_func)(),
+ caddr_t xdr_ptr)
+{
+ gss_buffer_desc in_buf, out_buf;
+ XDR temp_xdrs;
+ int conf_state;
+ unsigned int length;
+
+ PRINTF(("gssapi_wrap_data: starting\n"));
+
+ *major = GSS_S_COMPLETE;
+ *minor = 0; /* assumption */
+
+ xdralloc_create(&temp_xdrs, XDR_ENCODE);
+
+ /* serialize the sequence number into local memory */
+ PRINTF(("gssapi_wrap_data: encoding seq_num %d\n", seq_num));
+ if (! xdr_u_int32(&temp_xdrs, &seq_num)) {
+ PRINTF(("gssapi_wrap_data: serializing seq_num failed\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ /* serialize the arguments into local memory */
+ if (!(*xdr_func)(&temp_xdrs, xdr_ptr)) {
+ PRINTF(("gssapi_wrap_data: serializing arguments failed\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ in_buf.length = xdr_getpos(&temp_xdrs);
+ in_buf.value = xdralloc_getdata(&temp_xdrs);
+
+ *major = gss_seal(minor, context, 1,
+ GSS_C_QOP_DEFAULT, &in_buf, &conf_state,
+ &out_buf);
+ if (*major != GSS_S_COMPLETE) {
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ PRINTF(("gssapi_wrap_data: %d bytes data, %d bytes sealed\n",
+ (int) in_buf.length, (int) out_buf.length));
+
+ /* write the token */
+ length = out_buf.length;
+ if (! xdr_bytes(out_xdrs, (char **) &out_buf.value,
+ (unsigned int *) &length,
+ out_buf.length)) {
+ PRINTF(("gssapi_wrap_data: serializing encrypted data failed\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ *major = gss_release_buffer(minor, &out_buf);
+
+ PRINTF(("gssapi_wrap_data: succeeding\n\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return TRUE;
+}
+
+bool_t auth_gssapi_unwrap_data(
+ OM_uint32 *major,
+ OM_uint32 *minor,
+ gss_ctx_id_t context,
+ uint32_t seq_num,
+ XDR *in_xdrs,
+ bool_t (*xdr_func)(),
+ caddr_t xdr_ptr)
+{
+ gss_buffer_desc in_buf, out_buf;
+ XDR temp_xdrs;
+ uint32_t verf_seq_num;
+ int conf, qop;
+ unsigned int length;
+
+ PRINTF(("gssapi_unwrap_data: starting\n"));
+
+ *major = GSS_S_COMPLETE;
+ *minor = 0; /* assumption */
+
+ in_buf.value = NULL;
+ out_buf.value = NULL;
+ if (! xdr_bytes(in_xdrs, (char **) &in_buf.value,
+ &length, (unsigned int) -1)) {
+ PRINTF(("gssapi_unwrap_data: deserializing encrypted data failed\n"));
+ temp_xdrs.x_op = XDR_FREE;
+ (void)xdr_bytes(&temp_xdrs, (char **) &in_buf.value, &length,
+ (unsigned int) -1);
+ return FALSE;
+ }
+ in_buf.length = length;
+
+ *major = gss_unseal(minor, context, &in_buf, &out_buf, &conf,
+ &qop);
+ free(in_buf.value);
+ if (*major != GSS_S_COMPLETE)
+ return FALSE;
+
+ PRINTF(("gssapi_unwrap_data: %llu bytes data, %llu bytes sealed\n",
+ (unsigned long long)out_buf.length,
+ (unsigned long long)in_buf.length));
+
+ xdrmem_create(&temp_xdrs, out_buf.value, out_buf.length, XDR_DECODE);
+
+ /* deserialize the sequence number */
+ if (! xdr_u_int32(&temp_xdrs, &verf_seq_num)) {
+ PRINTF(("gssapi_unwrap_data: deserializing verf_seq_num failed\n"));
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+ if (verf_seq_num != seq_num) {
+ PRINTF(("gssapi_unwrap_data: seq %d specified, read %d\n",
+ seq_num, verf_seq_num));
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+ PRINTF(("gssapi_unwrap_data: unwrap seq_num %d okay\n", verf_seq_num));
+
+ /* deserialize the arguments into xdr_ptr */
+ if (! (*xdr_func)(&temp_xdrs, xdr_ptr)) {
+ PRINTF(("gssapi_unwrap_data: deserializing arguments failed\n"));
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ PRINTF(("gssapi_unwrap_data: succeeding\n\n"));
+
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return TRUE;
+}