nmt-secret-agent.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
  2. /*
  3. * This program is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU General Public License as
  5. * published by the Free Software Foundation; either version 2 of the
  6. * License, or (at your option) any later version.
  7. *
  8. * This program is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. * Copyright 2011-2013 Red Hat, Inc.
  17. * Copyright 2011 Giovanni Campagna <scampa.giovanni@gmail.com>
  18. */
  19. /**
  20. * SECTION:nmt-secret-agent
  21. * @short_description: A secret agent
  22. *
  23. * #NmtSecretAgent is the secret agent used by nmtui-connect.
  24. *
  25. * This is a stripped-down version of gnome-shell's ShellNetworkAgent,
  26. * with bits of the corresponding JavaScript code squished down into
  27. * it. It is intended to eventually be generic enough that it could
  28. * replace ShellNetworkAgent.
  29. */
  30. #include "config.h"
  31. #include <string.h>
  32. #include <dbus/dbus-glib.h>
  33. #include <glib/gi18n-lib.h>
  34. #include <nm-utils.h>
  35. #include "nmt-secret-agent.h"
  36. #include "nmt-newt.h"
  37. G_DEFINE_TYPE (NmtSecretAgent, nmt_secret_agent, NM_TYPE_SECRET_AGENT)
  38. #define NMT_SECRET_AGENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NMT_TYPE_SECRET_AGENT, NmtSecretAgentPrivate))
  39. enum {
  40. REQUEST_SECRETS,
  41. LAST_SIGNAL
  42. };
  43. static guint signals[LAST_SIGNAL] = { 0 };
  44. typedef struct {
  45. NmtSecretAgent *self;
  46. gchar *request_id;
  47. NMConnection *connection;
  48. gchar **hints;
  49. NMSecretAgentGetSecretsFunc callback;
  50. gpointer callback_data;
  51. } NmtSecretAgentRequest;
  52. typedef struct {
  53. /* <char *request_id, NmtSecretAgentRequest *request> */
  54. GHashTable *requests;
  55. } NmtSecretAgentPrivate;
  56. static void
  57. nmt_secret_agent_request_free (gpointer data)
  58. {
  59. NmtSecretAgentRequest *request = data;
  60. g_object_unref (request->self);
  61. g_object_unref (request->connection);
  62. g_strfreev (request->hints);
  63. g_slice_free (NmtSecretAgentRequest, request);
  64. }
  65. static void
  66. nmt_secret_agent_init (NmtSecretAgent *agent)
  67. {
  68. NmtSecretAgentPrivate *priv = NMT_SECRET_AGENT_GET_PRIVATE (agent);
  69. priv->requests = g_hash_table_new_full (g_str_hash, g_str_equal,
  70. g_free, nmt_secret_agent_request_free);
  71. }
  72. static void
  73. nmt_secret_agent_finalize (GObject *object)
  74. {
  75. NmtSecretAgentPrivate *priv = NMT_SECRET_AGENT_GET_PRIVATE (object);
  76. GError *error;
  77. GHashTableIter iter;
  78. gpointer key;
  79. gpointer value;
  80. error = g_error_new (NM_SECRET_AGENT_ERROR,
  81. NM_SECRET_AGENT_ERROR_AGENT_CANCELED,
  82. "The secret agent is going away");
  83. g_hash_table_iter_init (&iter, priv->requests);
  84. while (g_hash_table_iter_next (&iter, &key, &value)) {
  85. NmtSecretAgentRequest *request = value;
  86. request->callback (NM_SECRET_AGENT (object),
  87. request->connection,
  88. NULL, error,
  89. request->callback_data);
  90. }
  91. g_hash_table_destroy (priv->requests);
  92. g_error_free (error);
  93. G_OBJECT_CLASS (nmt_secret_agent_parent_class)->finalize (object);
  94. }
  95. static gboolean
  96. strv_has (gchar **haystack,
  97. gchar *needle)
  98. {
  99. gchar *iter;
  100. for (iter = *haystack; iter; iter++) {
  101. if (g_strcmp0 (iter, needle) == 0)
  102. return TRUE;
  103. }
  104. return FALSE;
  105. }
  106. /**
  107. * NmtSecretAgentSecret:
  108. * @name: the user-visible name of the secret. Eg, "WEP Passphrase".
  109. * @value: the value of the secret
  110. * @password: %TRUE if this secret represents a password, %FALSE
  111. * if it represents non-secret data.
  112. *
  113. * A single "secret" being requested.
  114. */
  115. typedef struct {
  116. NmtSecretAgentSecret base;
  117. NMSetting *setting;
  118. char *property;
  119. NmtNewtEntryValidator validator;
  120. gpointer validator_data;
  121. } NmtSecretAgentSecretReal;
  122. static void
  123. nmt_secret_agent_secret_free (NmtSecretAgentSecret *secret)
  124. {
  125. NmtSecretAgentSecretReal *real = (NmtSecretAgentSecretReal *)secret;
  126. g_free (secret->name);
  127. g_free (secret->value);
  128. g_free (real->property);
  129. g_clear_object (&real->setting);
  130. g_slice_free (NmtSecretAgentSecretReal, real);
  131. }
  132. static NmtSecretAgentSecret *
  133. nmt_secret_agent_secret_new (const char *name,
  134. NMSetting *setting,
  135. const char *property,
  136. gboolean password)
  137. {
  138. NmtSecretAgentSecretReal *real;
  139. real = g_slice_new0 (NmtSecretAgentSecretReal);
  140. real->base.name = g_strdup (name);
  141. real->base.password = password;
  142. if (setting) {
  143. real->setting = g_object_ref (setting);
  144. real->property = g_strdup (property);
  145. g_object_get (setting, property, &real->base.value, NULL);
  146. }
  147. return &real->base;
  148. }
  149. static gboolean
  150. add_8021x_secrets (NmtSecretAgentRequest *request,
  151. GPtrArray *secrets)
  152. {
  153. NMSetting8021x *s_8021x = nm_connection_get_setting_802_1x (request->connection);
  154. const char *eap_method;
  155. NmtSecretAgentSecret *secret;
  156. eap_method = nm_setting_802_1x_get_eap_method (s_8021x, 0);
  157. if (!eap_method)
  158. return FALSE;
  159. if ( !strcmp (eap_method, "md5")
  160. || !strcmp (eap_method, "leap")
  161. || !strcmp (eap_method, "ttls")
  162. || !strcmp (eap_method, "peap")) {
  163. /* TTLS and PEAP are actually much more complicated, but this complication
  164. * is not visible here since we only care about phase2 authentication
  165. * (and don't even care of which one)
  166. */
  167. secret = nmt_secret_agent_secret_new (_("Username"),
  168. NM_SETTING (s_8021x),
  169. NM_SETTING_802_1X_IDENTITY,
  170. FALSE);
  171. g_ptr_array_add (secrets, secret);
  172. secret = nmt_secret_agent_secret_new (_("Password"),
  173. NM_SETTING (s_8021x),
  174. NM_SETTING_802_1X_PASSWORD,
  175. TRUE);
  176. g_ptr_array_add (secrets, secret);
  177. return TRUE;
  178. }
  179. if (!strcmp (eap_method, "tls")) {
  180. secret = nmt_secret_agent_secret_new (_("Identity"),
  181. NM_SETTING (s_8021x),
  182. NM_SETTING_802_1X_IDENTITY,
  183. FALSE);
  184. g_ptr_array_add (secrets, secret);
  185. secret = nmt_secret_agent_secret_new (_("Private key password"),
  186. NM_SETTING (s_8021x),
  187. NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD,
  188. TRUE);
  189. g_ptr_array_add (secrets, secret);
  190. return TRUE;
  191. }
  192. return FALSE;
  193. }
  194. static gboolean
  195. add_wireless_secrets (NmtSecretAgentRequest *request,
  196. GPtrArray *secrets)
  197. {
  198. NMSettingWirelessSecurity *s_wsec = nm_connection_get_setting_wireless_security (request->connection);
  199. const char *key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
  200. NmtSecretAgentSecret *secret;
  201. if (!key_mgmt)
  202. return FALSE;
  203. if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) {
  204. secret = nmt_secret_agent_secret_new (_("Password"),
  205. NM_SETTING (s_wsec),
  206. NM_SETTING_WIRELESS_SECURITY_PSK,
  207. TRUE);
  208. g_ptr_array_add (secrets, secret);
  209. return TRUE;
  210. }
  211. if (!strcmp (key_mgmt, "none")) {
  212. int index;
  213. char *key;
  214. index = nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec);
  215. key = g_strdup_printf ("wep-key%d", index);
  216. secret = nmt_secret_agent_secret_new (_("Key"),
  217. NM_SETTING (s_wsec),
  218. key,
  219. TRUE);
  220. g_free (key);
  221. #if 0
  222. nmt_secret_agent_secret_set_validator (secret, static_wep_key_validate,
  223. nm_setting_wireless_security_get_wep_key_type (s_wsec));
  224. #endif
  225. g_ptr_array_add (secrets, secret);
  226. return TRUE;
  227. }
  228. if (!strcmp (key_mgmt, "iee8021x")) {
  229. if (!g_strcmp0 (nm_setting_wireless_security_get_auth_alg (s_wsec), "leap")) {
  230. secret = nmt_secret_agent_secret_new (_("Password"),
  231. NM_SETTING (s_wsec),
  232. NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
  233. TRUE);
  234. g_ptr_array_add (secrets, secret);
  235. return TRUE;
  236. } else
  237. return add_8021x_secrets (request, secrets);
  238. }
  239. if (!strcmp (key_mgmt, "wpa-eap"))
  240. return add_8021x_secrets (request, secrets);
  241. return FALSE;
  242. }
  243. static gboolean
  244. add_pppoe_secrets (NmtSecretAgentRequest *request,
  245. GPtrArray *secrets)
  246. {
  247. NMSettingPPPOE *s_pppoe = nm_connection_get_setting_pppoe (request->connection);
  248. NmtSecretAgentSecret *secret;
  249. secret = nmt_secret_agent_secret_new (_("Username"),
  250. NM_SETTING (s_pppoe),
  251. NM_SETTING_PPPOE_USERNAME,
  252. FALSE);
  253. g_ptr_array_add (secrets, secret);
  254. secret = nmt_secret_agent_secret_new (_("Service"),
  255. NM_SETTING (s_pppoe),
  256. NM_SETTING_PPPOE_SERVICE,
  257. FALSE);
  258. g_ptr_array_add (secrets, secret);
  259. secret = nmt_secret_agent_secret_new (_("Password"),
  260. NM_SETTING (s_pppoe),
  261. NM_SETTING_PPPOE_PASSWORD,
  262. TRUE);
  263. g_ptr_array_add (secrets, secret);
  264. return TRUE;
  265. }
  266. static void
  267. request_secrets_from_ui (NmtSecretAgentRequest *request)
  268. {
  269. GPtrArray *secrets;
  270. NmtSecretAgentSecret *secret;
  271. const char *title;
  272. char *msg;
  273. gboolean ok = TRUE;
  274. secrets = g_ptr_array_new_with_free_func ((GDestroyNotify) nmt_secret_agent_secret_free);
  275. if (nm_connection_is_type (request->connection, NM_SETTING_WIRELESS_SETTING_NAME)) {
  276. NMSettingWireless *s_wireless;
  277. char *ssid;
  278. s_wireless = nm_connection_get_setting_wireless (request->connection);
  279. ssid = nm_utils_ssid_to_utf8 (nm_setting_wireless_get_ssid (s_wireless));
  280. title = _("Authentication required by wireless network");
  281. msg = g_strdup_printf (_("Passwords or encryption keys are required to access the wireless network '%s'."), ssid);
  282. ok = add_wireless_secrets (request, secrets);
  283. } else if (nm_connection_is_type (request->connection, NM_SETTING_WIRED_SETTING_NAME)) {
  284. NMSettingConnection *s_con;
  285. s_con = nm_connection_get_setting_connection (request->connection);
  286. title = _("Wired 802.1X authentication");
  287. msg = NULL;
  288. secret = nmt_secret_agent_secret_new (_("Network name"),
  289. NM_SETTING (s_con),
  290. NM_SETTING_CONNECTION_ID,
  291. FALSE);
  292. g_ptr_array_add (secrets, secret);
  293. ok = add_8021x_secrets (request, secrets);
  294. } else if (nm_connection_is_type (request->connection, NM_SETTING_PPPOE_SETTING_NAME)) {
  295. title = _("DSL authentication");
  296. msg = NULL;
  297. ok = add_pppoe_secrets (request, secrets);
  298. } else if (nm_connection_is_type (request->connection, NM_SETTING_GSM_SETTING_NAME)) {
  299. NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (request->connection);
  300. if (strv_has (request->hints, "pin")) {
  301. title = _("PIN code required");
  302. msg = g_strdup (_("PIN code is needed for the mobile broadband device"));
  303. secret = nmt_secret_agent_secret_new (_("PIN"),
  304. NM_SETTING (s_gsm),
  305. NM_SETTING_GSM_PIN,
  306. FALSE);
  307. g_ptr_array_add (secrets, secret);
  308. } else {
  309. title = _("Mobile broadband network password");
  310. msg = g_strdup_printf (_("A password is required to connect to '%s'."),
  311. nm_connection_get_id (request->connection));
  312. secret = nmt_secret_agent_secret_new (_("Password"),
  313. NM_SETTING (s_gsm),
  314. NM_SETTING_GSM_PASSWORD,
  315. TRUE);
  316. g_ptr_array_add (secrets, secret);
  317. }
  318. } else if (nm_connection_is_type (request->connection, NM_SETTING_CDMA_SETTING_NAME)) {
  319. NMSettingCdma *s_cdma = nm_connection_get_setting_cdma (request->connection);
  320. title = _("Mobile broadband network password");
  321. msg = g_strdup_printf (_("A password is required to connect to '%s'."),
  322. nm_connection_get_id (request->connection));
  323. secret = nmt_secret_agent_secret_new (_("Password"),
  324. NM_SETTING (s_cdma),
  325. NM_SETTING_CDMA_PASSWORD,
  326. TRUE);
  327. g_ptr_array_add (secrets, secret);
  328. } else if (nm_connection_is_type (request->connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) {
  329. NMSetting *setting;
  330. setting = nm_connection_get_setting_by_name (request->connection, NM_SETTING_GSM_SETTING_NAME);
  331. if (!setting)
  332. setting = nm_connection_get_setting_by_name (request->connection, NM_SETTING_CDMA_SETTING_NAME);
  333. title = _("Mobile broadband network password");
  334. msg = g_strdup_printf (_("A password is required to connect to '%s'."),
  335. nm_connection_get_id (request->connection));
  336. secret = nmt_secret_agent_secret_new (_("Password"),
  337. setting,
  338. "password",
  339. TRUE);
  340. g_ptr_array_add (secrets, secret);
  341. } else
  342. ok = FALSE;
  343. if (!ok) {
  344. g_ptr_array_unref (secrets);
  345. return;
  346. }
  347. g_signal_emit (request->self, signals[REQUEST_SECRETS], 0,
  348. request->request_id, title, msg, secrets);
  349. }
  350. static void
  351. nmt_secret_agent_get_secrets (NMSecretAgent *agent,
  352. NMConnection *connection,
  353. const gchar *connection_path,
  354. const gchar *setting_name,
  355. const gchar **hints,
  356. NMSecretAgentGetSecretsFlags flags,
  357. NMSecretAgentGetSecretsFunc callback,
  358. gpointer callback_data)
  359. {
  360. NmtSecretAgent *self = NMT_SECRET_AGENT (agent);
  361. NmtSecretAgentPrivate *priv = NMT_SECRET_AGENT_GET_PRIVATE (self);
  362. NmtSecretAgentRequest *request;
  363. NMSettingConnection *s_con;
  364. const char *connection_type;
  365. char *request_id;
  366. GError *error;
  367. request_id = g_strdup_printf ("%s/%s", connection_path, setting_name);
  368. if (g_hash_table_lookup (priv->requests, request_id) != NULL) {
  369. /* We already have a request pending for this (connection, setting) */
  370. error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_INTERNAL_ERROR,
  371. "Request for %s secrets already pending", request_id);
  372. nope:
  373. callback (agent, connection, NULL, error, callback_data);
  374. g_error_free (error);
  375. g_free (request_id);
  376. return;
  377. }
  378. s_con = nm_connection_get_setting_connection (connection);
  379. connection_type = nm_setting_connection_get_connection_type (s_con);
  380. if (!strcmp (connection_type, NM_SETTING_VPN_SETTING_NAME)) {
  381. /* We don't support VPN secrets yet */
  382. error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_NO_SECRETS,
  383. "VPN secrets not supported");
  384. goto nope;
  385. }
  386. if (!(flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION)) {
  387. /* We don't do stored passwords */
  388. error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_NO_SECRETS,
  389. "Stored passwords not supported");
  390. goto nope;
  391. }
  392. request = g_slice_new (NmtSecretAgentRequest);
  393. request->self = g_object_ref (self);
  394. request->connection = g_object_ref (connection);
  395. request->hints = g_strdupv ((gchar **)hints);
  396. request->callback = callback;
  397. request->callback_data = callback_data;
  398. request->request_id = request_id;
  399. g_hash_table_replace (priv->requests, request->request_id, request);
  400. request_secrets_from_ui (request);
  401. }
  402. static void
  403. gvalue_destroy_notify (gpointer data)
  404. {
  405. GValue *value = data;
  406. g_value_unset (value);
  407. g_slice_free (GValue, value);
  408. }
  409. /**
  410. * nmt_secret_agent_response:
  411. * @self: the #NmtSecretAgent
  412. * @request_id: the request ID being responded to
  413. * @secrets: (allow-none): the array of secrets, or %NULL
  414. *
  415. * Response to a #NmtSecretAgent::get-secrets signal.
  416. *
  417. * If the user provided secrets, the caller should set the
  418. * corresponding <literal>value</literal> fields in the
  419. * #NmtSecretAgentSecrets (freeing any initial values they had), and
  420. * pass the array to nmt_secret_agent_response(). If the user
  421. * cancelled the request, @secrets should be NULL.
  422. */
  423. void
  424. nmt_secret_agent_response (NmtSecretAgent *self,
  425. const char *request_id,
  426. GPtrArray *secrets)
  427. {
  428. NmtSecretAgentPrivate *priv;
  429. NmtSecretAgentRequest *request;
  430. GHashTable *hash = NULL, *setting_hash;
  431. GValue *value;
  432. GError *error = NULL;
  433. int i;
  434. g_return_if_fail (NMT_IS_SECRET_AGENT (self));
  435. priv = NMT_SECRET_AGENT_GET_PRIVATE (self);
  436. request = g_hash_table_lookup (priv->requests, request_id);
  437. g_return_if_fail (request != NULL);
  438. if (secrets) {
  439. hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_hash_table_unref);
  440. for (i = 0; i < secrets->len; i++) {
  441. NmtSecretAgentSecretReal *secret = secrets->pdata[i];
  442. setting_hash = g_hash_table_lookup (hash, nm_setting_get_name (secret->setting));
  443. if (!setting_hash) {
  444. setting_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
  445. g_free, gvalue_destroy_notify);
  446. g_hash_table_insert (hash, (char *)nm_setting_get_name (secret->setting),
  447. setting_hash);
  448. }
  449. value = g_slice_new0 (GValue);
  450. g_value_init (value, G_TYPE_STRING);
  451. g_value_set_string (value, secret->base.value);
  452. g_hash_table_insert (setting_hash, g_strdup (secret->property), value);
  453. }
  454. } else {
  455. error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_USER_CANCELED,
  456. "User cancelled");
  457. }
  458. request->callback (NM_SECRET_AGENT (self), request->connection, hash, error, request->callback_data);
  459. g_clear_pointer (&hash, g_hash_table_unref);
  460. g_clear_error (&error);
  461. g_hash_table_remove (priv->requests, request_id);
  462. }
  463. static void
  464. nmt_secret_agent_cancel_get_secrets (NMSecretAgent *agent,
  465. const gchar *connection_path,
  466. const gchar *setting_name)
  467. {
  468. /* We don't support cancellation. Sorry! */
  469. }
  470. static void
  471. nmt_secret_agent_save_secrets (NMSecretAgent *agent,
  472. NMConnection *connection,
  473. const gchar *connection_path,
  474. NMSecretAgentSaveSecretsFunc callback,
  475. gpointer callback_data)
  476. {
  477. /* We don't support secret storage */
  478. callback (agent, connection, NULL, callback_data);}
  479. static void
  480. nmt_secret_agent_delete_secrets (NMSecretAgent *agent,
  481. NMConnection *connection,
  482. const gchar *connection_path,
  483. NMSecretAgentDeleteSecretsFunc callback,
  484. gpointer callback_data)
  485. {
  486. /* We don't support secret storage, so there's nothing to delete. */
  487. callback (agent, connection, NULL, callback_data);
  488. }
  489. void
  490. nmt_secret_agent_class_init (NmtSecretAgentClass *klass)
  491. {
  492. GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
  493. NMSecretAgentClass *agent_class = NM_SECRET_AGENT_CLASS (klass);
  494. g_type_class_add_private (klass, sizeof (NmtSecretAgentPrivate));
  495. gobject_class->finalize = nmt_secret_agent_finalize;
  496. agent_class->get_secrets = nmt_secret_agent_get_secrets;
  497. agent_class->cancel_get_secrets = nmt_secret_agent_cancel_get_secrets;
  498. agent_class->save_secrets = nmt_secret_agent_save_secrets;
  499. agent_class->delete_secrets = nmt_secret_agent_delete_secrets;
  500. /**
  501. * NmtSecretAgent::request-secrets:
  502. * @agent: the #NmtSecretAgent
  503. * @request_id: request ID, to eventually pass to
  504. * nmt_secret_agent_response().
  505. * @title: a title for the password dialog
  506. * @prompt: a prompt message for the password dialog
  507. * @secrets: (element-type #NmtSecretAgentSecret): array of secrets
  508. * being requested.
  509. *
  510. * Emitted when the agent requires secrets from the user.
  511. *
  512. * The application should create a password dialog (eg,
  513. * #NmtPasswordDialog) with the given title and prompt, and an
  514. * entry for each element of @secrets. If any of the secrets
  515. * already have a <literal>value</literal> filled in, the
  516. * corresponding entry should be initialized to that value.
  517. *
  518. * When the dialog is complete, the app must call
  519. * nmt_secret_agent_response() with the results.
  520. */
  521. signals[REQUEST_SECRETS] = g_signal_new ("request-secrets",
  522. G_TYPE_FROM_CLASS (klass),
  523. 0, 0, NULL, NULL, NULL,
  524. G_TYPE_NONE,
  525. 4,
  526. G_TYPE_STRING, /* request_id */
  527. G_TYPE_STRING, /* title */
  528. G_TYPE_STRING, /* prompt */
  529. G_TYPE_PTR_ARRAY);
  530. }
  531. /**
  532. * nmt_secret_agent_new:
  533. *
  534. * Creates a new #NmtSecretAgent.
  535. *
  536. * Returns: a new #NmtSecretAgent
  537. */
  538. NMSecretAgent *
  539. nmt_secret_agent_new (void)
  540. {
  541. return g_object_new (NMT_TYPE_SECRET_AGENT,
  542. NM_SECRET_AGENT_IDENTIFIER, "nmtui",
  543. NM_SECRET_AGENT_AUTO_REGISTER, FALSE,
  544. NULL);
  545. }