ACC SHELL

Path : /usr/share/YaST2/modules/
File Upload :
Current File : //usr/share/YaST2/modules/Samba.ycp

/**
 * File:	modules/Samba.ycp
 * Package:	Configuration of samba-client
 * Summary:	Data for configuration of samba-client, input and output functions.
 * Authors:	Stanislav Visnovsky <visnov@suse.cz>
 *
 * $Id: Samba.ycp 60041 2009-12-10 12:59:56Z jsuchome $
 *
 * Representation of the configuration of samba-client.
 * Input and output routines.
 */

{

module "Samba";
textdomain "samba-client";

import "Autologin";
import "FileUtils";
import "NetworkConfig";
import "Mode";
import "Nsswitch";
import "Package";
import "Pam";
import "Progress";
import "Report";
import "Service";
import "SambaAD";
import "SambaConfig";
import "SambaWinbind";
import "SambaNetJoin";
import "SambaNmbLookup";
import "String";
import "Summary";
import "SuSEFirewall";


/**
 * Data was modified?
 */
global boolean modified = false;

/**
 * Are globals already configured (for AutoYaST)
 */
global boolean globals_configured = false;

/**
 * Write only, used during autoinstallation.
 * Don't run services and SuSEconfig, it's all done at one place.
 */
global boolean write_only = false;

/**
 * Should be winbind enabled?
 */
global boolean winbind_enabled = false;

/**
 * If FAM should be started
 */
global boolean start_fam	= true;

/**
 * if pam_mkhomedir is set in /etc/pam.d/commond-session
 */
global boolean mkhomedir	= false;

// if it mkhomedir was modified
boolean mkhomedir_modified	= false;

// if shares config (actually group owner) was modified
boolean shares_modified		= false;

/**
 * map with user name and password (used for autoinstallation only)
 */
global map<string,string> password_data	= $[];

// dir with user shares
global string shares_dir	= "/var/lib/samba/usershares";

// path to config file with DHCP settings
string dhcp_path		= "/etc/samba/dhcp.conf";

// if existing shares should be removed
global boolean remove_shares	= false;

// if smb + nmb services should be stopped
global boolean stop_services	= false;

global string shares_group	= "users";

global string shares_separator	= "\\";

// remember if the last join was succesful
global symbol in_domain         = nil;

// if changing hostname by DHCP should be disabled (#169260)
global boolean disable_dhcp_hostname	= false;

// support for SSH single-sign-on (fate #303415)
global boolean ssh_support	= false;

// initial status of single-sign-on suport in ssh_config
boolean ssh_was_enabled		= false;

// initial status of single-sign-on suport in sshd_config
boolean sshd_was_enabled	= false;

// if it ssh support was modified
boolean ssh_modified		= false;

// section in /etc/ssh/ssh_config file for storing single-sign-on settings
string ssh_section = "*";

// if hosts are resolved via WINS
boolean hosts_resolution	= nil;

// host line of nsswitch.conf
list<string> hosts_db		= [];

// original value of hosts_resolution, for detecting changes
boolean hosts_resolution_orig	= false;

// path to pam_mount.conf.xml
string pam_mount_path	= "/etc/security/pam_mount.conf.xml";

// the volume data from pam_mount.conf.xml
list<map> pam_mount_volumes		= [];

// original value of pam_mount_volumes, for detecting changes
list<map> pam_mount_volumes_orig	= nil;

// network configuration (to be read from NetworkConfig module)
global map network_setup	= NetworkConfig::Export ();

global boolean PAMMountModified () {

    return
    (pam_mount_volumes_orig == nil && pam_mount_volumes != [])
    ||
    (pam_mount_volumes_orig != nil &&
     (sort (pam_mount_volumes) != sort (pam_mount_volumes_orig)));
}


/**
 * Data was modified?
 * @return true if modified
 */
global boolean GetModified() {
    y2debug("modified=%1",modified);
    return modified || mkhomedir_modified || shares_modified || SambaConfig::GetModified() || ssh_modified || PAMMountModified ();
};

/**
 * Read the data from /etc/security/pam_mount.conf.xml regarding
 * mounting user's home directories
 */
global boolean ReadPAMMount () {

    if (!FileUtils::Exists (pam_mount_path))
    {
	y2warning ("%1 does not exist", pam_mount_path);
	return false;
    }
    // initially, parse the whole file and let the agent build data map
    if (SCR::Read (.pam_mount, pam_mount_path) != true)
    {
	y2warning ("reading %1 failed", pam_mount_path);
	return false;
    }

    pam_mount_volumes	= (list<map>) SCR::Read (.pam_mount.get, $[
	"element"   : "volume",
    ]);
    if (pam_mount_volumes == nil)
	pam_mount_volumes	= [];

    pam_mount_volumes_orig	= pam_mount_volumes;
    return true;
}

/**
 * Return the list of 'volume' entries from pam_mount.conf.xml
 */
global list<map> GetPAMMountVolumes () {

    return pam_mount_volumes;
}

/**
 * Set the new list of 'volume' entries
 */
global void SetPAMMountVolumes (list<map> new_volumes) {

    pam_mount_volumes	= new_volumes;
}

/**
 * Write the changes to /etc/security/pam_mount.conf.xml
 */
global boolean WritePAMMount () {

    if (!FileUtils::Exists (pam_mount_path))
    {
	y2warning ("%1 does not exist, no writing", pam_mount_path);
	return false;
    }
    if (pam_mount_volumes_orig == nil)
    {
	y2milestone ("%1 not read yet, reading now...", pam_mount_path);
        if (SCR::Read (.pam_mount, pam_mount_path) != true)
	{
	    y2error ("reading %1 failed", pam_mount_path);
	    return false;
	}
    }
    if (!PAMMountModified ())
    {
	y2milestone ("no changes to pam_mount.conf.xml");
	return true;
    }

    SCR::Execute (.target.bash, sformat ("cp %1 %1.YaST2save", pam_mount_path));

    // 1. delete all volume entries with 'cifs' fstype
    SCR::Write (.pam_mount.delete, $[
	"element"       : "volume",
	"attrmap"	: $[
	    "fstype"	: "cifs"
	]
    ]);

    // 2. save the new set of volume entries
    foreach (map volume, pam_mount_volumes, {
	if (volume["fstype"]:"" != "cifs")
	    return;
	// if no volume entry is present, add new
	SCR::Write (.pam_mount.add, $[
	    "element"	: "volume",
	    // ... the keys without values should not end in config file
	    "attrmap"	: filter (
		string k, string v, (map<string,string>)volume,``(v != "")),
	    "newline"	: true
	]);
    });
    SCR::Write (.pam_mount, nil);
    return true;
}

/**
 * Read the state of mkhomedir in /etc/pam.d/common-session (bug #143519)
 */
global define boolean ReadMkHomeDir () {

    mkhomedir	= Pam::Enabled ("mkhomedir");
    return mkhomedir;
}

/**
 * Write the new value of pam_mkhomedir to /etc/pam.d/common-session
 * @param boolean new status
 */
global define boolean WriteMkHomeDir (boolean enabled) {

    if (!mkhomedir_modified)
	return true;
    return Pam::Set ("mkhomedir", enabled);
}

/**
 * Set the new value of mkhomedir
 */
global define boolean SetMkHomeDir (boolean new_value) {

    if (mkhomedir != new_value)
    {
	mkhomedir_modified	= true;
        mkhomedir = new_value;
    }
    return mkhomedir;

}

/**
 * get number of max shares from smb.conf; 0 mean shares are not enabled
 */
global define integer GetMaxShares () {

    return SambaConfig::GlobalGetInteger ("usershare max shares", 0);
}

/**
 * Read /etc/nsswitch.conf and check if WINS is used for hosts resolution
 */
global boolean GetHostsResolution () {

    if (hosts_resolution == nil)
    {
	hosts_db		= Nsswitch::ReadDb ("hosts");
	hosts_resolution	= contains (hosts_db, "wins");
	hosts_resolution_orig	= hosts_resolution;
    }
    return hosts_resolution;
}

/**
 * Set the new value for hosts resolution
 */
global boolean SetHostsResolution (boolean resolve) {

    hosts_resolution	= resolve;
    return true;
}

/**
 * Write /etc/nsswitch.conf if modified
 */
global boolean WriteHostsResolution () {

    if (hosts_resolution != hosts_resolution_orig)
    {
	if (hosts_resolution)
	    hosts_db	= add (hosts_db, "wins");
	else
	    hosts_db	= filter (string e, hosts_db, ``(e != "wins"));
	Nsswitch::WriteDb ("hosts", hosts_db);
	boolean ret	= Nsswitch::Write ();
	y2milestone ("/etc/nsswitch.conf written: %1", ret);
	return ret;
    }
    return true;
}


/**
 * Check if dhcp.conf is included in smb.conf
 */
global define boolean GetDHCP () {

    list<string> include_list	= SambaConfig::GlobalGetList ("include", []);
    return contains (include_list, dhcp_path);
}

/**
 * Set the support of DHCP (include dhcp.conf in smb.conf)
 * @return if status was changed
 */
global define boolean SetDHCP (boolean new) {

    list<string> include_list	= SambaConfig::GlobalGetList ("include", []);
    if (new && !contains (include_list, dhcp_path))
    {
	include_list	= (list<string>) union (include_list, [dhcp_path]);
    }
    else if (!new && contains (include_list, dhcp_path))
    {
	include_list	= filter (string i, include_list, ``(i != dhcp_path));
    }
    else return false;
    SambaConfig::GlobalSetList ("include", include_list);
    return true;
}

/**
 * check if shares guest access is allowed
 */
global define boolean GetGuessAccess () {

    return SambaConfig::GlobalGetTruth ("usershare allow guests", false);
}

/**
 * Set the new value for guest access (#144787)
 */
global define boolean SetGuessAccess (boolean guest) {

    SambaConfig::GlobalSetTruth ("usershare allow guests", guest);
    return true;
}

/**
 * Read user shares settings
 */
global define boolean ReadSharesSetting () {

    shares_dir	= SambaConfig::GlobalGetStr ("usershare path", shares_dir);
    if (shares_dir != nil && FileUtils::Exists (shares_dir))
    {
	map stat	= (map) SCR::Read (.target.stat, shares_dir);
	map out		= (map) SCR::Execute (.target.bash_output, sformat ("getent group | grep \":%1:\" | /usr/bin/cut -f 1 -d :", stat["gid"]:100));
	shares_group	= String::FirstChunk (out["stdout"]:"", "\n");
    }
    shares_separator	= SambaConfig::GlobalGetStr ("winbind separator", "\\");
}

/**
 * set the new values for user shares
 * @param max maximum number of shares (0 is for disabling)
 * @param group permited group
 */
global define boolean SetShares (integer max, string group)
{
    SambaConfig::GlobalSetStr ("usershare max shares", max > 0 ? max : nil);

    if (shares_group != group)
	shares_modified	= true;
    shares_group	= group;
    return true;
}

/**
 * Get the current status of winbind caching
 */
global define boolean GetWinbindCaching () {

    string cached = SambaConfig::WinbindGlobalGetStr ("cached_login", "");
    string offline = SambaConfig::GlobalGetStr ("winbind offline logon", "");
    return cached == "yes" && offline == "yes";
}

/**
 * Set the new value for winbind caching (see bug #143927)
 */
global define boolean SetWinbindCaching (boolean enable) {

    SambaConfig::WinbindGlobalSetStr("cached_login", enable ? "yes" : nil);
    SambaConfig::GlobalSetStr("winbind offline logon", enable ? "yes" : nil);
    return enable;
}

/**
 * Read the current status of ssh single-sign-on support (fate #303415)
 */
global define boolean ReadSSHSupport () {

    boolean ssh		= nil;
    boolean sshd	= false;

    if (FileUtils::Exists ("/etc/ssh/ssh_config") &&
	FileUtils::Exists ("/etc/ssh/sshd_config"))
    {
	string hostname = "*";
	map out = (map)SCR::Execute(.target.bash_output,"LANG=C /bin/hostname");
	if (out["stderr"]:nil == "")
	    hostname = deletechars(out["stdout"]:"", "\n");
	foreach (string sec, SCR::Dir (.etc.ssh.ssh_config.s), {
	    if (ssh != nil) return;
	    list cont = SCR::Dir (add(.etc.ssh.ssh_config.v, sec));
	    y2debug ("section %1 contains: %2", sec, cont);

	    if ((sec == "*" || sec == hostname) &&
		(contains (cont, "GSSAPIAuthentication") &&
		contains (cont, "GSSAPIDelegateCredentials")))
	    {
		ssh =
		    (SCR::Read (add (add (.etc.ssh.ssh_config.v, sec),
			"GSSAPIAuthentication")) == "yes") &&
		    (SCR::Read (add (add (.etc.ssh.ssh_config.v, sec),
			"GSSAPIDelegateCredentials")) == "yes");
		ssh_section = sec;
	    }
	});
	sshd	= true;
	foreach (string key, ["GSSAPIAuthentication","GSSAPICleanupCredentials",
	    "ChallengeResponseAuthentication", "UsePAM" ], {
	    sshd	= sshd && contains (
		(list)SCR::Read (add (.etc.ssh.sshd_config, key)), "yes");
	});
    }
    ssh_was_enabled	= (ssh == true);
    sshd_was_enabled	= sshd;
    ssh_support	= ssh_was_enabled && sshd_was_enabled;
    return ssh_support;
}

/**
 * Get the current status of ssh single-sign-on support
 */
global define boolean GetSSHSupport () {
    return ssh_support;
}

/**
 * Set the new value for sh single-sign-on support
 */
global define boolean SetSSHSupport (boolean enable) {
    ssh_support	= enable;
    ssh_modified	= (enable != (ssh_was_enabled && sshd_was_enabled));
    return enable;
}

/**
 * Write the new value for sh single-sign-on support (fate #303415)
 */
global define boolean WriteSSHSupport (boolean enable) {

    string write = enable ? "yes": "no";

    // do not write "no" everywhere, there might be some user setting...
    if (enable || ssh_was_enabled)
    {
	SCR::Write (add (add (.etc.ssh.ssh_config.v, ssh_section),
	    "GSSAPIAuthentication"), write);
	SCR::Write (add (add (.etc.ssh.ssh_config.v, ssh_section),
	    "GSSAPIDelegateCredentials"), write);
	SCR::Write (.etc.ssh.ssh_config, nil);
	y2milestone ("/etc/ssh/ssh_config modified");
    }
    if (enable || sshd_was_enabled)
    {
	foreach (string key, ["GSSAPIAuthentication","GSSAPICleanupCredentials",
	    "ChallengeResponseAuthentication", "UsePAM" ], {
	    SCR::Write (add (.etc.ssh.sshd_config, key), [write]);
	});
	SCR::Write (.etc.ssh.sshd_config, nil);
	y2milestone ("/etc/ssh/sshd_config modified");
    }
    return enable;
}

/**
 * Start/Stop and FAM service according to current settings
 * @param write_only do not start/stop services
 * @return success
 */
define boolean WriteFAM (boolean write_only) {

    if (start_fam)
    {
	if (!Package::InstalledAll (["fam","fam-server"]))
	    return false;

	Service::Enable ("fam");
	if (! write_only) Service::Start ("fam");
    }
    else
    {
	Service::Disable ("fam");
	if (!write_only) Service::Stop ("fam");
    }
    return true;
}

/**
 * create the shares directory with correct rights
 */
global boolean WriteShares () {

    if (!FileUtils::Exists (shares_dir))
    {
	SCR::Execute (.target.mkdir, shares_dir);
    }
    else if (remove_shares)
    {
	SCR::Execute (.target.bash, sformat ("/bin/rm -f %1/*", shares_dir));
    }
    if (FileUtils::Exists (shares_dir))
    {
	if (shares_group == "") shares_group = "users";
	SCR::Execute (.target.bash, sformat ("/bin/chmod 1770 %1; /bin/chgrp '%2' %1", shares_dir, shares_group));
    }
    return true;
}

/**
 * adjust the services for sharing
 */
global boolean AdjustSharesServices (boolean write_only) {

    if (GetMaxShares () > 0)
    {
	foreach (string service, [ "nmb", "smb"], {
	    Service::Enable (service);
	    if (! write_only)
	    {
		if (Service::Status (service) == 0)
		    Service::Restart (service);
		else
		    Service::Start (service);
	    }
	});
    }
    else if (stop_services)
    {
	Service::Disable ("nmb");
	Service::Disable ("smb");
	if (! write_only)
	{
	     Service::Stop ("nmb");
	     Service::Stop ("smb");
	}
    }
    return true;
}

/**
 * Tell displaymanager (KDM/GDM) to use special windbind greeter
 * @param enable if  winbind is enabled
 * @param write_only do not run SuSEconfig script
 * @return success
 */
define boolean WriteDisplayManager (boolean enable, boolean write_only) {

    if (!FileUtils::Exists ("/etc/sysconfig/displaymanager"))
	return false;

    if (enable)
    {
	if (!Package::InstalledAny (["kdebase3-kdm", "kde4-kdm", "gdm", "kdm"]))
	    return false;
	if (SCR::Read (.sysconfig.displaymanager.DISPLAYMANAGER_AD_INTEGRATION) == "yes")
	    return true;
    }

    SCR::Write (.sysconfig.displaymanager.DISPLAYMANAGER_AD_INTEGRATION,
	enable ? "yes" : "no");
    SCR::Write (.sysconfig.displaymanager, nil);

    string dm = (string) SCR::Read (.sysconfig.displaymanager.DISPLAYMANAGER);

    if (!write_only && dm == "gdm")
    {
	SCR::Execute (.target.bash, "/sbin/SuSEconfig --module gdm");
    }
    return true;
}

/**
 * Read all samba-client settings
 * @return true on success
 */
global boolean Read() {

    /* Samba-client read dialog caption */
    string caption = _("Initializing Samba Client Configuration");

    integer steps = 2;

    // We do not set help text here, because it was set outside
    Progress::New( caption, " ", steps, [
	    // translators: progress stage 1/2
	    _("Read the global Samba settings"),
	    // translators: progress stage 2/2
	    _("Read the winbind status"),
	], [
	    // translators: progress step 1/2
	    _("Reading the global Samba settings..."),
	    // translators: progress step 2/2
	    _("Reading the winbind status..."),
	    // translators: progress finished
	    _("Finished")
	],
	""
    );

    // read global settings
    Progress::NextStage();

    SambaConfig::Read(false);

    // read winbind status
    Progress::NextStage();
    winbind_enabled = SambaWinbind::IsEnabled();

    // start nmbstatus in background
    if (!Mode::test()) {
	SambaNmbLookup::Start();
    }

    ReadMkHomeDir ();

    ReadSharesSetting ();

    GetHostsResolution ();

    ReadSSHSupport ();

    Autologin::Read();

    // read network settings
    // (for bug 169260: do not allow DHCP to change the hostname)
    NetworkConfig::Read ();
    network_setup	= NetworkConfig::Export ();

    SuSEFirewall::Read ();

    ReadPAMMount ();

    // finished
    Progress::NextStage();
    globals_configured = true;
    modified = false;
    return true;
}

/**
 * Set a windind status
 *
 * @param group	a new winbind status
 */
global define void SetWinbind(boolean status) ``{
    if (status != winbind_enabled) {
	modified = true;
	winbind_enabled = status;
    }
    SambaAD::AdjustSambaConfig(status);
    SambaWinbind::AdjustSambaConfig(status);
}

/**
 * Write all samba-client settings
 * @return true on success
 */
global boolean Write(boolean write_only) {
    boolean ret = true;

    /* Samba-client read dialog caption */
    string caption = _("Saving Samba Client Configuration");

    list<string> stages	= [
	    // translators: write progress stage
	    _("Write the settings"),
	    // translators: write progress stage
	    !winbind_enabled ? _("Disable Samba services") :
		// translators: write progress stage
		_("Enable Samba services")
    ];
    list<string> steps	= [
	    // translators: write progress step
	    _("Writing the settings..."),
	    // translators: write progress step
	    !winbind_enabled ? _("Disabling Samba services...")
		// translators: write progress step
		: _("Enabling Samba services..."),
	    // translators: write progress finished
	    _("Finished")
    ];

    if (SambaAD::ADS () != "" && winbind_enabled)
    {
	// write progress stage
	stages	= add (stages, _("Write Kerberos configuration"));
	// write progress step
	steps	= add (steps, _("Writing Kerberos configuration..."));
    }

    // bug 169260: do not allow DHCP to change the hostname
    if (winbind_enabled && disable_dhcp_hostname)
    {
	if (network_setup == $[])
	{
	    NetworkConfig::Read ();
	    network_setup	= NetworkConfig::Export ();
	}
	network_setup["dhcp","DHCLIENT_SET_HOSTNAME"]	= "no";
	NetworkConfig::Import (network_setup);
	NetworkConfig::Write ();
    }

    // We do not set help text here, because it was set outside
    Progress::New (caption, " ", size (stages), stages, steps, "");

    // write settings
    Progress::NextStage();
    // if nothing to write, quit (but show at least the progress bar :-)
    if (!GetModified()) return true;

    if (Mode::autoinst ())
    {
	if (SambaAD::ADS () != "")
	{
	    SambaConfig::GlobalSetStr("workgroup",
	      SambaAD::GetWorkgroup(SambaConfig::GlobalGetStr("workgroup","")));
	    SambaAD::ReadRealm ();
	}
	// join the domain during autoinstallation
	if (password_data != $[])
	{
	    SambaNetJoin::Join (SambaConfig::GlobalGetStr("workgroup",""),
		"member",
		password_data["user"]:password_data["username"]:"",
		password_data["password"]:password_data["passwd"]:"",
		password_data["machine"]:nil
	    );
	}
    }

    if (!SambaConfig::Write(write_only)) {
	// translators: error message, %1 is filename
	Report::Error (sformat(_("Cannot write settings to %1."), "/etc/samba/smb.conf") );
	ret = false;
    }

    // winbind
    Progress::NextStage();
    if (winbind_enabled) {
	if (!Package::Installed("samba-winbind") && !Mode::test()) {
		ret = false;
	}
	if (!SambaWinbind::AdjustService(true)) {
	    // translators: error message, do not change winbind
	    Report::Error( _("Cannot start winbind service."));
	    ret = false;
	}
	if (!write_only && !SambaWinbind::StartStopNow(true)) {
	    // translators: error message, do not change winbind
	    Report::Error(_("Cannot start winbind daemon."));
	    ret = false;
	}
    } else {
	if (!SambaWinbind::AdjustService(false)) {
	    // translators: error message, do not change winbind
	    Report::Error( _("Cannot stop winbind service."));
	    ret = false;
	}
	if (!write_only && !SambaWinbind::StartStopNow(false)) {
	    // translators: error message, do not change winbind
	    Report::Error(_("Cannot stop winbind daemon."));
	    ret = false;
	}
    }
    if (!SambaWinbind::AdjustNsswitch(winbind_enabled, write_only)) {
	// translators: error message, %1 is filename
	Report::Error(sformat(_("Cannot write settings to %1."), "/etc/nsswitch.conf"));
	ret = false;
    }
    if (!SambaWinbind::AdjustPam(winbind_enabled)) {
	// translators: error message
	Report::Error (_("Cannot write PAM settings."));
	ret = false;
    }

    if (SambaAD::ADS () != "" && winbind_enabled)
	Progress::NextStage();

    if (!SambaAD::AdjustKerberos (winbind_enabled)) {
	// translators: error message, %1 is filename
	Report::Error(sformat(_("Cannot write settings to %1."), "/etc/krb5.conf"));
	ret = false;
    }

    WriteMkHomeDir (mkhomedir);

    // if autologin was modified, SuSEconfig script will be called there
    WriteDisplayManager (winbind_enabled, write_only || Autologin::modified);

    Autologin::Write(write_only);	// see dialog.ycp

    WriteShares ();
    AdjustSharesServices (write_only);

    WriteSSHSupport (ssh_support);

    WriteHostsResolution ();

    SuSEFirewall::WriteOnly ();
    if (!write_only)
	SuSEFirewall::ActivateConfiguration ();

    if (WritePAMMount () && size (pam_mount_volumes) > 0)
    {
	// enable pam_mount for services gdm, xdm, login, sshd (bnc#433845)
	foreach (string service, ["gdm", "login", "xdm", "sshd" ], {
	    map out = (map)SCR::Execute (.target.bash_output, sformat (
		"pam-config --service %1 -a --mount", service));
	    if (out["stderr"]:"" != "")
		y2warning ("pam-config failed for service %1", service);
	});
    }

    // finished
    Progress::NextStage();
    modified = false;

    return ret;
}

/**
 * Get all samba-client settings from the first parameter
 * (For use by autoinstallation.)
 * @param settings The YCP structure to be imported.
 * @return boolean True on success
 */
global boolean Import (map settings) {

    if (haskey(settings, "global")) {
	map globals	= settings["global"]:$[];
	SambaConfig::GlobalSetStr("workgroup",globals["workgroup"]:"WORKGROUP");

	if (tolower (globals["winbind_offline_logon"]:"") == "yes" &&
	    tolower (globals["cached_login"]:"") == "yes")
	    SetWinbindCaching (true);

	if (haskey (globals, "usershare_max_shares") ||
	    haskey (settings, "shares_group"))
	    SetShares (tointeger (globals["usershare_max_shares"]:"0"),
		settings["shares_group"]:shares_group);

	if (tolower (globals["usershare_allow_guests"]:"") == "yes")
	    SetGuessAccess (true);

	globals_configured = true;
        modified	= true;
    } else {
	globals_configured = false;
    }
    if (haskey (settings, "shares_group"))
	shares_group	= settings["shares_group"]:shares_group;

    if (haskey(settings, "active_directory"))
    {
	SambaAD::SetADS	(settings["active_directory","kdc"]:"");
    }
    // call this _after_ evaluation if AD is used
    boolean winbind = settings["winbind"]:settings["global","winbind"]:false;
    if (winbind != nil)
    {
	SetWinbind (winbind);
    }
    if (haskey(settings, "join"))
    {
	password_data	= settings["join"]:$[];
    }
    if (haskey (settings, "mkhomedir"))
    {
	SetMkHomeDir (settings["mkhomedir"]:mkhomedir);
    }
    disable_dhcp_hostname	= settings["disable_dhcp_hostname"]:disable_dhcp_hostname;

    return true;
}

/**
 * Dump the samba-client settings to a single map
 * (For use by autoinstallation.)
 * @return map Dumped settings (later acceptable by Import ())
 */
global map Export () {

    if (!globals_configured) {
	return $[];
    }
    map ret	= $[
	"winbind"	: winbind_enabled
    ];
    if (mkhomedir_modified)
	ret["mkhomedir"]	= mkhomedir;

    if (shares_modified && shares_group != "")
	ret["shares_group"]	= shares_group;

    if (disable_dhcp_hostname)
	ret["disable_dhcp_hostname"]	= disable_dhcp_hostname;

    foreach (map sect, (list<map>) SambaConfig::Export (), {
	string name	= sect["name"]:"";
	ret[name]	= sect["parameters"]:$[];
    });

    if (SambaAD::ADS() != "")
    {
	ret["active_directory"]	= $[
	    "kdc" : SambaAD::ADS()
	];
    }
    // export user & password to "join" map
    map joinmap	= $[];
    foreach (string key, string val, password_data, {
	if (val != nil && val != "")
	    joinmap[key]	= val;
    });
    if (joinmap != $[])
	ret["join"]	= joinmap;
    modified = false;
    return ret;
}

/**
 * Create a textual summary and a list of unconfigured options
 * @return summary of the current configuration
 */
global string Summary() {

    string summary = "";
    string nc = Summary::NotConfigured();
    string workgroup = SambaConfig::GlobalGetStr("workgroup", "");

    // summary header
    summary = Summary::AddHeader(summary, _("Global Configuration"));

    if (globals_configured)
    {
	summary = Summary::AddLine (summary, sformat (
	    // autoyast summary item: configured workgroup
	    _("Workgroup or Domain: %1"), workgroup)
	);

	if (mkhomedir)
	    summary = Summary::AddLine (summary,
		// autoyast summary item
		_("Create Home Directory on Login")
	    );
	if (GetWinbindCaching ())
	    summary = Summary::AddLine (summary,
		// autoyast summary item
		_("Offline Authentication Enabled")
	    );
	if (GetMaxShares () > 0)
	{
	    summary = Summary::AddLine (summary, sformat (
		// autoyast summary item
		_("Maximum Number of Shares: %1"), GetMaxShares ())
	    );
	}
    }
    else
    {
	summary = Summary::AddLine(summary, nc );
    }
    return summary;
}

/**
 * Create shorter textual summary and a list of unconfigured options
 * @return summary of the current configuration
 */
global string ShortSummary() {

    string summary = "";
    string workgroup = SambaConfig::GlobalGetStr("workgroup", "");

    if (globals_configured) {
	// summary item: configured workgroup
	summary = sformat(_("<p><b>Workgroup or Domain</b>: %1</p>"), workgroup) +
	// summary item: authentication using winbind
	sformat(_("<p><b>Authentication with SMB</b>: %1</p>"),
	    // translators: winbind status in summary
	    winbind_enabled ? _("Yes")
	    // translators: winbind status in summary
		: _("No"));
    } else {
	summary = Summary::NotConfigured();
    }
    return summary;
}


/**
 * Set a host workgroup
 *
 * @param group	a new workgroup
 */
global void SetWorkgroup( string group ) {
    SambaConfig::GlobalSetStr("workgroup", group);
}

/**
 * Get a host workgroup
 *
 * @return string	a new workgroup
 */
global string GetWorkgroup() {
    return SambaConfig::GlobalGetStr("workgroup", "");
}

global string GetWorkgroupOrRealm() {
    string workgroup = SambaConfig::GlobalGetStr("workgroup", "");
    if (toupper (SambaConfig::GlobalGetStr("security","")) == "ADS")
    {
	return SambaConfig::GlobalGetStr("realm", workgroup);
    }
    return workgroup;
}


/**
 * Get a winbind status
 *
 * @return booleand	a winbind status
 */
global define boolean GetWinbind() ``{
    return winbind_enabled;
}

/**
 * Return required packages for auto-installation
 * @return map of packages to be installed and to be removed
 */
global define map AutoPackages() ``{
    list<string> to_install = ["samba-client", "samba-winbind", "pam_mount"];
    if (SambaAD::ADS () != "")
	to_install = (list<string>) union (to_install, ["krb5", "krb5-client"]);
    return $[
	"install"	: to_install,
	"remove"	: []
    ];
}

/**
 * update the information if FAM should be started
 * @return current fam status
 */
global define boolean SetStartFAM (boolean fam) {

    if (fam != start_fam)
    {
	start_fam	= fam;
	modified	= true;
    }
    return start_fam;
}

/* EOF */
}

ACC SHELL 2018