Пример #1
0
/*
 * Search the given keytab file looking for an entry with the given
 * service name and realm, ignoring hostname (instance).
 *
 * Returns:
 *	0 => No error
 *	non-zero => An error occurred
 *
 * If a keytab entry is found, "found" is set to one, and the keytab
 * entry is returned in "kte".  Otherwise, "found" is zero, and the
 * value of "kte" is unpredictable.
 */
static int gssd_search_krb5_keytab(krb5_context context, krb5_keytab kt,
				   const char *realm, const char *service,
				   int *found, krb5_keytab_entry *kte)
{
	krb5_kt_cursor cursor;
	krb5_error_code code;
	struct gssd_k5_kt_princ *ple;
	int retval = -1, status;
	char kt_name[BUFSIZ];
	char *pname;
	char *k5err = NULL;

	if (found == NULL) {
		retval = EINVAL;
		goto out;
	}
	*found = 0;

	/*
	 * Look through each entry in the keytab file and determine
	 * if we might want to use it as machine credentials.  If so,
	 * save info in the global principal list (gssd_k5_kt_princ_list).
	 */
	code = krb5_kt_get_name(context, kt, kt_name, BUFSIZ);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s attempting to get keytab name\n",
			 k5err);
		gsh_free(k5err);
		retval = code;
		goto out;
	}
	code = krb5_kt_start_seq_get(context, kt, &cursor);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0,
			 "ERROR: %s while beginning keytab scan "
			 "for keytab '%s'\n", k5err, kt_name);
		gsh_free(k5err);
		retval = code;
		goto out;
	}

	while ((code = krb5_kt_next_entry(context, kt, kte, &cursor)) == 0) {
		code = krb5_unparse_name(context, kte->principal, &pname);
		if (code != 0) {
			k5err = gssd_k5_err_msg(context, code);
			printerr(0,
				 "WARNING: Skipping keytab entry because "
				 "we failed to unparse principal name: %s\n",
				 k5err);
			k5_free_kt_entry(context, kte);
			gsh_free(k5err);
			continue;
		}
		printerr(4, "Processing keytab entry for principal '%s'\n",
			 pname);
		/* Use the first matching keytab entry found */
#ifdef HAVE_KRB5
		status =
		    realm_and_service_match(kte->principal, realm, service);
#else
		status =
		    realm_and_service_match(context, kte->principal, realm,
					    service);
#endif
		if (status) {
			printerr(4, "We WILL use this entry (%s)\n", pname);
			ple = get_ple_by_princ(context, kte->principal);
			/*
			 * Return, don't free, keytab entry if
			 * we were successful!
			 */
			if (ple == NULL) {
				retval = ENOMEM;
				k5_free_kt_entry(context, kte);
			} else {
				retval = 0;
				*found = 1;
			}
			k5_free_unparsed_name(context, pname);
			break;
		} else {
			printerr(4, "We will NOT use this entry (%s)\n", pname);
		}
		k5_free_unparsed_name(context, pname);
		k5_free_kt_entry(context, kte);
	}

	code = krb5_kt_end_seq_get(context, kt, &cursor);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0,
			 "WARNING: %s while ending keytab scan for "
			 "keytab '%s'\n", k5err, kt_name);
		gsh_free(k5err);
	}

	retval = 0;
 out:
	return retval;
}
Пример #2
0
/*
 * Obtain (or refresh if necessary) Kerberos machine credentials
 */
