Example #1
0
static int
do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
		gss_OID mech, gss_buffer_desc *context_token,
		int32_t endtime, char *client_name)
{
	FILE *f;
	int i;
	char *fname = NULL;
	int err;

	printerr(1, "doing downcall\n");
	if ((fname = mech2file(mech)) == NULL)
		goto out_err;
	f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w");
	if (f == NULL) {
		printerr(0, "WARNING: unable to open downcall channel "
			     "%s: %s\n",
			     SVCGSSD_CONTEXT_CHANNEL, strerror(errno));
		goto out_err;
	}
	qword_printhex(f, out_handle->value, out_handle->length);
	/* XXX are types OK for the rest of this? */
	/* For context cache, use the actual context endtime */
	qword_printint(f, endtime);
	qword_printint(f, cred->cr_uid);
	qword_printint(f, cred->cr_gid);
	qword_printint(f, cred->cr_ngroups);
	printerr(2, "mech: %s, hndl len: %d, ctx len %d, timeout: %d (%d from now), "
		 "clnt: %s, uid: %d, gid: %d, num aux grps: %d:\n",
		 fname, out_handle->length, context_token->length,
		 endtime, endtime - time(0),
		 client_name ? client_name : "<null>",
		 cred->cr_uid, cred->cr_gid, cred->cr_ngroups);
	for (i=0; i < cred->cr_ngroups; i++) {
		qword_printint(f, cred->cr_groups[i]);
		printerr(2, "  (%4d) %d\n", i+1, cred->cr_groups[i]);
	}
	qword_print(f, fname);
	qword_printhex(f, context_token->value, context_token->length);
	if (client_name)
		qword_print(f, client_name);
	err = qword_eol(f);
	if (err) {
		printerr(1, "WARNING: error writing to downcall channel "
			 "%s: %s\n", SVCGSSD_CONTEXT_CHANNEL, strerror(errno));
	}
	fclose(f);
	return err;
out_err:
	printerr(1, "WARNING: downcall failed\n");
	return -1;
}
Example #2
0
static int
get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
{
	u_int32_t	maj_stat, min_stat;
	gss_buffer_desc	name;
	char		*sname;
	int		res = -1;
	uid_t		uid, gid;
	gss_OID		name_type = GSS_C_NO_OID;
	char		*secname;

	maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
	if (maj_stat != GSS_S_COMPLETE) {
		pgsserr("get_ids: gss_display_name",
			maj_stat, min_stat, mech);
		goto out;
	}
	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) {
		printerr(0, "WARNING: get_ids: error mapping mech to "
			"file for name '%s'\n", sname);
		goto out_free;
	}
	nfs4_init_name_mapping(NULL); /* XXX: should only do this once */
	res = nfs4_gss_princ_to_ids(secname, sname, &uid, &gid);
	if (res < 0) {
		/*
		 * -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(1, "WARNING: get_ids: failed to map name '%s' "
			"to uid/gid: %s\n", sname, strerror(-res));
		goto out_free;
	}
	cred->cr_uid = uid;
	cred->cr_gid = gid;
	add_supplementary_groups(secname, sname, cred);
	res = 0;
out_free:
	free(sname);
out:
	return res;
}