user-accounts: Implement enterprise logins in add dialog
* Use realmd for domain joining and lookup, runtime dependency * Validate join domain correctly * Add UmRealmManager for handling some stuff above the autogenerated realmd dbus code * Show a dialog if the user's credentials cannot be used to join the domain. Prompt for admin creds. * Register the user's login with the AccountsService * This depends on the CacheUser() method of AccountsService https://bugzilla.gnome.org/show_bug.cgi?id=677548
This commit is contained in:
parent
06233ebba8
commit
4bb0739670
8 changed files with 1969 additions and 21 deletions
17
configure.ac
17
configure.ac
|
@ -225,6 +225,23 @@ PKG_CHECK_MODULES(ISOCODES, iso-codes)
|
||||||
AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX],["`$PKG_CONFIG --variable=prefix iso-codes`"],[ISO codes prefix])
|
AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX],["`$PKG_CONFIG --variable=prefix iso-codes`"],[ISO codes prefix])
|
||||||
ISO_CODES=iso-codes
|
ISO_CODES=iso-codes
|
||||||
|
|
||||||
|
# Kerberos kerberos support
|
||||||
|
AC_PATH_PROG(KRB5_CONFIG, krb5-config, no)
|
||||||
|
if test "$KRB5_CONFIG" = "no"; then
|
||||||
|
AC_MSG_ERROR([krb5-config executable not found in your path - should be installed with the kerberos libraries])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(for krb5 libraries and flags)
|
||||||
|
KRB5_CFLAGS="`$KRB5_CONFIG --cflags`"
|
||||||
|
KRB5_LIBS="`$KRB5_CONFIG --libs`"
|
||||||
|
AC_MSG_RESULT($KRB5_CFLAGS $KRB5_LIBS)
|
||||||
|
|
||||||
|
AC_SUBST(KRB5_CFLAGS)
|
||||||
|
AC_SUBST(KRB5_LIBS)
|
||||||
|
|
||||||
|
USER_ACCOUNTS_PANEL_CFLAGS="$USER_ACCOUNTS_PANEL_CFLAGS $KRB5_CFLAGS"
|
||||||
|
USER_ACCOUNTS_PANEL_LIBS="$USER_ACCOUNTS_PANEL_LIBS $KRB5_LIBS"
|
||||||
|
|
||||||
dnl ==============================================
|
dnl ==============================================
|
||||||
dnl End: Check that we meet the dependencies
|
dnl End: Check that we meet the dependencies
|
||||||
dnl ==============================================
|
dnl ==============================================
|
||||||
|
|
|
@ -23,6 +23,10 @@ if BUILD_CHEESE
|
||||||
AM_CPPFLAGS += $(CHEESE_CFLAGS)
|
AM_CPPFLAGS += $(CHEESE_CFLAGS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
BUILT_SOURCES = \
|
||||||
|
um-realm-generated.c \
|
||||||
|
um-realm-generated.h
|
||||||
|
|
||||||
libuser_accounts_la_SOURCES = \
|
libuser_accounts_la_SOURCES = \
|
||||||
um-account-type.h \
|
um-account-type.h \
|
||||||
um-account-type.c \
|
um-account-type.c \
|
||||||
|
@ -53,7 +57,10 @@ libuser_accounts_la_SOURCES = \
|
||||||
um-editable-combo.c \
|
um-editable-combo.c \
|
||||||
um-user-panel.h \
|
um-user-panel.h \
|
||||||
um-user-panel.c \
|
um-user-panel.c \
|
||||||
um-user-module.c
|
um-user-module.c \
|
||||||
|
um-realm-manager.c \
|
||||||
|
um-realm-manager.h \
|
||||||
|
$(BUILT_SOURCES)
|
||||||
|
|
||||||
libuser_accounts_la_LIBADD = \
|
libuser_accounts_la_LIBADD = \
|
||||||
$(PANEL_LIBS) \
|
$(PANEL_LIBS) \
|
||||||
|
@ -69,18 +76,26 @@ endif
|
||||||
|
|
||||||
libuser_accounts_la_LDFLAGS = $(PANEL_LDFLAGS)
|
libuser_accounts_la_LDFLAGS = $(PANEL_LDFLAGS)
|
||||||
|
|
||||||
|
um-realm-generated.c: $(srcdir)/data/org.freedesktop.realmd.xml
|
||||||
|
$(AM_V_GEN) gdbus-codegen --interface-prefix org.freedesktop.realmd. \
|
||||||
|
--generate-c-code um-realm-generated --c-namespace UmRealm $<
|
||||||
|
um-realm-generated.h: um-realm-generated.c
|
||||||
|
|
||||||
noinst_PROGRAMS = frob-account-dialog
|
noinst_PROGRAMS = frob-account-dialog
|
||||||
|
|
||||||
frob_account_dialog_SOURCES = \
|
frob_account_dialog_SOURCES = \
|
||||||
frob-account-dialog.c \
|
frob-account-dialog.c \
|
||||||
um-account-dialog.h \
|
um-account-dialog.h \
|
||||||
um-account-dialog.c \
|
um-account-dialog.c \
|
||||||
|
um-realm-manager.c \
|
||||||
|
um-realm-manager.h \
|
||||||
um-user.h \
|
um-user.h \
|
||||||
um-user.c \
|
um-user.c \
|
||||||
um-user-manager.c \
|
um-user-manager.c \
|
||||||
um-user-manager.h \
|
um-user-manager.h \
|
||||||
um-utils.h \
|
um-utils.h \
|
||||||
um-utils.c
|
um-utils.c \
|
||||||
|
$(BUILT_SOURCES)
|
||||||
|
|
||||||
frob_account_dialog_LDADD = \
|
frob_account_dialog_LDADD = \
|
||||||
$(libuser_accounts_la_LIBADD)
|
$(libuser_accounts_la_LIBADD)
|
||||||
|
|
|
@ -16,6 +16,7 @@ desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop)
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
gnome-user-accounts-panel.desktop.in.in \
|
gnome-user-accounts-panel.desktop.in.in \
|
||||||
|
org.freedesktop.realmd.xml \
|
||||||
$(ui_DATA)
|
$(ui_DATA)
|
||||||
|
|
||||||
CLEANFILES = \
|
CLEANFILES = \
|
||||||
|
|
|
@ -205,15 +205,20 @@
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkGrid" id="enterprise-area">
|
<object class="GtkGrid" id="enterprise-area">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
<property name="hexpand">True</property>
|
<property name="hexpand">True</property>
|
||||||
<property name="column_spacing">10</property>
|
|
||||||
<property name="row_spacing">10</property>
|
<property name="row_spacing">10</property>
|
||||||
|
<property name="column_spacing">10</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkLabel" id="label61">
|
<object class="GtkLabel" id="label4">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
<property name="xalign">1</property>
|
<property name="xalign">1</property>
|
||||||
<property name="label" translatable="yes">Enterprise Widgets</property>
|
<property name="yalign">0</property>
|
||||||
|
<property name="label" translatable="yes">_Domain</property>
|
||||||
<property name="use_underline">True</property>
|
<property name="use_underline">True</property>
|
||||||
|
<property name="mnemonic_widget">enterprise-domain</property>
|
||||||
<style>
|
<style>
|
||||||
<class name="dim-label"/>
|
<class name="dim-label"/>
|
||||||
</style>
|
</style>
|
||||||
|
@ -221,13 +226,359 @@
|
||||||
<packing>
|
<packing>
|
||||||
<property name="left_attach">0</property>
|
<property name="left_attach">0</property>
|
||||||
<property name="top_attach">0</property>
|
<property name="top_attach">0</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label8">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">_Login Name</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="mnemonic_widget">enterprise-login</property>
|
||||||
|
<style>
|
||||||
|
<class name="dim-label"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label9">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">_Password</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="mnemonic_widget">enterprise-password</property>
|
||||||
|
<style>
|
||||||
|
<class name="dim-label"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="box1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">3</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkComboBox" id="enterprise-domain">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="has_entry">True</property>
|
||||||
|
<property name="entry_text_column">0</property>
|
||||||
|
<child internal-child="entry">
|
||||||
|
<object class="GtkEntry" id="combobox-entry">
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label10">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="label" translatable="yes">Tip: Enterprise domain or realm name</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="scale" value="0.8"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="enterprise-login">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="enterprise-password">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="visibility">False</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="activates_default">True</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<object class="GtkDialog" id="join-dialog">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="border_width">10</property>
|
||||||
|
<property name="resizable">False</property>
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<property name="destroy_with_parent">True</property>
|
||||||
|
<property name="type_hint">dialog</property>
|
||||||
|
<child internal-child="vbox">
|
||||||
|
<object class="GtkBox" id="dialog-vbox1">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">2</property>
|
||||||
|
<child internal-child="action_area">
|
||||||
|
<object class="GtkButtonBox" id="dialog-action_area1">
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="layout_style">end</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="button1">
|
||||||
|
<property name="label">gtk-cancel</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="can_default">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="use_stock">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="button2">
|
||||||
|
<property name="label" translatable="yes">C_ontinue</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="can_default">True</property>
|
||||||
|
<property name="has_default">True</property>
|
||||||
|
<property name="receives_default">True</property>
|
||||||
|
<property name="use_action_appearance">False</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="expand">False</property>
|
<property name="expand">False</property>
|
||||||
<property name="fill">False</property>
|
<property name="fill">True</property>
|
||||||
|
<property name="pack_type">end</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="box2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="border_width">5</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<property name="spacing">10</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label71">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Domain Administrator Login</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="bold"/>
|
||||||
|
<attribute name="scale" value="1.2"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label12">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="yalign">0</property>
|
||||||
|
<property name="label" translatable="yes">In order to use enterpise logins, this computer needs to be
|
||||||
|
enrolled in the domain. Please have your network administrator
|
||||||
|
type their domain password here.</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid" id="grid1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_left">12</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="row_spacing">6</property>
|
||||||
|
<property name="column_spacing">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label13">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">_Domain</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="mnemonic_widget">join-domain</property>
|
||||||
|
<style>
|
||||||
|
<class name="dim-label"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="join-domain">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="margin_top">5</property>
|
||||||
|
<property name="margin_bottom">5</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">0</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label14">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">Administrator _Name</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="mnemonic_widget">join-name</property>
|
||||||
|
<style>
|
||||||
|
<class name="dim-label"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="join-name">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">1</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label15">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">False</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
<property name="label" translatable="yes">Administrator Password</property>
|
||||||
|
<property name="use_underline">True</property>
|
||||||
|
<property name="mnemonic_widget">join-password</property>
|
||||||
|
<style>
|
||||||
|
<class name="dim-label"/>
|
||||||
|
</style>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">0</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="join-password">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can_focus">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="visibility">False</property>
|
||||||
|
<property name="invisible_char">●</property>
|
||||||
|
<property name="activates_default">True</property>
|
||||||
|
<property name="invisible_char_set">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left_attach">1</property>
|
||||||
|
<property name="top_attach">2</property>
|
||||||
|
<property name="width">1</property>
|
||||||
|
<property name="height">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<action-widgets>
|
||||||
|
<action-widget response="-6">button1</action-widget>
|
||||||
|
<action-widget response="-5">button2</action-widget>
|
||||||
|
</action-widgets>
|
||||||
|
</object>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
145
panels/user-accounts/data/org.freedesktop.realmd.xml
Normal file
145
panels/user-accounts/data/org.freedesktop.realmd.xml
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||||
|
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||||
|
|
||||||
|
<node name="/">
|
||||||
|
<!--
|
||||||
|
* Global interface implemented by realmd. Allows listing of providers
|
||||||
|
* and discovering which one is relevant for a given domain.
|
||||||
|
*
|
||||||
|
* This is implemented by individual providers, but is aggregated
|
||||||
|
* globally at the system bus name 'org.freedesktop.realmd' with the
|
||||||
|
* object path '/org/freedesktop/realmd'
|
||||||
|
-->
|
||||||
|
<interface name="org.freedesktop.realmd.Provider">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* A list of known, enrolled or discovered realms.
|
||||||
|
* Each realm is a DBus object and is represeted by a:
|
||||||
|
* s: DBus bus name of the realm
|
||||||
|
* o: DBus object path of the realm
|
||||||
|
* s: DBus interface name, like 'ofr.Kerberos' (below)
|
||||||
|
-->
|
||||||
|
<property name="Realms" type="a(sos)" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* Discover whether a string represents a realm that a provider
|
||||||
|
* can enroll or otherwise use.
|
||||||
|
-->
|
||||||
|
<method name="Discover">
|
||||||
|
<!-- The input string -->
|
||||||
|
<arg name="string" type="s" direction="in"/>
|
||||||
|
|
||||||
|
<!-- Returned match relevance -->
|
||||||
|
<arg name="relevance" type="i" direction="out"/>
|
||||||
|
|
||||||
|
<!-- The realm objects: bus name, object path, interface -->
|
||||||
|
<arg name="realm" type="a(sos)" direction="out"/>
|
||||||
|
</method>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* This interface is implemented by Providers and Realms to provide
|
||||||
|
* additional information when an long running operation is happening
|
||||||
|
*
|
||||||
|
* In particular you can connect to the "Diagnostics" signal when
|
||||||
|
* during an enroll or unenroll to get details.
|
||||||
|
-->
|
||||||
|
<interface name="org.freedesktop.realmd.Diagnostics">
|
||||||
|
<signal name="Diagnostics">
|
||||||
|
<arg name="data" type="s"/>
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* This interface is implemented by Kerberos realms.
|
||||||
|
-->
|
||||||
|
<interface name="org.freedesktop.realmd.Kerberos">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* The kerberos realm name. Usually capitalized.
|
||||||
|
-->
|
||||||
|
<property name="Name" type="s" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* The DNS domain name for this realm.
|
||||||
|
-->
|
||||||
|
<property name="Domain" type="s" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* The suggested Administrator login name for this realm
|
||||||
|
-->
|
||||||
|
<property name="SuggestedAdministrator" type="s" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* Whether the machine is enrolled in this realm or not.
|
||||||
|
-->
|
||||||
|
<property name="Enrolled" type="b" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* Enroll the machine in this realm using an administrative
|
||||||
|
* account and a password.
|
||||||
|
-->
|
||||||
|
<method name="EnrollWithPassword">
|
||||||
|
<arg name="principal" type="s" direction="in"/>
|
||||||
|
<arg name="password" type="s" direction="in"/>
|
||||||
|
<arg name="options" type="a{sv}" direction="in"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* Enroll the machine in this realm using kerberos cached
|
||||||
|
* administrative credentials.
|
||||||
|
-->
|
||||||
|
<method name="EnrollWithCredentialCache">
|
||||||
|
<!-- The contents of a kerberos cache file containing administrative credentials -->
|
||||||
|
<arg name="kerberos_cache" type="ay" direction="in">
|
||||||
|
<annotation name="org.gtk.GDBus.C.ForceGVariant" value="yup"/>
|
||||||
|
</arg>
|
||||||
|
<arg name="options" type="a{sv}" direction="in"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* Unenroll the machine from this realm using an administrative
|
||||||
|
* account and a password.
|
||||||
|
-->
|
||||||
|
<method name="UnenrollWithPassword">
|
||||||
|
<arg name="principal" type="s" direction="in"/>
|
||||||
|
<arg name="password" type="s" direction="in"/>
|
||||||
|
<arg name="options" type="a{sv}" direction="in"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* Unenroll the machine from this realm using a kerberos cached
|
||||||
|
* administrative credentials.
|
||||||
|
-->
|
||||||
|
<method name="UnenrollWithCredentialCache">
|
||||||
|
<!-- The contents of a kerberos cache file containing administrative credentials -->
|
||||||
|
<arg name="kerberos_cache" type="ay" direction="in">
|
||||||
|
<annotation name="org.gtk.GDBus.C.ForceGVariant" value="yup"/>
|
||||||
|
</arg>
|
||||||
|
<arg name="options" type="a{sv}" direction="in"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* The format for user logins when this realm is enrolled.
|
||||||
|
* This property may not be valid unless machine is enrolled
|
||||||
|
* in this realm. The format contains a %s where the user name
|
||||||
|
* goes eg: "DOMAIN\%s"
|
||||||
|
-->
|
||||||
|
<property name="LoginFormat" type="s" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* The list of permitted logins in the LoginFormat style
|
||||||
|
-->
|
||||||
|
<property name="PermittedLogins" type="as" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
* Change the PermittedLogins property. Should take effect
|
||||||
|
* immediately. Some providers may not enforce this :S
|
||||||
|
-->
|
||||||
|
<method name="ChangePermittedLogins">
|
||||||
|
<arg name="add" type="as" direction="in"/>
|
||||||
|
<arg name="remove" type="as" direction="in"/>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
</interface>
|
||||||
|
</node>
|
|
@ -26,23 +26,35 @@
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
#include "um-account-dialog.h"
|
#include "um-account-dialog.h"
|
||||||
|
#include "um-realm-manager.h"
|
||||||
#include "um-user-manager.h"
|
#include "um-user-manager.h"
|
||||||
#include "um-utils.h"
|
#include "um-utils.h"
|
||||||
|
|
||||||
static void dialog_validate (UmAccountDialog *self);
|
|
||||||
|
|
||||||
#define UM_ACCOUNT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UM_TYPE_ACCOUNT_DIALOG, \
|
|
||||||
UmAccountDialogClass))
|
|
||||||
#define UM_IS_ACCOUNT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UM_TYPE_ACCOUNT_DIALOG))
|
|
||||||
#define UM_ACCOUNT_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UM_TYPE_ACCOUNT_DIALOG, \
|
|
||||||
UmAccountDialogClass))
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
UM_LOCAL,
|
UM_LOCAL,
|
||||||
UM_ENTERPRISE,
|
UM_ENTERPRISE,
|
||||||
NUM_MODES
|
NUM_MODES
|
||||||
} UmAccountMode;
|
} UmAccountMode;
|
||||||
|
|
||||||
|
static void mode_change (UmAccountDialog *self,
|
||||||
|
UmAccountMode mode);
|
||||||
|
|
||||||
|
static void dialog_validate (UmAccountDialog *self);
|
||||||
|
|
||||||
|
static void on_join_login (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
static void on_realm_joined (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
#define UM_ACCOUNT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UM_TYPE_ACCOUNT_DIALOG, \
|
||||||
|
UmAccountDialogClass))
|
||||||
|
#define UM_IS_ACCOUNT_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UM_TYPE_ACCOUNT_DIALOG))
|
||||||
|
#define UM_ACCOUNT_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UM_TYPE_ACCOUNT_DIALOG, \
|
||||||
|
UmAccountDialogClass))
|
||||||
|
|
||||||
struct _UmAccountDialog {
|
struct _UmAccountDialog {
|
||||||
GtkDialog parent;
|
GtkDialog parent;
|
||||||
GtkWidget *container_widget;
|
GtkWidget *container_widget;
|
||||||
|
@ -63,6 +75,22 @@ struct _UmAccountDialog {
|
||||||
GtkWidget *local_account_type;
|
GtkWidget *local_account_type;
|
||||||
|
|
||||||
/* Enterprise widgets */
|
/* Enterprise widgets */
|
||||||
|
guint realmd_watch;
|
||||||
|
GtkWidget *enterprise_button;
|
||||||
|
GtkListStore *enterprise_realms;
|
||||||
|
GtkComboBox *enterprise_domain;
|
||||||
|
GtkEntry *enterprise_domain_entry;
|
||||||
|
gboolean enterprise_domain_chosen;
|
||||||
|
GtkEntry *enterprise_login;
|
||||||
|
GtkEntry *enterprise_password;
|
||||||
|
UmRealmManager *realm_manager;
|
||||||
|
UmRealmKerberos *selected_realm;
|
||||||
|
|
||||||
|
/* Join credential dialog */
|
||||||
|
GtkDialog *join_dialog;
|
||||||
|
GtkLabel *join_domain;
|
||||||
|
GtkEntry *join_name;
|
||||||
|
GtkEntry *join_password;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _UmAccountDialogClass {
|
struct _UmAccountDialogClass {
|
||||||
|
@ -230,7 +258,7 @@ on_name_changed (GtkEditable *editable,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
local_area_init (UmAccountDialog *self,
|
local_init (UmAccountDialog *self,
|
||||||
GtkBuilder *builder)
|
GtkBuilder *builder)
|
||||||
{
|
{
|
||||||
GtkWidget *widget;
|
GtkWidget *widget;
|
||||||
|
@ -260,6 +288,527 @@ local_prepare (UmAccountDialog *self)
|
||||||
gtk_combo_box_set_active (GTK_COMBO_BOX (self->local_account_type), 0);
|
gtk_combo_box_set_active (GTK_COMBO_BOX (self->local_account_type), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
enterprise_validate (UmAccountDialog *self)
|
||||||
|
{
|
||||||
|
const gchar *name;
|
||||||
|
gboolean valid_name;
|
||||||
|
gboolean valid_domain;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
name = gtk_entry_get_text (GTK_ENTRY (self->enterprise_login));
|
||||||
|
valid_name = is_valid_name (name);
|
||||||
|
|
||||||
|
if (gtk_combo_box_get_active_iter (self->enterprise_domain, &iter)) {
|
||||||
|
gtk_tree_model_get (gtk_combo_box_get_model (self->enterprise_domain),
|
||||||
|
&iter, 0, &name, -1);
|
||||||
|
} else {
|
||||||
|
name = gtk_entry_get_text (self->enterprise_domain_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_domain = is_valid_name (name);
|
||||||
|
return valid_name && valid_domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enterprise_add_realm (UmAccountDialog *self,
|
||||||
|
UmRealmKerberos *realm)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
gtk_list_store_append (self->enterprise_realms, &iter);
|
||||||
|
gtk_list_store_set (self->enterprise_realms, &iter,
|
||||||
|
0, um_realm_kerberos_get_domain (realm),
|
||||||
|
1, realm,
|
||||||
|
-1);
|
||||||
|
|
||||||
|
/* Select the domain if appropriate */
|
||||||
|
if (!self->enterprise_domain_chosen && um_realm_kerberos_get_enrolled (realm))
|
||||||
|
gtk_combo_box_set_active_iter (self->enterprise_domain, &iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_manager_realm_added (UmRealmManager *manager,
|
||||||
|
UmRealmKerberos *realm,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
enterprise_add_realm (self, realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_register_user (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
GError *error = NULL;
|
||||||
|
UmUser *user = NULL;
|
||||||
|
|
||||||
|
um_user_manager_cache_user_finish (UM_USER_MANAGER (source),
|
||||||
|
result, &user, &error);
|
||||||
|
|
||||||
|
/* This is where we're finally done */
|
||||||
|
if (error == NULL) {
|
||||||
|
finish_action (self);
|
||||||
|
complete_dialog (self, user);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
show_error_dialog (self, _("Failed to register account"), error);
|
||||||
|
g_message ("Couldn't cache user account: %s", error->message);
|
||||||
|
finish_action (self);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
enterprise_calculate_login (UmAccountDialog *self)
|
||||||
|
{
|
||||||
|
const gchar *format = um_realm_kerberos_get_login_format (self->selected_realm);
|
||||||
|
return g_strdup_printf (format, gtk_entry_get_text (self->enterprise_login));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_permit_user_login (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
UmUserManager *manager;
|
||||||
|
GError *error = NULL;
|
||||||
|
gchar *login;
|
||||||
|
|
||||||
|
um_realm_kerberos_call_change_permitted_logins_finish (UM_REALM_KERBEROS (source),
|
||||||
|
result, &error);
|
||||||
|
if (error == NULL) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now tell the account service about this user. The account service
|
||||||
|
* should also lookup information about this via the realm and make
|
||||||
|
* sure all that is functional.
|
||||||
|
*/
|
||||||
|
manager = um_user_manager_ref_default ();
|
||||||
|
login = enterprise_calculate_login (self);
|
||||||
|
um_user_manager_cache_user (manager, login, self->cancellable,
|
||||||
|
on_register_user, g_object_ref (self),
|
||||||
|
g_object_unref);
|
||||||
|
|
||||||
|
g_free (login);
|
||||||
|
g_object_unref (manager);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
show_error_dialog (self, _("Failed to register account"), error);
|
||||||
|
g_message ("Couldn't permit logins on account: %s", error->message);
|
||||||
|
finish_action (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enterprise_permit_user_login (UmAccountDialog *self)
|
||||||
|
{
|
||||||
|
gchar *login;
|
||||||
|
const gchar *add[2];
|
||||||
|
const gchar *remove[1];
|
||||||
|
|
||||||
|
login = enterprise_calculate_login (self);
|
||||||
|
|
||||||
|
add[0] = login;
|
||||||
|
add[1] = NULL;
|
||||||
|
remove[0] = NULL;
|
||||||
|
|
||||||
|
um_realm_kerberos_call_change_permitted_logins (self->selected_realm,
|
||||||
|
add, remove,
|
||||||
|
self->cancellable,
|
||||||
|
on_permit_user_login,
|
||||||
|
g_object_ref (self));
|
||||||
|
|
||||||
|
g_free (login);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_join_response (GtkDialog *dialog,
|
||||||
|
gint response,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
|
||||||
|
gtk_widget_hide (GTK_WIDGET (dialog));
|
||||||
|
if (response != GTK_RESPONSE_OK) {
|
||||||
|
finish_action (self);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prompted for some admin credentials, try to use them to log in */
|
||||||
|
um_realm_login (um_realm_kerberos_get_name (self->selected_realm),
|
||||||
|
um_realm_kerberos_get_domain (self->selected_realm),
|
||||||
|
gtk_entry_get_text (self->join_name),
|
||||||
|
gtk_entry_get_text (self->join_password),
|
||||||
|
self->cancellable,
|
||||||
|
on_join_login,
|
||||||
|
g_object_ref (self));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
join_show_prompt (UmAccountDialog *self,
|
||||||
|
GError *error)
|
||||||
|
{
|
||||||
|
const gchar *name;
|
||||||
|
|
||||||
|
gtk_entry_set_text (self->join_password, "");
|
||||||
|
gtk_widget_grab_focus (GTK_WIDGET (self->join_password));
|
||||||
|
|
||||||
|
gtk_label_set_text (self->join_domain,
|
||||||
|
um_realm_kerberos_get_domain (self->selected_realm));
|
||||||
|
|
||||||
|
clear_entry_validation_error (self->join_name);
|
||||||
|
clear_entry_validation_error (self->join_password);
|
||||||
|
|
||||||
|
if (error == NULL) {
|
||||||
|
name = um_realm_kerberos_get_suggested_administrator (self->selected_realm);
|
||||||
|
if (name && !g_str_equal (name, "")) {
|
||||||
|
gtk_entry_set_text (self->join_name, name);
|
||||||
|
} else {
|
||||||
|
gtk_widget_grab_focus (GTK_WIDGET (self->join_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
|
||||||
|
set_entry_validation_error (self->join_password, error->message);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_dbus_error_strip_remote_error (error);
|
||||||
|
set_entry_validation_error (self->join_name, error->message);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_window_set_transient_for (GTK_WINDOW (self->join_dialog), GTK_WINDOW (self));
|
||||||
|
gtk_window_set_modal (GTK_WINDOW (self->join_dialog), TRUE);
|
||||||
|
gtk_window_present (GTK_WINDOW (self->join_dialog));
|
||||||
|
|
||||||
|
/* And now we wait for on_join_response() */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_join_login (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
GError *error = NULL;
|
||||||
|
GBytes *creds;
|
||||||
|
|
||||||
|
um_realm_login_finish (result, &creds, &error);
|
||||||
|
|
||||||
|
/* Logged in as admin successfully, use creds to join domain */
|
||||||
|
if (error == NULL) {
|
||||||
|
um_realm_join (self->selected_realm,
|
||||||
|
creds, self->cancellable, on_realm_joined,
|
||||||
|
g_object_ref (self));
|
||||||
|
g_bytes_unref (creds);
|
||||||
|
|
||||||
|
/* Couldn't login as admin, show prompt again */
|
||||||
|
} else {
|
||||||
|
join_show_prompt (self, error);
|
||||||
|
g_message ("Couldn't log in as admin to join domain: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
join_init (UmAccountDialog *self,
|
||||||
|
GtkBuilder *builder)
|
||||||
|
{
|
||||||
|
self->join_dialog = GTK_DIALOG (gtk_builder_get_object (builder, "join-dialog"));
|
||||||
|
self->join_domain = GTK_LABEL (gtk_builder_get_object (builder, "join-domain"));
|
||||||
|
self->join_name = GTK_ENTRY (gtk_builder_get_object (builder, "join-name"));
|
||||||
|
self->join_password = GTK_ENTRY (gtk_builder_get_object (builder, "join-password"));
|
||||||
|
|
||||||
|
g_signal_connect (self->join_dialog, "response",
|
||||||
|
G_CALLBACK (on_join_response), self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_realm_joined (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
um_realm_join_finish (self->selected_realm,
|
||||||
|
result, &error);
|
||||||
|
|
||||||
|
/* Yay, joined the domain, register the user locally */
|
||||||
|
if (error == NULL) {
|
||||||
|
enterprise_permit_user_login (self);
|
||||||
|
|
||||||
|
/* Credential failure while joining domain, prompt for admin creds */
|
||||||
|
} else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN) ||
|
||||||
|
g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
|
||||||
|
join_show_prompt (self, error);
|
||||||
|
|
||||||
|
/* Other failure */
|
||||||
|
} else {
|
||||||
|
show_error_dialog (self, _("Failed to join domain"), error);
|
||||||
|
g_message ("Failed to join the domain: %s", error->message);
|
||||||
|
finish_action (self);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_realm_login (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
GError *error = NULL;
|
||||||
|
GBytes *creds;
|
||||||
|
|
||||||
|
um_realm_login_finish (result, &creds, &error);
|
||||||
|
if (error == NULL) {
|
||||||
|
|
||||||
|
/* Already joined to the domain, just register this user */
|
||||||
|
if (um_realm_kerberos_get_enrolled (self->selected_realm)) {
|
||||||
|
enterprise_permit_user_login (self);
|
||||||
|
|
||||||
|
/* Join the domain, try using the user's creds */
|
||||||
|
} else {
|
||||||
|
um_realm_join (self->selected_realm,
|
||||||
|
creds,
|
||||||
|
self->cancellable,
|
||||||
|
on_realm_joined,
|
||||||
|
g_object_ref (self));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_bytes_unref (creds);
|
||||||
|
|
||||||
|
/* A problem with the user's login name or password */
|
||||||
|
} else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN)) {
|
||||||
|
set_entry_validation_error (self->enterprise_login, error->message);
|
||||||
|
finish_action (self);
|
||||||
|
gtk_widget_grab_focus (GTK_WIDGET (self->enterprise_login));
|
||||||
|
|
||||||
|
} else if (g_error_matches (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD)) {
|
||||||
|
set_entry_validation_error (self->enterprise_password, error->message);
|
||||||
|
finish_action (self);
|
||||||
|
gtk_widget_grab_focus (GTK_WIDGET (self->enterprise_password));
|
||||||
|
|
||||||
|
/* Other login failure */
|
||||||
|
} else {
|
||||||
|
g_dbus_error_strip_remote_error (error);
|
||||||
|
show_error_dialog (self, _("Failed to log into domain"), error);
|
||||||
|
g_message ("Couldn't log in as user: %s", error->message);
|
||||||
|
finish_action (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_error (&error);
|
||||||
|
g_object_unref (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enterprise_check_login (UmAccountDialog *self)
|
||||||
|
{
|
||||||
|
g_assert (self->selected_realm);
|
||||||
|
|
||||||
|
um_realm_login (um_realm_kerberos_get_name (self->selected_realm),
|
||||||
|
um_realm_kerberos_get_domain (self->selected_realm),
|
||||||
|
gtk_entry_get_text (self->enterprise_login),
|
||||||
|
gtk_entry_get_text (self->enterprise_password),
|
||||||
|
self->cancellable,
|
||||||
|
on_realm_login,
|
||||||
|
g_object_ref (self));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_realm_discover_input (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
GError *error = NULL;
|
||||||
|
GList *realms;
|
||||||
|
|
||||||
|
realms = um_realm_manager_discover_finish (self->realm_manager,
|
||||||
|
result, &error);
|
||||||
|
|
||||||
|
/* Found a realm, log user into domain */
|
||||||
|
if (error == NULL) {
|
||||||
|
g_assert (realms != NULL);
|
||||||
|
self->selected_realm = g_object_ref (realms->data);
|
||||||
|
enterprise_check_login (self);
|
||||||
|
g_list_free_full (realms, g_object_unref);
|
||||||
|
|
||||||
|
/* The domain is likely invalid*/
|
||||||
|
} else {
|
||||||
|
finish_action (self);
|
||||||
|
g_message ("Couldn't discover domain: %s", error->message);
|
||||||
|
gtk_widget_grab_focus (GTK_WIDGET (self->enterprise_domain_entry));
|
||||||
|
g_dbus_error_strip_remote_error (error);
|
||||||
|
set_entry_validation_error (self->enterprise_domain_entry,
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enterprise_add_user (UmAccountDialog *self)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
begin_action (self);
|
||||||
|
g_clear_object (&self->selected_realm);
|
||||||
|
|
||||||
|
/* Already know about this realm, try to login as user */
|
||||||
|
if (gtk_combo_box_get_active_iter (self->enterprise_domain, &iter)) {
|
||||||
|
gtk_tree_model_get (gtk_combo_box_get_model (self->enterprise_domain),
|
||||||
|
&iter, 1, &self->selected_realm, -1);
|
||||||
|
enterprise_check_login (self);
|
||||||
|
|
||||||
|
/* Something the user typed, we need to discover realm */
|
||||||
|
} else {
|
||||||
|
um_realm_manager_discover (self->realm_manager,
|
||||||
|
gtk_entry_get_text (self->enterprise_domain_entry),
|
||||||
|
self->cancellable,
|
||||||
|
on_realm_discover_input,
|
||||||
|
g_object_ref (self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_realm_manager_created (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
GError *error = NULL;
|
||||||
|
GList *realms, *l;
|
||||||
|
|
||||||
|
g_clear_object (&self->realm_manager);
|
||||||
|
|
||||||
|
self->realm_manager = um_realm_manager_new_finish (result, &error);
|
||||||
|
if (error != NULL) {
|
||||||
|
g_warning ("Couldn't contact realmd service: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lookup all the realm objects */
|
||||||
|
realms = um_realm_manager_get_realms (self->realm_manager);
|
||||||
|
for (l = realms; l != NULL; l = g_list_next (l))
|
||||||
|
enterprise_add_realm (self, l->data);
|
||||||
|
g_list_free (realms);
|
||||||
|
g_signal_connect (self->realm_manager, "realm-added",
|
||||||
|
G_CALLBACK (on_manager_realm_added), self);
|
||||||
|
|
||||||
|
/* When no realms try to discover a sensible default, triggers realm-added signal */
|
||||||
|
um_realm_manager_discover (self->realm_manager, "", self->cancellable,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
|
/* Show the 'Enterprise Login' stuff, and update mode */
|
||||||
|
gtk_widget_show (self->enterprise_button);
|
||||||
|
mode_change (self, self->mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_realmd_appeared (GDBusConnection *connection,
|
||||||
|
const gchar *name,
|
||||||
|
const gchar *name_owner,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
um_realm_manager_new (self->cancellable, on_realm_manager_created, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_realmd_disappeared (GDBusConnection *unused1,
|
||||||
|
const gchar *unused2,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
|
||||||
|
if (self->realm_manager) {
|
||||||
|
g_signal_handlers_disconnect_by_func (self->realm_manager,
|
||||||
|
on_manager_realm_added,
|
||||||
|
self);
|
||||||
|
g_object_unref (self->realm_manager);
|
||||||
|
self->realm_manager = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_list_store_clear (self->enterprise_realms);
|
||||||
|
gtk_widget_hide (self->enterprise_button);
|
||||||
|
mode_change (self, UM_LOCAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_domain_changed (GtkComboBox *widget,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
|
||||||
|
dialog_validate (self);
|
||||||
|
self->enterprise_domain_chosen = TRUE;
|
||||||
|
clear_entry_validation_error (self->enterprise_domain_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_entry_changed (GtkEditable *editable,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
UmAccountDialog *self = UM_ACCOUNT_DIALOG (user_data);
|
||||||
|
dialog_validate (self);
|
||||||
|
clear_entry_validation_error (GTK_ENTRY (editable));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enterprise_init (UmAccountDialog *self,
|
||||||
|
GtkBuilder *builder)
|
||||||
|
{
|
||||||
|
GtkWidget *widget;
|
||||||
|
|
||||||
|
self->enterprise_realms = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
widget = (GtkWidget *) gtk_builder_get_object (builder, "enterprise-domain");
|
||||||
|
g_signal_connect (widget, "changed", G_CALLBACK (on_domain_changed), self);
|
||||||
|
self->enterprise_domain = GTK_COMBO_BOX (widget);
|
||||||
|
gtk_combo_box_set_model (self->enterprise_domain,
|
||||||
|
GTK_TREE_MODEL (self->enterprise_realms));
|
||||||
|
gtk_combo_box_set_entry_text_column (self->enterprise_domain, 0);
|
||||||
|
self->enterprise_domain_entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (widget)));
|
||||||
|
|
||||||
|
widget = (GtkWidget *) gtk_builder_get_object (builder, "enterprise-login");
|
||||||
|
g_signal_connect (widget, "changed", G_CALLBACK (on_entry_changed), self);
|
||||||
|
self->enterprise_login = GTK_ENTRY (widget);
|
||||||
|
|
||||||
|
widget = (GtkWidget *) gtk_builder_get_object (builder, "enterprise-password");
|
||||||
|
g_signal_connect (widget, "changed", G_CALLBACK (on_entry_changed), self);
|
||||||
|
self->enterprise_password = GTK_ENTRY (widget);
|
||||||
|
|
||||||
|
/* Initially we hide the 'Enterprise Login' stuff */
|
||||||
|
widget = (GtkWidget *) gtk_builder_get_object (builder, "enterprise-button");
|
||||||
|
self->enterprise_button = widget;
|
||||||
|
gtk_widget_hide (widget);
|
||||||
|
|
||||||
|
self->realmd_watch = g_bus_watch_name (G_BUS_TYPE_SYSTEM, "org.freedesktop.realmd",
|
||||||
|
G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
|
||||||
|
on_realmd_appeared, on_realmd_disappeared,
|
||||||
|
self, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enterprise_prepare (UmAccountDialog *self)
|
||||||
|
{
|
||||||
|
gtk_entry_set_text (GTK_ENTRY (self->enterprise_login), "");
|
||||||
|
gtk_entry_set_text (GTK_ENTRY (self->enterprise_password), "");
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dialog_validate (UmAccountDialog *self)
|
dialog_validate (UmAccountDialog *self)
|
||||||
{
|
{
|
||||||
|
@ -270,8 +819,7 @@ dialog_validate (UmAccountDialog *self)
|
||||||
valid = local_validate (self);
|
valid = local_validate (self);
|
||||||
break;
|
break;
|
||||||
case UM_ENTERPRISE:
|
case UM_ENTERPRISE:
|
||||||
/* TODO: Implement */
|
valid = enterprise_validate (self);
|
||||||
valid = FALSE;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
valid = FALSE;
|
valid = FALSE;
|
||||||
|
@ -442,7 +990,9 @@ um_account_dialog_init (UmAccountDialog *self)
|
||||||
gtk_container_add (GTK_CONTAINER (content), widget);
|
gtk_container_add (GTK_CONTAINER (content), widget);
|
||||||
self->container_widget = widget;
|
self->container_widget = widget;
|
||||||
|
|
||||||
local_area_init (self, builder);
|
local_init (self, builder);
|
||||||
|
enterprise_init (self, builder);
|
||||||
|
join_init (self, builder);
|
||||||
mode_init (self, builder);
|
mode_init (self, builder);
|
||||||
|
|
||||||
g_object_unref (builder);
|
g_object_unref (builder);
|
||||||
|
@ -461,8 +1011,7 @@ um_account_dialog_response (GtkDialog *dialog,
|
||||||
local_create_user (self);
|
local_create_user (self);
|
||||||
break;
|
break;
|
||||||
case UM_ENTERPRISE:
|
case UM_ENTERPRISE:
|
||||||
/* TODO: */
|
enterprise_add_user (self);
|
||||||
g_assert_not_reached ();
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
|
@ -484,6 +1033,18 @@ um_account_dialog_dispose (GObject *obj)
|
||||||
if (self->cancellable)
|
if (self->cancellable)
|
||||||
g_cancellable_cancel (self->cancellable);
|
g_cancellable_cancel (self->cancellable);
|
||||||
|
|
||||||
|
if (self->realmd_watch)
|
||||||
|
g_bus_unwatch_name (self->realmd_watch);
|
||||||
|
self->realmd_watch = 0;
|
||||||
|
|
||||||
|
if (self->realm_manager) {
|
||||||
|
g_signal_handlers_disconnect_by_func (self->realm_manager,
|
||||||
|
on_manager_realm_added,
|
||||||
|
self);
|
||||||
|
g_object_unref (self->realm_manager);
|
||||||
|
self->realm_manager = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (um_account_dialog_parent_class)->dispose (obj);
|
G_OBJECT_CLASS (um_account_dialog_parent_class)->dispose (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,6 +1055,7 @@ um_account_dialog_finalize (GObject *obj)
|
||||||
|
|
||||||
if (self->cancellable)
|
if (self->cancellable)
|
||||||
g_object_unref (self->cancellable);
|
g_object_unref (self->cancellable);
|
||||||
|
g_object_unref (self->enterprise_realms);
|
||||||
|
|
||||||
G_OBJECT_CLASS (um_account_dialog_parent_class)->finalize (obj);
|
G_OBJECT_CLASS (um_account_dialog_parent_class)->finalize (obj);
|
||||||
}
|
}
|
||||||
|
@ -535,6 +1097,7 @@ um_account_dialog_show (UmAccountDialog *self,
|
||||||
self->cancellable = g_cancellable_new ();
|
self->cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
local_prepare (self);
|
local_prepare (self);
|
||||||
|
enterprise_prepare (self);
|
||||||
mode_change (self, UM_LOCAL);
|
mode_change (self, UM_LOCAL);
|
||||||
dialog_validate (self);
|
dialog_validate (self);
|
||||||
|
|
||||||
|
|
765
panels/user-accounts/um-realm-manager.c
Normal file
765
panels/user-accounts/um-realm-manager.c
Normal file
|
@ -0,0 +1,765 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright 2009-2012 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by: Matthias Clasen <mclasen@redhat.com>
|
||||||
|
* Stef Walter <stefw@gnome.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "um-realm-manager.h"
|
||||||
|
|
||||||
|
#include <krb5/krb5.h>
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct _UmRealmManager {
|
||||||
|
UmRealmProviderProxy parent;
|
||||||
|
guint diagnostics_sig;
|
||||||
|
GHashTable *realms;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UmRealmProviderProxyClass parent_class;
|
||||||
|
} UmRealmManagerClass;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
REALM_ADDED,
|
||||||
|
NUM_SIGNALS,
|
||||||
|
};
|
||||||
|
|
||||||
|
static gint signals[NUM_SIGNALS] = { 0, };
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (UmRealmManager, um_realm_manager, UM_REALM_TYPE_PROVIDER_PROXY);
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
um_realm_error_get_quark (void)
|
||||||
|
{
|
||||||
|
static GQuark quark = 0;
|
||||||
|
if (quark == 0)
|
||||||
|
quark = g_quark_from_static_string ("um-realm-error");
|
||||||
|
return quark;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
UmRealmManager *manager;
|
||||||
|
GList *realms;
|
||||||
|
gint outstanding;
|
||||||
|
} LoadClosure;
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_closure_free (gpointer data)
|
||||||
|
{
|
||||||
|
LoadClosure *load = data;
|
||||||
|
g_list_free_full (load->realms, g_object_unref);
|
||||||
|
g_object_unref (load->manager);
|
||||||
|
g_slice_free (LoadClosure, load);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_realm_proxy_created (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
LoadClosure *load = g_simple_async_result_get_op_res_gpointer (async);
|
||||||
|
UmRealmManager *self = load->manager;
|
||||||
|
UmRealmKerberos *realm;
|
||||||
|
UmRealmKerberos *have;
|
||||||
|
GError *error = NULL;
|
||||||
|
GDBusProxy *proxy;
|
||||||
|
GVariant *info;
|
||||||
|
|
||||||
|
realm = um_realm_kerberos_proxy_new_finish (result, &error);
|
||||||
|
if (error == NULL) {
|
||||||
|
proxy = G_DBUS_PROXY (realm);
|
||||||
|
info = g_variant_new ("(sos)",
|
||||||
|
g_dbus_proxy_get_name (proxy),
|
||||||
|
g_dbus_proxy_get_object_path (proxy),
|
||||||
|
g_dbus_proxy_get_interface_name (proxy));
|
||||||
|
|
||||||
|
/* Add it to the manager, unless race */
|
||||||
|
have = g_hash_table_lookup (self->realms, info);
|
||||||
|
if (have == NULL) {
|
||||||
|
g_hash_table_insert (self->realms,
|
||||||
|
g_variant_ref_sink (info), realm);
|
||||||
|
g_signal_emit (self, signals[REALM_ADDED], 0, realm);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_object_unref (realm);
|
||||||
|
g_variant_unref (info);
|
||||||
|
realm = have;
|
||||||
|
}
|
||||||
|
|
||||||
|
load->realms = g_list_prepend (load->realms, g_object_ref (realm));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_simple_async_result_take_error (async, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (load->outstanding-- == 1)
|
||||||
|
g_simple_async_result_complete (async);
|
||||||
|
|
||||||
|
g_object_unref (async);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
um_realm_manager_load (UmRealmManager *self,
|
||||||
|
GVariant *realms,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async;
|
||||||
|
GDBusConnection *connection;
|
||||||
|
LoadClosure *load;
|
||||||
|
GVariantIter iter;
|
||||||
|
GVariant *info;
|
||||||
|
UmRealmKerberos *realm;
|
||||||
|
const gchar *path;
|
||||||
|
const gchar *iface;
|
||||||
|
const gchar *name;
|
||||||
|
|
||||||
|
g_return_if_fail (realms != NULL);
|
||||||
|
|
||||||
|
async = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
||||||
|
um_realm_manager_load);
|
||||||
|
load = g_slice_new0 (LoadClosure);
|
||||||
|
load->manager = g_object_ref (self);
|
||||||
|
g_simple_async_result_set_op_res_gpointer (async, load, load_closure_free);
|
||||||
|
|
||||||
|
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (self));
|
||||||
|
|
||||||
|
g_variant_iter_init (&iter, realms);
|
||||||
|
while (1) {
|
||||||
|
info = g_variant_iter_next_value (&iter);
|
||||||
|
if (info == NULL)
|
||||||
|
break;
|
||||||
|
realm = g_hash_table_lookup (self->realms, info);
|
||||||
|
if (realm == NULL) {
|
||||||
|
g_variant_get (info, "(&s&o&s)", &name, &path, &iface);
|
||||||
|
if (g_str_equal (iface, "org.freedesktop.realmd.Kerberos")) {
|
||||||
|
um_realm_kerberos_proxy_new (connection,
|
||||||
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
|
name, path, cancellable,
|
||||||
|
on_realm_proxy_created,
|
||||||
|
g_object_ref (async));
|
||||||
|
load->outstanding++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
load->realms = g_list_prepend (load->realms, g_object_ref (realm));
|
||||||
|
}
|
||||||
|
g_variant_unref (info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (load->outstanding == 0)
|
||||||
|
g_simple_async_result_complete_in_idle (async);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GList *
|
||||||
|
um_realm_manager_load_finish (UmRealmManager *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
|
LoadClosure *load;
|
||||||
|
GList *realms;
|
||||||
|
|
||||||
|
if (g_simple_async_result_propagate_error (async, error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
load = g_simple_async_result_get_op_res_gpointer (async);
|
||||||
|
realms = g_list_reverse (load->realms);
|
||||||
|
load->realms = NULL;
|
||||||
|
return realms;
|
||||||
|
}
|
||||||
|
|
||||||
|
static guint
|
||||||
|
hash_realm_info (gconstpointer value)
|
||||||
|
{
|
||||||
|
const gchar *name, *path, *iface;
|
||||||
|
g_variant_get ((GVariant *)value, "(&s&o&s)", &name, &path, &iface);
|
||||||
|
return g_str_hash (name) ^ g_str_hash (path) ^ g_str_hash (iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
um_realm_manager_init (UmRealmManager *self)
|
||||||
|
{
|
||||||
|
self->realms = g_hash_table_new_full (hash_realm_info, g_variant_equal,
|
||||||
|
(GDestroyNotify)g_variant_unref,
|
||||||
|
g_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
um_realm_manager_notify (GObject *obj,
|
||||||
|
GParamSpec *spec)
|
||||||
|
{
|
||||||
|
UmRealmManager *self = UM_REALM_MANAGER (obj);
|
||||||
|
GVariant *realms;
|
||||||
|
|
||||||
|
if (G_OBJECT_CLASS (um_realm_manager_parent_class)->notify)
|
||||||
|
G_OBJECT_CLASS (um_realm_manager_parent_class)->notify (obj, spec);
|
||||||
|
|
||||||
|
if (g_str_equal (spec->name, "realms")) {
|
||||||
|
realms = um_realm_provider_get_realms (UM_REALM_PROVIDER (self));
|
||||||
|
if (realms != NULL)
|
||||||
|
um_realm_manager_load (self, realms, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
um_realm_manager_dispose (GObject *obj)
|
||||||
|
{
|
||||||
|
UmRealmManager *self = UM_REALM_MANAGER (obj);
|
||||||
|
GDBusConnection *connection;
|
||||||
|
|
||||||
|
if (self->diagnostics_sig) {
|
||||||
|
connection = g_dbus_proxy_get_connection (G_DBUS_PROXY (self));
|
||||||
|
if (connection != NULL)
|
||||||
|
g_dbus_connection_signal_unsubscribe (connection, self->diagnostics_sig);
|
||||||
|
self->diagnostics_sig = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (um_realm_manager_parent_class)->dispose (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
um_realm_manager_finalize (GObject *obj)
|
||||||
|
{
|
||||||
|
UmRealmManager *self = UM_REALM_MANAGER (obj);
|
||||||
|
|
||||||
|
g_hash_table_destroy (self->realms);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (um_realm_manager_parent_class)->finalize (obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
um_realm_manager_class_init (UmRealmManagerClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->notify = um_realm_manager_notify;
|
||||||
|
object_class->dispose = um_realm_manager_dispose;
|
||||||
|
object_class->finalize = um_realm_manager_finalize;
|
||||||
|
|
||||||
|
signals[REALM_ADDED] = g_signal_new ("realm-added", UM_TYPE_REALM_MANAGER,
|
||||||
|
G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
|
||||||
|
g_cclosure_marshal_generic,
|
||||||
|
G_TYPE_NONE, 1, UM_REALM_TYPE_KERBEROS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_realm_diagnostics (GDBusConnection *connection,
|
||||||
|
const gchar *sender_name,
|
||||||
|
const gchar *object_path,
|
||||||
|
const gchar *interface_name,
|
||||||
|
const gchar *signal_name,
|
||||||
|
GVariant *parameters,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
const gchar *message;
|
||||||
|
|
||||||
|
if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(s)"))) {
|
||||||
|
/* Data is already formatted appropriately for stderr */
|
||||||
|
g_variant_get (parameters, "(&s)", &message);
|
||||||
|
g_printerr ("%s", message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_realm_manager_async_init (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
UmRealmManager *self;
|
||||||
|
GError *error = NULL;
|
||||||
|
GDBusProxy *proxy;
|
||||||
|
GObject *object;
|
||||||
|
guint sig;
|
||||||
|
|
||||||
|
object = g_async_initable_new_finish (G_ASYNC_INITABLE (source), result, &error);
|
||||||
|
|
||||||
|
if (error != NULL)
|
||||||
|
g_simple_async_result_take_error (async, error);
|
||||||
|
if (object != NULL) {
|
||||||
|
proxy = G_DBUS_PROXY (object);
|
||||||
|
sig = g_dbus_connection_signal_subscribe (g_dbus_proxy_get_connection (proxy),
|
||||||
|
g_dbus_proxy_get_name_owner (proxy),
|
||||||
|
"org.freedesktop.realmd.Diagnostics",
|
||||||
|
"Diagnostics",
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||||
|
on_realm_diagnostics,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
self = UM_REALM_MANAGER (object);
|
||||||
|
self->diagnostics_sig = sig;
|
||||||
|
g_simple_async_result_set_op_res_gpointer (async, self, g_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_simple_async_result_complete (async);
|
||||||
|
g_object_unref (async);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
um_realm_manager_new (GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async;
|
||||||
|
|
||||||
|
async = g_simple_async_result_new (NULL, callback, user_data,
|
||||||
|
um_realm_manager_new);
|
||||||
|
|
||||||
|
g_async_initable_new_async (UM_TYPE_REALM_MANAGER,
|
||||||
|
G_PRIORITY_DEFAULT, cancellable,
|
||||||
|
on_realm_manager_async_init, g_object_ref (async),
|
||||||
|
"g-name", "org.freedesktop.realmd",
|
||||||
|
"g-bus-type", G_BUS_TYPE_SYSTEM,
|
||||||
|
"g-object-path", "/org/freedesktop/realmd",
|
||||||
|
"g-interface-name", "org.freedesktop.realmd.Provider",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_object_unref (async);
|
||||||
|
}
|
||||||
|
|
||||||
|
UmRealmManager *
|
||||||
|
um_realm_manager_new_finish (GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
UmRealmManager *self;
|
||||||
|
GSimpleAsyncResult *async;
|
||||||
|
|
||||||
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
|
||||||
|
um_realm_manager_new), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
async = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
|
if (g_simple_async_result_propagate_error (async, error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
self = g_simple_async_result_get_op_res_gpointer (async);
|
||||||
|
if (self != NULL)
|
||||||
|
g_object_ref (self);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GCancellable *cancellable;
|
||||||
|
GList *realms;
|
||||||
|
} DiscoverClosure;
|
||||||
|
|
||||||
|
static void
|
||||||
|
discover_closure_free (gpointer data)
|
||||||
|
{
|
||||||
|
DiscoverClosure *discover = data;
|
||||||
|
g_clear_object (&discover->cancellable);
|
||||||
|
g_list_free_full (discover->realms, g_object_unref);
|
||||||
|
g_slice_free (DiscoverClosure, discover);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_manager_load (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
DiscoverClosure *discover = g_simple_async_result_get_op_res_gpointer (async);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
discover->realms = um_realm_manager_load_finish (UM_REALM_MANAGER (source),
|
||||||
|
result, &error);
|
||||||
|
if (error != NULL)
|
||||||
|
g_simple_async_result_take_error (async, error);
|
||||||
|
g_simple_async_result_complete (async);
|
||||||
|
|
||||||
|
g_object_unref (async);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_provider_discover (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
DiscoverClosure *discover = g_simple_async_result_get_op_res_gpointer (async);
|
||||||
|
UmRealmManager *self = UM_REALM_MANAGER (source);
|
||||||
|
GError *error = NULL;
|
||||||
|
GVariant *realms;
|
||||||
|
gint relevance;
|
||||||
|
|
||||||
|
um_realm_provider_call_discover_finish (UM_REALM_PROVIDER (self),
|
||||||
|
&relevance, &realms, result, &error);
|
||||||
|
if (error == NULL) {
|
||||||
|
um_realm_manager_load (self, realms, discover->cancellable,
|
||||||
|
on_manager_load, g_object_ref (async));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
g_simple_async_result_take_error (async, error);
|
||||||
|
g_simple_async_result_complete (async);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (async);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
um_realm_manager_discover (UmRealmManager *self,
|
||||||
|
const gchar *input,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *res;
|
||||||
|
DiscoverClosure *discover;
|
||||||
|
|
||||||
|
g_return_if_fail (UM_IS_REALM_MANAGER (self));
|
||||||
|
g_return_if_fail (input != NULL);
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
|
||||||
|
um_realm_manager_discover);
|
||||||
|
discover = g_slice_new0 (DiscoverClosure);
|
||||||
|
discover->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
|
g_simple_async_result_set_op_res_gpointer (res, discover, discover_closure_free);
|
||||||
|
|
||||||
|
um_realm_provider_call_discover (UM_REALM_PROVIDER (self), input, cancellable,
|
||||||
|
on_provider_discover, g_object_ref (res));
|
||||||
|
|
||||||
|
g_object_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
GList *
|
||||||
|
um_realm_manager_discover_finish (UmRealmManager *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async;
|
||||||
|
DiscoverClosure *discover;
|
||||||
|
GList *realms;
|
||||||
|
|
||||||
|
g_return_val_if_fail (UM_IS_REALM_MANAGER (self), NULL);
|
||||||
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
|
||||||
|
um_realm_manager_discover), NULL);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||||
|
|
||||||
|
async = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
|
if (g_simple_async_result_propagate_error (async, error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
discover = g_simple_async_result_get_op_res_gpointer (async);
|
||||||
|
if (!discover->realms) {
|
||||||
|
g_set_error (error, UM_REALM_ERROR, UM_REALM_ERROR_GENERIC,
|
||||||
|
_("No such domain or realm found"));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
realms = discover->realms;
|
||||||
|
discover->realms = NULL;
|
||||||
|
return realms;
|
||||||
|
}
|
||||||
|
|
||||||
|
GList *
|
||||||
|
um_realm_manager_get_realms (UmRealmManager *self)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (UM_IS_REALM_MANAGER (self), NULL);
|
||||||
|
return g_hash_table_get_values (self->realms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
um_realm_join (UmRealmKerberos *realm,
|
||||||
|
GBytes *credentials,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GVariant *options;
|
||||||
|
GVariant *creds;
|
||||||
|
|
||||||
|
g_return_if_fail (UM_REALM_IS_KERBEROS (realm));
|
||||||
|
g_return_if_fail (credentials != NULL);
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
creds = g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
|
||||||
|
g_bytes_get_data (credentials, NULL),
|
||||||
|
g_bytes_get_size (credentials),
|
||||||
|
TRUE, (GDestroyNotify)g_bytes_unref, credentials);
|
||||||
|
options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
|
||||||
|
|
||||||
|
um_realm_kerberos_call_enroll_with_credential_cache (realm,
|
||||||
|
g_variant_ref_sink (creds),
|
||||||
|
g_variant_ref_sink (options),
|
||||||
|
cancellable,
|
||||||
|
callback,
|
||||||
|
user_data);
|
||||||
|
|
||||||
|
g_variant_unref (options);
|
||||||
|
g_variant_unref (creds);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
um_realm_join_finish (UmRealmKerberos *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GError *call_error = NULL;
|
||||||
|
gchar *dbus_error;
|
||||||
|
|
||||||
|
g_return_val_if_fail (UM_REALM_IS_KERBEROS (self), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
um_realm_kerberos_call_enroll_with_credential_cache_finish (self,
|
||||||
|
result,
|
||||||
|
&call_error);
|
||||||
|
if (call_error == NULL)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
dbus_error = g_dbus_error_get_remote_error (call_error);
|
||||||
|
if (dbus_error == NULL) {
|
||||||
|
g_propagate_error (error, call_error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dbus_error_strip_remote_error (call_error);
|
||||||
|
|
||||||
|
if (g_str_equal (dbus_error, "org.freedesktop.realmd.Error.AuthFailed")) {
|
||||||
|
g_set_error (error, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN,
|
||||||
|
call_error->message);
|
||||||
|
g_error_free (call_error);
|
||||||
|
} else {
|
||||||
|
g_propagate_error (error, call_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (dbus_error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gchar *domain;
|
||||||
|
gchar *realm;
|
||||||
|
gchar *user;
|
||||||
|
gchar *password;
|
||||||
|
GBytes *credentials;
|
||||||
|
} LoginClosure;
|
||||||
|
|
||||||
|
static void
|
||||||
|
login_closure_free (gpointer data)
|
||||||
|
{
|
||||||
|
LoginClosure *login = data;
|
||||||
|
g_free (login->domain);
|
||||||
|
g_free (login->realm);
|
||||||
|
g_free (login->user);
|
||||||
|
g_free (login->password);
|
||||||
|
g_bytes_unref (login->credentials);
|
||||||
|
g_slice_free (LoginClosure, login);
|
||||||
|
}
|
||||||
|
|
||||||
|
static krb5_error_code
|
||||||
|
login_perform_kinit (krb5_context k5,
|
||||||
|
const gchar *realm,
|
||||||
|
const gchar *login,
|
||||||
|
const gchar *password,
|
||||||
|
const gchar *filename)
|
||||||
|
{
|
||||||
|
krb5_get_init_creds_opt *opts;
|
||||||
|
krb5_error_code code;
|
||||||
|
krb5_principal principal;
|
||||||
|
krb5_ccache ccache;
|
||||||
|
krb5_creds creds;
|
||||||
|
gchar *name;
|
||||||
|
|
||||||
|
name = g_strdup_printf ("%s@%s", login, realm);
|
||||||
|
code = krb5_parse_name (k5, name, &principal);
|
||||||
|
g_free (name);
|
||||||
|
|
||||||
|
if (code != 0)
|
||||||
|
return code;
|
||||||
|
|
||||||
|
if (filename == NULL)
|
||||||
|
code = krb5_cc_default (k5, &ccache);
|
||||||
|
else
|
||||||
|
code = krb5_cc_resolve (k5, filename, &ccache);
|
||||||
|
|
||||||
|
if (code != 0) {
|
||||||
|
krb5_free_principal (k5, principal);
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
code = krb5_get_init_creds_opt_alloc (k5, &opts);
|
||||||
|
g_return_val_if_fail (code == 0, code);
|
||||||
|
|
||||||
|
code = krb5_get_init_creds_opt_set_out_ccache (k5, opts, ccache);
|
||||||
|
g_return_val_if_fail (code == 0, code);
|
||||||
|
|
||||||
|
code = krb5_get_init_creds_password (k5, &creds, principal,
|
||||||
|
(char *)password,
|
||||||
|
NULL, 0, 0, NULL, opts);
|
||||||
|
|
||||||
|
krb5_get_init_creds_opt_free (k5, opts);
|
||||||
|
krb5_cc_close (k5, ccache);
|
||||||
|
krb5_free_principal (k5, principal);
|
||||||
|
|
||||||
|
if (code == 0)
|
||||||
|
krb5_free_cred_contents (k5, &creds);
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
kinit_thread_func (GSimpleAsyncResult *async,
|
||||||
|
GObject *object,
|
||||||
|
GCancellable *cancellable)
|
||||||
|
{
|
||||||
|
LoginClosure *login = g_simple_async_result_get_op_res_gpointer (async);
|
||||||
|
krb5_context k5 = NULL;
|
||||||
|
krb5_error_code code;
|
||||||
|
GError *error = NULL;
|
||||||
|
gchar *filename = NULL;
|
||||||
|
gchar *contents;
|
||||||
|
gsize length;
|
||||||
|
gint temp_fd;
|
||||||
|
|
||||||
|
filename = g_build_filename (g_get_user_runtime_dir (),
|
||||||
|
"um-krb5-creds.XXXXXX", NULL);
|
||||||
|
temp_fd = g_mkstemp_full (filename, O_RDWR, S_IRUSR | S_IWUSR);
|
||||||
|
if (temp_fd == -1) {
|
||||||
|
g_warning ("Couldn't create credential cache file: %s: %s",
|
||||||
|
filename, g_strerror (errno));
|
||||||
|
g_free (filename);
|
||||||
|
filename = NULL;
|
||||||
|
} else {
|
||||||
|
close (temp_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
code = krb5_init_context (&k5);
|
||||||
|
if (code == 0) {
|
||||||
|
code = login_perform_kinit (k5, login->realm, login->user,
|
||||||
|
login->password, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case 0:
|
||||||
|
if (filename != NULL) {
|
||||||
|
g_file_get_contents (filename, &contents, &length, &error);
|
||||||
|
if (error == NULL) {
|
||||||
|
login->credentials = g_bytes_new_take (contents, length);
|
||||||
|
} else {
|
||||||
|
g_warning ("Couldn't read credential cache: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
|
||||||
|
case KRB5KDC_ERR_CLIENT_REVOKED:
|
||||||
|
case KRB5KDC_ERR_KEY_EXP:
|
||||||
|
case KRB5KDC_ERR_POLICY:
|
||||||
|
case KRB5KDC_ERR_ETYPE_NOSUPP:
|
||||||
|
g_simple_async_result_set_error (async, UM_REALM_ERROR, UM_REALM_ERROR_BAD_LOGIN,
|
||||||
|
_("Cannot log in as %s at the %s domain"),
|
||||||
|
login->user, login->domain);
|
||||||
|
break;
|
||||||
|
case KRB5KDC_ERR_PREAUTH_FAILED:
|
||||||
|
g_simple_async_result_set_error (async, UM_REALM_ERROR, UM_REALM_ERROR_BAD_PASSWORD,
|
||||||
|
_("Invalid password, please try again"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_simple_async_result_set_error (async, UM_REALM_ERROR, UM_REALM_ERROR_GENERIC,
|
||||||
|
_("Couldn't connect to the %s domain: %s"),
|
||||||
|
login->domain, krb5_get_error_message (k5, code));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename) {
|
||||||
|
g_unlink (filename);
|
||||||
|
g_free (filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k5)
|
||||||
|
krb5_free_context (k5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
um_realm_login (const gchar *realm,
|
||||||
|
const gchar *domain,
|
||||||
|
const gchar *user,
|
||||||
|
const gchar *password,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async;
|
||||||
|
LoginClosure *login;
|
||||||
|
|
||||||
|
g_return_if_fail (realm != NULL);
|
||||||
|
g_return_if_fail (user != NULL);
|
||||||
|
g_return_if_fail (password != NULL);
|
||||||
|
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
|
||||||
|
|
||||||
|
async = g_simple_async_result_new (NULL, callback, user_data,
|
||||||
|
um_realm_login);
|
||||||
|
login = g_slice_new0 (LoginClosure);
|
||||||
|
login->domain = g_strdup (domain ? domain : realm);
|
||||||
|
login->realm = g_strdup (realm);
|
||||||
|
login->user = g_strdup (user);
|
||||||
|
login->password = g_strdup (password);
|
||||||
|
g_simple_async_result_set_op_res_gpointer (async, login, login_closure_free);
|
||||||
|
|
||||||
|
g_simple_async_result_set_handle_cancellation (async, TRUE);
|
||||||
|
g_simple_async_result_run_in_thread (async, kinit_thread_func,
|
||||||
|
G_PRIORITY_DEFAULT, cancellable);
|
||||||
|
|
||||||
|
g_object_unref (async);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
um_realm_login_finish (GAsyncResult *result,
|
||||||
|
GBytes **credentials,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async;
|
||||||
|
LoginClosure *login;
|
||||||
|
|
||||||
|
g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
|
||||||
|
um_realm_login), FALSE);
|
||||||
|
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||||
|
|
||||||
|
async = G_SIMPLE_ASYNC_RESULT (result);
|
||||||
|
if (g_simple_async_result_propagate_error (async, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
login = g_simple_async_result_get_op_res_gpointer (async);
|
||||||
|
if (credentials) {
|
||||||
|
if (login->credentials)
|
||||||
|
*credentials = g_bytes_ref (login->credentials);
|
||||||
|
else
|
||||||
|
*credentials = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
91
panels/user-accounts/um-realm-manager.h
Normal file
91
panels/user-accounts/um-realm-manager.h
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright 2012 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Written by: Stef Walter <stefw@gnome.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UM_REALM_MANAGER_H__
|
||||||
|
#define __UM_REALM_MANAGER_H__
|
||||||
|
|
||||||
|
#include "um-realm-generated.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UM_REALM_ERROR_BAD_LOGIN,
|
||||||
|
UM_REALM_ERROR_BAD_PASSWORD,
|
||||||
|
UM_REALM_ERROR_GENERIC,
|
||||||
|
} UmRealmErrors;
|
||||||
|
|
||||||
|
#define UM_REALM_ERROR (um_realm_error_get_quark ())
|
||||||
|
|
||||||
|
GQuark um_realm_error_get_quark (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define UM_TYPE_REALM_MANAGER (um_realm_manager_get_type ())
|
||||||
|
#define UM_REALM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UM_TYPE_REALM_MANAGER, UmRealmManager))
|
||||||
|
#define UM_IS_REALM_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UM_TYPE_REALM_MANAGER))
|
||||||
|
|
||||||
|
typedef struct _UmRealmManager UmRealmManager;
|
||||||
|
|
||||||
|
GType um_realm_manager_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
void um_realm_manager_new (GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
UmRealmManager * um_realm_manager_new_finish (GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void um_realm_manager_discover (UmRealmManager *self,
|
||||||
|
const gchar *input,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
GList * um_realm_manager_discover_finish (UmRealmManager *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
GList * um_realm_manager_get_realms (UmRealmManager *self);
|
||||||
|
|
||||||
|
void um_realm_login (const gchar *realm_name,
|
||||||
|
const gchar *domain,
|
||||||
|
const gchar *login,
|
||||||
|
const gchar *password,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean um_realm_login_finish (GAsyncResult *result,
|
||||||
|
GBytes **credentials,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
void um_realm_join (UmRealmKerberos *realm,
|
||||||
|
GBytes *credentials,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
gboolean um_realm_join_finish (UmRealmKerberos *self,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __UM_REALM_H__ */
|
Loading…
Add table
Add a link
Reference in a new issue