int gssd_refresh_krb5_machine_credential(char *hostname,
					 struct gssd_k5_kt_princ *ple,
					 char *service)
{
	krb5_error_code code = 0;
	krb5_context context;
	krb5_keytab kt = NULL;
	int retval = 0;
	char *k5err = NULL;
	const char *svcnames[5] = { "$", "root", "nfs", "host", NULL };

	/*
	 * If a specific service name was specified, use it.
	 * Otherwise, use the default list.
	 */
	if (service != NULL && strcmp(service, "*") != 0) {
		svcnames[0] = service;
		svcnames[1] = NULL;
	}
	if (hostname == NULL && ple == NULL)
		return EINVAL;

	code = krb5_init_context(&context);
	if (code) {
		k5err = gssd_k5_err_msg(NULL, code);
		printerr(0, "ERROR: %s: %s while initializing krb5 context\n",
			 __func__, k5err);
		retval = code;
		gsh_free(k5err);
		goto out_wo_context;
	}

	code = krb5_kt_resolve(context, keytabfile, &kt);
	if (code != 0) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s: %s while resolving keytab '%s'\n",
			 __func__, k5err, keytabfile);
		gsh_free(k5err);
		goto out;
	}

	if (ple == NULL) {
		krb5_keytab_entry kte;

		code = find_keytab_entry(context, kt, hostname, &kte,
					 svcnames);
		if (code) {
			printerr(0,
				 "ERROR: %s: no usable keytab entry found "
				 "in keytab %s for connection with host %s\n",
				 __func__, keytabfile, hostname);
			retval = code;
			goto out;
		}

		ple = get_ple_by_princ(context, kte.principal);
		k5_free_kt_entry(context, &kte);
		if (ple == NULL) {
			char *pname;
			if ((krb5_unparse_name(context, kte.principal,
					       &pname))) {
				pname = NULL;
			}
			printerr(0,
				 "ERROR: %s: Could not locate or create ple struct for principal %s for connection with host %s\n",
				 __func__,
				 pname ? pname : "<unparsable>", hostname);
			if (pname)
				k5_free_unparsed_name(context, pname);
			goto out;
		}
	}
	retval = gssd_get_single_krb5_cred(context, kt, ple, 0);
 out:
	if (kt)
		krb5_kt_close(context, kt);
	krb5_free_context(context);
 out_wo_context:
	return retval;
}
Пример #3
0
/*
 * Obtain (or refresh if necessary) Kerberos machine credentials
 */
int
gssd_refresh_krb5_machine_credential(char *hostname,
				     struct gssd_k5_kt_princ *ple)
{
	krb5_error_code code = 0;
	krb5_context context;
	krb5_keytab kt = NULL;;
	int retval = 0;
	char *k5err = NULL;

	if (hostname == NULL && ple == NULL)
		return EINVAL;

	code = krb5_init_context(&context);
	if (code) {
		k5err = gssd_k5_err_msg(NULL, code);
		printerr(0, "ERROR: %s: %s while initializing krb5 context\n",
			 __func__, k5err);
		retval = code;
		goto out;
	}

	if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
		k5err = gssd_k5_err_msg(context, code);
		printerr(0, "ERROR: %s: %s while resolving keytab '%s'\n",
			 __func__, k5err, keytabfile);
		goto out;
	}

	if (ple == NULL) {
		krb5_keytab_entry kte;

		code = find_keytab_entry(context, kt, hostname, &kte);
		if (code) {
			printerr(0, "ERROR: %s: no usable keytab entry found "
				 "in keytab %s for connection with host %s\n",
				 __FUNCTION__, keytabfile, hostname);
			retval = code;
			goto out;
		}

		ple = get_ple_by_princ(context, kte.principal);
		k5_free_kt_entry(context, &kte);
		if (ple == NULL) {
			char *pname;
			if ((krb5_unparse_name(context, kte.principal, &pname))) {
				pname = NULL;
			}
			printerr(0, "ERROR: %s: Could not locate or create "
				 "ple struct for principal %s for connection "
				 "with host %s\n",
				 __FUNCTION__, pname ? pname : "<unparsable>",
				 hostname);
			if (pname) k5_free_unparsed_name(context, pname);
			goto out;
		}
	}
	retval = gssd_get_single_krb5_cred(context, kt, ple);
out:
	if (kt)
		krb5_kt_close(context, kt);
	krb5_free_context(context);
	free(k5err);
	return retval;
}