Exemplo n.º 1
0
int
gssd_acquire_cred(char *server_name, const gss_OID oid)
{
	gss_buffer_desc name;
	gss_name_t target_name;
	u_int32_t maj_stat, min_stat;
	u_int32_t ignore_maj_stat, ignore_min_stat;
	gss_buffer_desc pbuf;

	/* If server_name is NULL, get cred for GSS_C_NO_NAME */
	if (server_name == NULL) {
		target_name = GSS_C_NO_NAME;
	} else {
		name.value = (void *)server_name;
		name.length = strlen(server_name);

		maj_stat = gss_import_name(&min_stat, &name,
				oid,
				&target_name);

		if (maj_stat != GSS_S_COMPLETE) {
			pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid);
			return (FALSE);
		}
	}

	maj_stat = gss_acquire_cred(&min_stat, target_name, GSS_C_INDEFINITE,
			GSS_C_NO_OID_SET, GSS_C_ACCEPT,
			&gssd_creds, NULL, NULL);

	if (maj_stat != GSS_S_COMPLETE) {
		pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid);
		ignore_maj_stat = gss_display_name(&ignore_min_stat,
				target_name, &pbuf, NULL);
		if (ignore_maj_stat == GSS_S_COMPLETE) {
			printerr(1, "Unable to obtain credentials for '%.*s'\n",
				 pbuf.length, pbuf.value);
			ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
							     &pbuf);
		}
	}

	ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name);

	return (maj_stat == GSS_S_COMPLETE);
}
Exemplo n.º 2
0
int
svcgssd_limit_krb5_enctypes(void)
{
	u_int maj_stat, min_stat;
	krb5_enctype old_kernel_enctypes[] = {
		ENCTYPE_DES_CBC_CRC,
		ENCTYPE_DES_CBC_MD5,
		ENCTYPE_DES_CBC_MD4 };
	krb5_enctype new_kernel_enctypes[] = {
		ENCTYPE_AES256_CTS_HMAC_SHA1_96,
		ENCTYPE_AES128_CTS_HMAC_SHA1_96,
		ENCTYPE_DES3_CBC_SHA1,
		ENCTYPE_ARCFOUR_HMAC,
		ENCTYPE_DES_CBC_CRC,
		ENCTYPE_DES_CBC_MD5,
		ENCTYPE_DES_CBC_MD4 };
	krb5_enctype *default_enctypes, *enctypes;
	int default_num_enctypes, num_enctypes;


	if (linux_version_code() < MAKE_VERSION(2, 6, 35)) {
		default_enctypes = old_kernel_enctypes;
		default_num_enctypes =
			sizeof(old_kernel_enctypes) / sizeof(old_kernel_enctypes[0]);
	} else {
		default_enctypes = new_kernel_enctypes;
		default_num_enctypes =
			sizeof(new_kernel_enctypes) / sizeof(new_kernel_enctypes[0]);
	}

	get_kernel_supported_enctypes();

	if (parsed_enctypes != NULL) {
		enctypes = parsed_enctypes;
		num_enctypes = parsed_num_enctypes;
		printerr(2, "%s: Calling gss_set_allowable_enctypes with %d "
			"enctypes from the kernel\n", __func__, num_enctypes);
	} else {
		enctypes = default_enctypes;
		num_enctypes = default_num_enctypes;
		printerr(2, "%s: Calling gss_set_allowable_enctypes with %d "
			"enctypes from defaults\n", __func__, num_enctypes);
	}

	maj_stat = set_allowable_enctypes(&min_stat, gssd_creds,
			&krb5oid, num_enctypes, enctypes);
	if (maj_stat != GSS_S_COMPLETE) {
		printerr(1, "WARNING: gss_set_allowable_enctypes failed\n");
		pgsserr("svcgssd_limit_krb5_enctypes: gss_set_allowable_enctypes",
			maj_stat, min_stat, &krb5oid);
		return -1;
	}
	return 0;
}
Exemplo n.º 3
0
int
limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
{
	u_int maj_stat, min_stat;
	gss_cred_id_t credh;
	gss_OID_set_desc  desired_mechs;
	krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC,
				    ENCTYPE_DES_CBC_MD5,
				    ENCTYPE_DES_CBC_MD4 };
	int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);

	/* We only care about getting a krb5 cred */
	desired_mechs.count = 1;
	desired_mechs.elements = &krb5oid;

	maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
				    &desired_mechs, GSS_C_INITIATE,
				    &credh, NULL, NULL);

	if (maj_stat != GSS_S_COMPLETE) {
		if (get_verbosity() > 0)
			pgsserr("gss_acquire_cred",
				maj_stat, min_stat, &krb5oid);
		return -1;
	}

	maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
					     num_enctypes, &enctypes);
	if (maj_stat != GSS_S_COMPLETE) {
		pgsserr("gss_set_allowable_enctypes",
			maj_stat, min_stat, &krb5oid);
		gss_release_cred(&min_stat, &credh);
		return -1;
	}
	sec->cred = credh;

	return 0;
}
Exemplo n.º 4
0
static int
get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
			  char **hostbased_name)
{
	u_int32_t	maj_stat, min_stat;
	gss_buffer_desc	name;
	gss_OID		name_type = GSS_C_NO_OID;
	char		*cname;
	int		res = -1;

	*hostbased_name = NULL;	    /* preset in case we fail */

	/* Get the client's gss authenticated name */
	maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
	if (maj_stat != GSS_S_COMPLETE) {
		pgsserr("get_hostbased_client_name: gss_display_name",
			maj_stat, min_stat, mech);
		goto out_err;
	}
	if (name.length >= 0xffff) {	    /* don't overflow */
		printerr(0, "ERROR: get_hostbased_client_name: "
			 "received gss_name is too long (%d bytes)\n",
			 name.length);
		goto out_rel_buf;
	}

	/* For Kerberos, transform the NT_KRB5_PRINCIPAL name to
	 * an NT_HOSTBASED_SERVICE name */
	if (g_OID_equal(&krb5oid, mech)) {
		if (get_krb5_hostbased_name(&name, &cname) == 0)
			*hostbased_name = cname;
	}

	/* No support for SPKM3, just print a warning (for now) */
	if (g_OID_equal(&spkm3oid, mech)) {
		printerr(1, "WARNING: get_hostbased_client_name: "
			 "no hostbased_name support for SPKM3\n");
	}

	res = 0;
out_rel_buf:
	gss_release_buffer(&min_stat, &name);
out_err:
	return res;
}
Exemplo n.º 5
0
int
serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
{
	OM_uint32 maj_stat, min_stat;
	void *return_ctx = 0;
	OM_uint32 vers;
	gss_krb5_lucid_context_v1_t *lctx = 0;
	int retcode = 0;

	printerr(3, "lucid version!\n");
	maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
						1, &return_ctx);
	if (maj_stat != GSS_S_COMPLETE) {
		pgsserr("gss_export_lucid_sec_context",
			maj_stat, min_stat, &krb5oid);
		goto out_err;
	}

	/* Check the version returned, we only support v1 right now */
	vers = ((gss_krb5_lucid_context_version_t *)return_ctx)->version;
	switch (vers) {
	case 1:
		lctx = (gss_krb5_lucid_context_v1_t *) return_ctx;
		break;
	default:
		printerr(0, "ERROR: unsupported lucid sec context version %d\n",
			vers);
		goto out_err;
		break;
	}

        /*
	 * Now lctx points to a lucid context that we can send down to kernel
	 *
	 * Note: we send down different information to the kernel depending
	 * on the protocol version and the enctyption type.
	 * For protocol version 0 with all enctypes besides DES3, we use
	 * the original format.  For protocol version != 0 or DES3, we
	 * send down the new style information.
	 */

	if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4)
		retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
	else
		retcode = prepare_krb5_rfc4121_buffer(lctx, buf);

	maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
	if (maj_stat != GSS_S_COMPLETE) {
		pgsserr("gss_export_lucid_sec_context",
			maj_stat, min_stat, &krb5oid);
		printerr(0, "WARN: failed to free lucid sec context\n");
	}

	if (retcode) {
		printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n",
			 __FUNCTION__, retcode);
		goto out_err;
	}

	return 0;

out_err:
	printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
	return -1;
}
Exemplo n.º 6
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;
}