diff options
Diffstat (limited to 'src/lib/rpc/auth_gssapi_misc.c')
| -rw-r--r-- | src/lib/rpc/auth_gssapi_misc.c | 334 | 
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; +} | 
