From: Kevin Coffman Add CONTINUE_INIT handling to svcgssd. Store the partially complete spkm context handle in the out_handle of CONTINUE_INIT messages so that it is returned in the in_handle of subsequent messages. Signed-off-by: Andy Adamson Signed-off-by: Kevin Coffman --- nfs-utils-1.0.7-kwc/utils/svcgssd/svcgssd_proc.c | 49 ++++++++++++++++------- 1 files changed, 36 insertions(+), 13 deletions(-) diff -puN utils/svcgssd/svcgssd_proc.c~svcgssd_continue_init utils/svcgssd/svcgssd_proc.c --- nfs-utils-1.0.7/utils/svcgssd/svcgssd_proc.c~svcgssd_continue_init 2005-10-18 15:16:14.088419000 -0400 +++ nfs-utils-1.0.7-kwc/utils/svcgssd/svcgssd_proc.c 2005-10-18 15:16:14.124419000 -0400 @@ -56,6 +56,8 @@ extern char * mech2file(gss_OID mech); #define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel" #define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.rpcsec.init/channel" +#define TOKEN_BUF_SIZE 8192 + struct svc_cred { uid_t cr_uid; gid_t cr_gid; @@ -111,7 +113,7 @@ send_response(FILE *f, gss_buffer_desc * u_int32_t maj_stat, u_int32_t min_stat, gss_buffer_desc *out_handle, gss_buffer_desc *out_token) { - char buf[2 * 4096]; + char buf[2 * TOKEN_BUF_SIZE]; char *bp = buf; int blen = sizeof(buf); /* XXXARG: */ @@ -272,7 +274,7 @@ handle_nullreq(FILE *f) { /* XXX initialize to a random integer to reduce chances of unnecessary * invalidation of existing ctx's on restarting svcgssd. */ static u_int32_t handle_seq = 0; - char in_tok_buf[8192]; + char in_tok_buf[TOKEN_BUF_SIZE]; char in_handle_buf[15]; char out_handle_buf[15]; gss_buffer_desc in_tok = {.value = in_tok_buf}, @@ -306,9 +308,6 @@ handle_nullreq(FILE *f) { sizeof(in_handle_buf)); printerr(2, "in_handle: \n"); print_hexl(2, in_handle.value, in_handle.length); - handle_seq++; - out_handle.length = sizeof(handle_seq); - memcpy(out_handle.value, &handle_seq, sizeof(handle_seq)); in_tok.length = (size_t) qword_get(&cp, in_tok.value, sizeof(in_tok_buf)); @@ -322,15 +321,30 @@ handle_nullreq(FILE *f) { } if (in_handle.length != 0) { /* CONTINUE_INIT case */ - printerr(0, "WARNING: handle_nullreq: " - "CONTINUE_INIT unsupported\n"); - goto out_err; + if (in_handle.length != sizeof(ctx)) { + printerr(0, "WARNING: handle_nullreq: " + "input handle has unexpected length %d\n", + in_handle.length); + goto out_err; + } + /* in_handle is the context id stored in the out_handle + * for the GSS_S_CONTINUE_NEEDED case below. */ + memcpy(&ctx, in_handle.value, in_handle.length); } maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds, &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name, &mech, &out_tok, &ret_flags, NULL, NULL); - if (maj_stat != GSS_S_COMPLETE) { + + if (maj_stat == GSS_S_CONTINUE_NEEDED) { + printerr(1, "gss_accept_sec_context GSS_S_CONTINUE_NEEDED\n"); + + /* Save the context handle for future calls */ + out_handle.length = sizeof(ctx); + memcpy(out_handle.value, &ctx, sizeof(ctx)); + goto continue_needed; + } + else if (maj_stat != GSS_S_COMPLETE) { printerr(0, "WARNING: gss_accept_sec_context failed\n"); pgsserr("handle_nullreq: gss_accept_sec_context", maj_stat, min_stat, mech); @@ -342,6 +356,13 @@ handle_nullreq(FILE *f) { goto out_err; } + + /* Context complete. Pass handle_seq in out_handle to use + * for context lookup in the kernel. */ + handle_seq++; + out_handle.length = sizeof(handle_seq); + memcpy(out_handle.value, &handle_seq, sizeof(handle_seq)); + /* kernel needs ctx to calculate verifier on null response, so * must give it context before doing null call: */ if (serialize_context_for_kernel(ctx, &ctx_token)) { @@ -351,15 +372,17 @@ handle_nullreq(FILE *f) { goto out_err; } do_svc_downcall(&out_handle, &cred, mech, &ctx_token); +continue_needed: send_response(f, &in_handle, &in_tok, maj_stat, min_stat, &out_handle, &out_tok); - goto out; -out_err: - send_response(f, &in_handle, &in_tok, maj_stat, min_stat, - &null_token, &null_token); out: if (ctx_token.value != NULL) free(ctx_token.value); printerr(1, "finished handling null request\n"); return; + +out_err: + send_response(f, &in_handle, &in_tok, maj_stat, min_stat, + &null_token, &null_token); + goto out; } _