return -1;
}
*bp = '\0';
- printerr(1, "writing message: %s", buf);
+ printerr(3, "writing message: %s", buf);
if (write(g, buf, bp - buf) == -1) {
printerr(0, "WARNING: failed to write message\n");
close(g);
uid_t uid, gid;
gss_OID name_type = GSS_C_NO_OID;
char *secname;
- gid_t *groups;
maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
if (maj_stat != GSS_S_COMPLETE) {
maj_stat, min_stat, mech);
goto out;
}
- if (!(sname = calloc(name.length + 1, 1))) {
+ if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */
+ !(sname = calloc(name.length + 1, 1))) {
printerr(0, "WARNING: get_ids: error allocating %d bytes "
"for sname\n", name.length + 1);
+ gss_release_buffer(&min_stat, &name);
goto out;
}
memcpy(sname, name.value, name.length);
printerr(1, "sname = %s\n", sname);
+ gss_release_buffer(&min_stat, &name);
res = -EINVAL;
if ((secname = mech2file(mech)) == NULL) {
nfs4_init_name_mapping(NULL); /* XXX: should only do this once */
res = nfs4_gss_princ_to_ids(secname, sname, &uid, &gid);
if (res < 0) {
- printerr(0, "WARNING: get_ids: unable to map "
- "name '%s' to a uid\n", sname);
+ /*
+ * -ENOENT means there was no mapping, any other error
+ * value means there was an error trying to do the
+ * mapping.
+ * If there was no mapping, we send down the value -1
+ * to indicate that the anonuid/anongid for the export
+ * should be used.
+ */
+ if (res == -ENOENT) {
+ cred->cr_uid = -1;
+ cred->cr_gid = -1;
+ cred->cr_ngroups = 0;
+ res = 0;
+ goto out_free;
+ }
+ printerr(0, "WARNING: get_ids: failed to map name '%s' "
+ "to uid/gid: %s\n", sname, strerror(-res));
goto out_free;
}
cred->cr_uid = uid;
in_handle = {.value = in_handle_buf},
out_handle = {.value = out_handle_buf},
ctx_token = {.value = NULL},
+ ignore_out_tok = {.value = NULL},
/* XXX isn't there a define for this?: */
null_token = {.value = NULL};
u_int32_t ret_flags;
gss_name_t client_name;
gss_OID mech = GSS_C_NO_OID;
u_int32_t maj_stat = GSS_S_FAILURE, min_stat = 0;
+ u_int32_t ignore_min_stat;
struct svc_cred cred;
static char *lbuf = NULL;
static int lbuflen = 0;
if (get_ids(client_name, mech, &cred)) {
/* get_ids() prints error msg */
maj_stat = GSS_S_BAD_NAME; /* XXX ? */
+ gss_release_name(&ignore_min_stat, &client_name);
goto out_err;
}
+ gss_release_name(&ignore_min_stat, &client_name);
/* Context complete. Pass handle_seq in out_handle to use
/* 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)) {
+ if (serialize_context_for_kernel(ctx, &ctx_token, mech)) {
printerr(0, "WARNING: handle_nullreq: "
"serialize_context_for_kernel failed\n");
maj_stat = GSS_S_FAILURE;
goto out_err;
}
+ /* We no longer need the gss context */
+ gss_delete_sec_context(&ignore_min_stat, &ctx, &ignore_out_tok);
+
do_svc_downcall(&out_handle, &cred, mech, &ctx_token);
continue_needed:
send_response(f, &in_handle, &in_tok, maj_stat, min_stat,
out:
if (ctx_token.value != NULL)
free(ctx_token.value);
+ if (out_tok.value != NULL)
+ gss_release_buffer(&ignore_min_stat, &out_tok);
printerr(1, "finished handling null request\n");
return;
out_err:
+ if (ctx != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&ignore_min_stat, &ctx, &ignore_out_tok);
send_response(f, &in_handle, &in_tok, maj_stat, min_stat,
&null_token, &null_token);
goto out;