/**
 * File:	modules/PamSettings.ycp
 * Package:	yast2-pam
 * Summary:	YaST intrerface for security agent (/etc/security/*.conf)
 *		and /etc/default/passwd agent
 * Authors:	Jiri Suchomel <jsuchome@suse.cz>
 *
 * $Id: PamSettings.ycp 18675 2004-08-18 10:51:15Z jsuchome $
 *
 */

{

module "PamSettings";

/**
 * Was /etc/default/passwd modified?
 */
boolean default_passwd_modified	= false;

/**
 * Was anything under /etc/security/ modified?
 */
boolean security_modified	= false;

list<string> security_files = [];

//---------------------------- functions for handling /etc/security/*.conf

/**
 * Returns list of files currently handled by the module
 * @return list
 */
global define list<string> GetFiles () ``{

    if (security_files == [])
	security_files = (list<string>) SCR::Dir (.etc.security.section);
    if (security_files == nil)
	security_files = [];
    return security_files;
}

/**
 * Form absolute path name.
 * @param file name (or unambiguous substring, like "unix2" or "pwcheck")
 * @return path to file
 */
define string Filename (string name) ``{

    string ret = name;
    foreach (string file, GetFiles (), ``{
	if (issubstring (file, name))
	    ret = file;
    });
    return ret;
}

/**
 * Returns the values (options) of one type in the given file
 * @param file file name
 * @param type type of management group (these are used for authentication,
 *  account management and password management)
 * @return list of options
 * @example
 * GetValues ("pwcheck", "password") returns [ "nullok", "cracklib" ]
 */
global define list<string> GetValues (string file, string type) ``{

    string filename = Filename (file);
    string ret = (string) SCR::Read (add (add (.etc.security.v, filename), type));
    if(ret == nil) return [];
    return splitstring (ret, " \t");
}

/**
 * Returns the given file contents in the map form
 * @param file file name
 * @return map which maps type to list of its options
 * @example
 * GetFile ("pwcheck") returns $[ "password" : [ "nullok", "cracklib" ] ]
 */
global define map GetFile (string file) ``{

    map ret = $[];
    string filename = Filename (file);
    foreach (string type, SCR::Dir (add (.etc.security.v, filename)), ``{
	ret [type] = GetValues (filename, type);
    });
    return ret;
}

/**
 * Saves the new list of options of one type to given file
 * @param file file name
 * @param type type of management group
 * @return success
 * @example
 * SetValues ("pwcheck", "password", [ "cracklib", "md5" ])
 */
global define boolean SetValues (string file, string type, list<string> values) ``{
    string filename	= Filename (file);
    security_modified	= true;
    return SCR::Write (add (add (.etc.security.v, filename), type),
	mergestring ((list<string>)values, " ")) == true;
}

/**
 * Adds a new options to the current list of options
 * @param file file name
 * @param type type of management group
 * @return success
 * @example
 * AddValue ("pwcheck", "password", "md5" ])
 */
global define boolean AddValue (string file, string type, string value) ``{
    list<string> values = GetValues (file, type);
    // value must be first (to avoid adding to the commented rest of line)
    return SetValues (file, type, (list<string>) union ([value], values));
}

/**
 * Deletes an options from the current list of options
 * @param file file name
 * @param type type of management group
 * @return success
 * @example
 * RemoveValue ("pwcheck", "password", "md5" ])
 */
global define boolean RemoveValue (string file, string type, string value) ``{
    list<string> values = GetValues (file, type);
    return SetValues (file, type, filter (string v, values, ``{
	// this is for options like "minlen=5" etc.
	if (!issubstring (v, "="))
	    return v != value;
	else
	    return !issubstring (v,value);
    }));
}

//---------------------------- functions for handling /etc/default/passwd

/**
 * Reads the value of default crypt hash (defined in /etc/default/passwd)
 */
global define string GetHashMethod () {
    return (string) SCR::Read (.etc.default.passwd.crypt);
}

/**
 * Reads the value of default crypt hash for group passwords
 */
global define string GetGroupHashMethod () {

    any g = SCR::Read (.etc.default.passwd.group_crypt);
    if (g != nil && is (g, string) && (string) g != "")
	return (string) g;
    else return GetHashMethod ();
}

/**
 * Reads the value from /etc/default/passwd
 */
global define string GetDefaultValue (string key) {
    return (string) SCR::Read (add (.etc.default.passwd, key));
}

/**
 * Sets the new value of default crypt hash - modifies /etc/default/passwd !
 * @param hash the new value of hash
 * @example
 * SetValues ("md5")
 */
global define boolean SetHashMethod (string hash) {
    if (GetHashMethod () != hash)
    {
	default_passwd_modified	= true;
    }
    default_passwd_modified	= true;
    return SCR::Write (.etc.default.passwd.crypt, hash);
}

/**
 * Sets the new value of default crypt hash for group passwords
 * @param hash the new value of hash
 */
global define boolean SetGroupHashMethod (string hash) {
    if (GetGroupHashMethod () != hash)
    {
	default_passwd_modified	= true;
    }
    return SCR::Write (.etc.default.passwd.group_crypt, hash);
}

/**
 * Set the value of key in /etc/default/passwd
 */
global define boolean SetDefaultValue (string key, string value) {
    if (GetDefaultValue (key) != value)
    {
	default_passwd_modified	= true;
    }
    return SCR::Write (add (.etc.default.passwd, key), value);
}



//---------------------------- common functions ------------------------------

/**
 * Writes all edited files to the disk
 * @param force - write everythink, even if modification was not detected
 * @return true on success
 */
global define boolean Write (boolean force) {

    boolean ret = true;
    if (security_modified || force)
	ret	= ret && SCR::Write (.etc.security, nil);
    if (default_passwd_modified || force)
	ret	= ret && SCR::Write (.etc.default.passwd, nil);
    return ret;
}

}//EOF
