gboolean
nm_active_connection_get_user_requested (NMActiveConnection *self)
{
	g_return_val_if_fail (NM_IS_ACTIVE_CONNECTION (self), FALSE);

	return nm_auth_subject_is_unix_process (NM_ACTIVE_CONNECTION_GET_PRIVATE (self)->subject);
}
static void
_audit_log_helper (NMAuditManager *self, GPtrArray *fields, const char *file,
                   guint line, const char *func, const char *op, gboolean result,
                   gpointer subject_context, const char *reason)
{
	AuditField op_field = { }, pid_field = { }, uid_field = { };
	AuditField result_field = { }, reason_field = { };
	gulong pid, uid;
	NMAuthSubject *subject = NULL;
	gs_unref_object NMAuthSubject *subject_free = NULL;

	_audit_field_init_string (&op_field, "op", op, FALSE, BACKEND_ALL);
	g_ptr_array_insert (fields, 0, &op_field);

	if (subject_context) {
		if (NM_IS_AUTH_SUBJECT (subject_context))
			subject = subject_context;
		else if (G_IS_DBUS_METHOD_INVOCATION (subject_context)) {
			GDBusMethodInvocation *context = subject_context;

			subject = subject_free = nm_auth_subject_new_unix_process_from_context (context);
		} else
			g_warn_if_reached ();
	}
	if (subject && nm_auth_subject_is_unix_process (subject)) {
		pid = nm_auth_subject_get_unix_process_pid (subject);
		uid = nm_auth_subject_get_unix_process_uid (subject);
		if (pid != G_MAXULONG) {
			_audit_field_init_uint (&pid_field, "pid", pid, BACKEND_ALL);
			g_ptr_array_add (fields, &pid_field);
		}
		if (uid != G_MAXULONG) {
			_audit_field_init_uint (&uid_field, "uid", uid, BACKEND_ALL);
			g_ptr_array_add (fields, &uid_field);
		}
	}

	_audit_field_init_string (&result_field, "result", result ? "success" : "fail",
	                          FALSE, BACKEND_ALL);
	g_ptr_array_add (fields, &result_field);

	if (reason) {
		_audit_field_init_string (&reason_field, "reason", reason, FALSE, BACKEND_LOG);
		g_ptr_array_add (fields, &reason_field);
	}

	nm_audit_log (self, fields, file, line, func, result);
}
NMSecretAgent *
nm_secret_agent_new (DBusGMethodInvocation *context,
                     NMAuthSubject *subject,
                     const char *identifier,
                     NMSecretAgentCapabilities capabilities)
{
	NMSecretAgent *self;
	NMSecretAgentPrivate *priv;
	char *hash_str, *username;
	struct passwd *pw;

	g_return_val_if_fail (context != NULL, NULL);
	g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
	g_return_val_if_fail (nm_auth_subject_is_unix_process (subject), NULL);
	g_return_val_if_fail (identifier != NULL, NULL);

	pw = getpwuid (nm_auth_subject_get_unix_process_uid (subject));
	g_return_val_if_fail (pw != NULL, NULL);
	g_return_val_if_fail (pw->pw_name[0] != '\0', NULL);
	username = g_strdup (pw->pw_name);

	self = (NMSecretAgent *) g_object_new (NM_TYPE_SECRET_AGENT, NULL);
	priv = NM_SECRET_AGENT_GET_PRIVATE (self);

	priv->identifier = g_strdup (identifier);
	priv->owner_username = g_strdup (username);
	priv->capabilities = capabilities;
	priv->subject = g_object_ref (subject);

	hash_str = g_strdup_printf ("%16lu%s", nm_auth_subject_get_unix_process_uid (subject), identifier);
	priv->hash = g_str_hash (hash_str);
	g_free (hash_str);

	priv->proxy = nm_dbus_manager_new_proxy (nm_dbus_manager_get (),
	                                         context,
	                                         nm_auth_subject_get_unix_process_dbus_sender (subject),
	                                         NM_DBUS_PATH_SECRET_AGENT,
	                                         NM_DBUS_INTERFACE_SECRET_AGENT);
	g_assert (priv->proxy);
	priv->proxy_destroy_id = g_signal_connect_swapped (priv->proxy, "destroy",
	                                                   G_CALLBACK (proxy_cleanup), self);

	g_free (username);
	return self;
}
gboolean
nm_auth_is_subject_in_acl (NMConnection *connection,
                           NMAuthSubject *subject,
                           char **out_error_desc)
{
	NMSettingConnection *s_con;
	const char *user = NULL;
	gulong uid;

	g_return_val_if_fail (connection != NULL, FALSE);
	g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), FALSE);
	g_return_val_if_fail (nm_auth_subject_is_internal (subject) || nm_auth_subject_is_unix_process (subject), FALSE);

	if (nm_auth_subject_is_internal (subject))
		return TRUE;

	uid = nm_auth_subject_get_unix_process_uid (subject);

	/* Root gets a free pass */
	if (0 == uid)
		return TRUE;

	if (!nm_session_monitor_uid_to_user (uid, &user)) {
		if (out_error_desc)
			*out_error_desc = g_strdup_printf ("Could not determine username for uid %lu", uid);
		return FALSE;
	}

	s_con = nm_connection_get_setting_connection (connection);
	if (!s_con) {
		/* This can only happen when called from AddAndActivate, so we know
		 * the user will be authorized when the connection is completed.
		 */
		return TRUE;
	}

	/* Match the username returned by the session check to a user in the ACL */
	if (!nm_setting_connection_permissions_user_allowed (s_con, user)) {
		if (out_error_desc)
			*out_error_desc = g_strdup_printf ("uid %lu has no permission to perform this operation", uid);
		return FALSE;
	}

	return TRUE;
}
void
nm_auth_chain_add_call (NMAuthChain *self,
                        const char *permission,
                        gboolean allow_interaction)
{
	AuthCall *call;
	NMAuthManager *auth_manager = nm_auth_manager_get ();

	g_return_if_fail (self != NULL);
	g_return_if_fail (permission && *permission);
	g_return_if_fail (self->subject);
	g_return_if_fail (nm_auth_subject_is_unix_process (self->subject) || nm_auth_subject_is_internal (self->subject));
	g_return_if_fail (!self->idle_id && !self->done);

	call = auth_call_new (self, permission);
	self->calls = g_slist_append (self->calls, call);

	if (   nm_auth_subject_is_internal (self->subject)
	    || nm_auth_subject_get_unix_process_uid (self->subject) == 0
	    || !nm_auth_manager_get_polkit_enabled (auth_manager)) {
		/* Root user or non-polkit always gets the permission */
		nm_auth_chain_set_data (self, permission, GUINT_TO_POINTER (NM_AUTH_CALL_RESULT_YES), NULL);
		call->call_idle_id = g_idle_add ((GSourceFunc) auth_call_complete, call);
	} else {
		/* Non-root always gets authenticated when using polkit */
#if WITH_POLKIT
		call->cancellable = g_cancellable_new ();
		nm_auth_manager_polkit_authority_check_authorization (auth_manager,
		                                                      self->subject,
		                                                      permission,
		                                                      allow_interaction,
		                                                      call->cancellable,
		                                                      pk_call_cb,
		                                                      call);
#else
		if (!call->chain->error) {
			call->chain->error = g_error_new_literal (DBUS_GERROR,
			                                          DBUS_GERROR_FAILED,
			                                          "Polkit support is disabled at compile time");
		}
		call->call_idle_id = g_idle_add ((GSourceFunc) auth_call_complete, call);
#endif
	}
}
/* Requires an NMAuthSubject */
NMAuthChain *
nm_auth_chain_new_subject (NMAuthSubject *subject,
                           GDBusMethodInvocation *context,
                           NMAuthChainResultFunc done_func,
                           gpointer user_data)
{
	NMAuthChain *self;

	g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
	g_return_val_if_fail (nm_auth_subject_is_unix_process (subject) || nm_auth_subject_is_internal (subject), NULL);

	self = g_slice_new0 (NMAuthChain);
	self->refcount = 1;
	self->data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, chain_data_free);
	self->done_func = done_func;
	self->user_data = user_data;
	self->context = context ? g_object_ref (context) : NULL;
	self->subject = g_object_ref (subject);

	return self;
}