/* * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved. * */ #include #include #include #include #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_free(xdr_func, xdr_ptr); 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; }