/* PureAdmin * Copyright (C) 2003 Isak Savo * * 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 2 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. */ /* * Configuration backend. * * Copyright (C) 2003-2006 Isak Savo */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include "globals.h" #include "helper.h" #include "cfg.h" /* Global configuration structure */ cfg_t cfg; /* cfg_write_settings: Writes the configuration to disk (~/.pureadminrc). * * Returns: TRUE if everything was saved. * FALSE if something went wrong. (i.e. file couldn't be opened) */ gboolean cfg_write_settings (void) { FILE *f; gchar filename[FILEPATH_MAX]; g_snprintf (filename, FILEPATH_MAX, "%s/" RCFILE, g_get_home_dir ()); if (!(f = fopen (filename, "w"))) { perror ("Unable to open config-file for writing"); return FALSE; } fputs ("# -*- sh -*-\n" "# ~/.pureadminrc - Configuration file for pureadmin\n" "# All variables are in the form VARNAME=VALUE where VALUE should be an UN-quoted string\n" "# Comment lines BEGINS with a '#'. Otherwise the # is considered a part of the value/variablename\n\n", f); fputs ("# Default UID and GID to assign to new virtual users. These should point to an un-priveliged system account.\n", f); if (cfg.default_uid > 0) fprintf (f, "defaultuid=%d\n", cfg.default_uid); if (cfg.default_gid > 0) fprintf (f, "defaultgid=%d\n\n", cfg.default_gid); if (cfg.default_home) { fputs ("# Default home is the directory which will be assigned to new users by default.\n", f); fprintf (f, "defaulthome=%s\n\n", cfg.default_home); } if (cfg.cmd_purepw) { fputs ("# Name and optional full path to the pure-pw command. Path is only needed if it is not installed in a standard location (i.e. Not in $PATH)\n", f); fprintf (f, "cmd_purepw=%s\n\n", cfg.cmd_purepw); } fputs ("# Name and location of the password files where pureftpd reads user-information. The pdb-file is a binary database file,\n", f); if (cfg.pwfile) fprintf (f, "pwfile=%s\n", cfg.pwfile); if (cfg.pdbfile) fprintf (f, "pdbfile=%s\n\n", cfg.pdbfile); if (cfg.logfile) { fputs ("# Location of the logfile where pureftpd writes logging info\n", f); fprintf (f, "logfile=%s\n\n", cfg.logfile); } fputs ("# Logging method, 0 means syslog and 1 means custom logfile\n", f); fprintf (f, "logmethod=%d\n", cfg.logmethod); fputs ("# If this is enabled, then DNS name lookups will be performed resulting in IP-addresses being\n" "# converted to human readable names\n" "# Setting this to 0 will make PureAdmin seem faster and more responsive.\n", f); fprintf (f, "resolve_hostnames=%d\n\n", cfg.resolve_hostnames); fputs ("# Indicates wether the first-time user-dialog messagebox have been seen by the user\n", f); fprintf (f, "seen_usrdlg_welcome=%d\n\n", cfg.seen_usrdlg_welcome); fputs ("# Indicates wether the FAM Error dialog should be shown or not\n", f); fprintf (f, "show_fam_errmsg=%d\n\n", cfg.show_fam_errmsg); fputs ("# Should we display an icon in the system tray upon events?\n", f); fprintf (f, "use_tray_icon=%d\n\n", cfg.use_tray_icon); fputs ("# Character set to use for usernames\n", f); fprintf (f, "username_encoding=%s\n", cfg.uname_encoding); fprintf (f, "use_system_encoding=%d\n\n", cfg.use_system_encoding); fputs ("# True if window size and position should be restored\n", f); fprintf (f, "save_window_geometry=%d\n\n", cfg.save_window_geometry); fputs ("# The window size and position in x:y pairs\n", f); fprintf (f, "window_size=%d:%d\n", cfg.win_size[0], cfg.win_size[1]); fprintf (f, "window_pos=%d:%d\n", cfg.win_pos[0], cfg.win_pos[1]); fprintf (f, "divider_pos=%d\n", cfg.div_pos); fprintf (f, "show_advinfo=%d\n", cfg.show_advinfo); fclose (f); return TRUE; } /* cfg_read_settings: Reads the settings from user configuration file (~/.pureadminrc) * * Returns: TRUE if all went well * FALSE if something went wrong. (i.e. file couldn't be opened) */ gboolean cfg_read_settings (void) { FILE *f; gchar filename[FILEPATH_MAX]; gchar buf[LINE_MAX], **arr; g_snprintf (filename, FILEPATH_MAX, "%s/" RCFILE, g_get_home_dir ()); if (!(f = fopen (filename, "r"))) { pur_log_wrn ("Unable to open config-file for reading: %s", strerror (errno)); pur_log_nfo ("Using default configuration\n"); return FALSE; } while (fgets (buf, LINE_MAX, f)) { g_strstrip (buf); if (*buf == '#' || *buf == '\0') continue; arr = g_strsplit (buf, "=", 2); if (!arr || !arr[0] || !arr[1]) continue; g_strstrip (arr[0]); g_strstrip (arr[1]); gchar *key = arr[0]; gchar *val = arr[1]; if (*val == '\0') /* Ignore values that is empty (i.e. "") */ continue; if (strncmp (key, "defaultuid", 10) == 0) cfg.default_uid = atoi (val); else if (strncmp (key, "defaultgid", 10) == 0) cfg.default_gid = atoi (val); else if (strncmp (key, "defaulthome", 11) == 0) { if (g_path_is_absolute(val)) { g_free (cfg.default_home); cfg.default_home = g_strdup (val); } } else if (strncmp (key, "cmd_purepw", 10) == 0) { if ((g_path_is_absolute(val) && g_file_test(val, G_FILE_TEST_EXISTS)) || g_find_program_in_path(val)) { g_free (cfg.cmd_purepw); cfg.cmd_purepw = g_strdup (val); } } else if (strncmp (key, "pwfile", 6) == 0) { if (g_path_is_absolute(val)) { g_free (cfg.pwfile); cfg.pwfile = g_strdup (val); } } else if (strncmp (key, "pdbfile", 7) == 0) { if (g_path_is_absolute(val)) { g_free (cfg.pdbfile); cfg.pdbfile = g_strdup (val); } } else if (strncmp (key, "logfile", 7) == 0) { if (g_path_is_absolute(val)) { g_free (cfg.logfile); cfg.logfile = g_strdup (val); } } else if (strncmp (key, "logmethod", 9) == 0) { cfg.logmethod = atoi (val); if (cfg.logmethod < 0 || cfg.logmethod >= NUM_LOGMETHODS) cfg.logmethod = 0; } else if (strncmp (key, "window_size", 11) == 0) sscanf (val,"%d:%d",&(cfg.win_size[0]), &(cfg.win_size[1])); else if (strncmp (key, "window_pos", 10) == 0) sscanf (val,"%d:%d",&(cfg.win_pos[0]), &(cfg.win_pos[1])); else if (strncmp (key, "divider_pos", 11) == 0) cfg.div_pos = atoi (val); else if (strncmp (key, "save_window_geometry", 20) == 0) cfg.save_window_geometry = atoi (val); else if (strncmp (key, "show_advinfo", 12) == 0) cfg.show_advinfo = atoi (val); else if (strncmp (key, "resolve_hostnames", 17) == 0) cfg.resolve_hostnames = atoi (val); else if (strncmp (key, "seen_usrdlg_welcome", 19) == 0) cfg.seen_usrdlg_welcome = atoi (val); else if (strncmp (key, "show_fam_errmsg", 15) == 0) cfg.show_fam_errmsg = atoi (val); else if (strncmp (key, "use_tray_icon", 13) == 0) cfg.use_tray_icon = atoi (val); else if (strncmp (key, "username_encoding", 17) == 0) { g_free (cfg.uname_encoding); cfg.uname_encoding = g_strdup (val); } else if (strncmp (key, "use_system_encoding", 19) == 0) cfg.use_system_encoding = atoi (val); g_strfreev (arr); } fclose (f); return TRUE; } void cfg_terminate (void) { g_free (cfg.default_home); g_free (cfg.cmd_purepw); g_free (cfg.cmd_ftpwho); g_free (cfg.cmd_startstop); g_free (cfg.cmd_useradd); g_free (cfg.cmd_groupadd); g_free (cfg.pwfile); g_free (cfg.pdbfile); g_free (cfg.logfile); g_free (cfg.uname_encoding); } gchar *cfg_find_default_home (void) { if (g_file_test ("/home/ftpuser", G_FILE_TEST_IS_DIR)) return g_strdup ("/home/ftpuser"); else if (g_file_test ("/home/ftpusers", G_FILE_TEST_IS_DIR)) return g_strdup ("/home/ftpusers"); else if (g_file_test ("/home/ftp", G_FILE_TEST_IS_DIR)) return g_strdup ("/home/ftp"); return g_strdup ("/home/ftpusers"); } gchar *cfg_find_pwfile (void) { if (g_file_test (g_getenv ("PURE_PASSWDFILE"), G_FILE_TEST_IS_REGULAR)) return g_strdup (g_getenv ("PURE_PASSWDFILE")); else if (g_file_test ("/etc/pureftpd.passwd", G_FILE_TEST_IS_REGULAR)) return g_strdup ("/etc/pureftpd.passwd"); else if (g_file_test ("/etc/pure-ftpd/pureftpd.passwd", G_FILE_TEST_IS_REGULAR)) return g_strdup ("/etc/pure-ftpd/pureftpd.passwd"); return NULL; } gchar *cfg_find_pdbfile (void) { if (g_file_test (g_getenv ("PURE_DBFILE"), G_FILE_TEST_IS_REGULAR)) return g_strdup (g_getenv ("PURE_DBFILE")); else if (g_file_test ("/etc/pureftpd.pdb", G_FILE_TEST_IS_REGULAR)) return g_strdup ("/etc/pureftpd.pdb"); else if (g_file_test ("/etc/pure-ftpd/pureftpd.pdb", G_FILE_TEST_IS_REGULAR)) return g_strdup ("/etc/pure-ftpd/pureftpd.pdb"); /* No existing, default to the same as pwfile but with pdb-extension */ if (cfg.pwfile) { gchar *s, *tmp ; s = g_strdup (cfg.pwfile); tmp = strrchr(s, '.'); if (tmp) *tmp = '\0'; tmp = g_strconcat (s, ".pdb", NULL); g_free (s); return tmp; } /* We've done all we can, return NULL */ return NULL; } guint cfg_find_ftpuser_uid (void) { gchar *s, **arr; guint rv = 0; arr = NULL; s = misc_get_line_beginning_with ("/etc/passwd", "ftpuser"); if (!s) return 0; arr = g_strsplit (s, ":", 0); if (arr_count (arr) > 2) rv = atoi (arr[2]); g_strfreev (arr); g_free (s); return rv; } guint cfg_find_ftpgroup_gid (void) { gchar *s, **arr; guint rv = 0; arr = NULL; s = misc_get_line_beginning_with ("/etc/group", "ftpgroup"); if (!s) return 0; arr = g_strsplit (s, ":", 0); if (arr_count (arr) > 2) rv = atoi (arr[2]); g_strfreev (arr); g_free (s); return rv; } gchar *cfg_get_pftp_config_dir (void) { gchar *dir = NULL; if (cfg.pwfile) dir = g_path_get_dirname (cfg.pwfile); else if (cfg.pdbfile) dir = g_path_get_dirname (cfg.pdbfile); else if (g_file_test("/etc/pure-ftpd", G_FILE_TEST_IS_DIR)) dir = g_strdup ("/etc/pure-ftpd"); else dir = g_strdup ("/etc"); return dir; } /* Gets the default password file for pureftpd, regardless of whether it exists or not */ gchar *cfg_get_pftp_default_pwfile (void) { if (g_getenv ("PURE_PASSWDFILE") && g_path_is_absolute(g_getenv("PURE_PASSWDFILE"))) return g_strdup (g_getenv ("PURE_PASSWDFILE")); gchar *dir = cfg_get_pftp_config_dir(); gchar *f = g_build_filename(dir, "pureftpd.passwd", NULL); g_free(dir); return f; } /* Gets the default dbfile for pureftpd, regardless of whether it exists or not */ gchar *cfg_get_pftp_default_pdbfile (void) { if (g_getenv ("PURE_DBFILE") && g_path_is_absolute(g_getenv("PURE_DBFILE"))) return g_strdup (g_getenv ("PURE_DBFILE")); gchar *dir = cfg_get_pftp_config_dir(); gchar *f = g_build_filename(dir, "pureftpd.pdb", NULL); g_free(dir); return f; } /* cfg_fill_missing: Tries to find sane defaults for values that there are no * configured setting for. This is mostly done by probing the * file system for the relevant files. */ void cfg_fill_missing (void) { if (!cfg.cmd_purepw) cfg.cmd_purepw = g_find_program_in_path ("pure-pw"); if (!cfg.cmd_ftpwho) cfg.cmd_ftpwho = g_find_program_in_path ("pure-ftpwho"); if (!cfg.cmd_startstop) { gchar prg_arr[][20] = { "rc.pure-ftpd", "rc.pureftpd", "pure-ftpd", "pure-ftpd-mysql"}; for (gint i = 0; i < G_N_ELEMENTS(prg_arr); i++) { gchar *s = prg_arr[i]; cfg.cmd_startstop = misc_find_prog_in_dirs (s, "/etc/rc.d /etc/rc.d/init.d /etc/init.d /usr/local/etc/rc.d"); if (cfg.cmd_startstop) break; } } if (!cfg.pwfile) { gchar *base = cfg_get_pftp_config_dir(); cfg.pwfile = g_build_filename (base, "pureftpd.passwd", NULL); g_free (base); } if (!cfg.pdbfile) { gchar *base = cfg_get_pftp_config_dir(); cfg.pdbfile = g_build_filename (base, "pureftpd.pdb", NULL); g_free (base); } if (!cfg.default_home) cfg.default_home = cfg_find_default_home (); if (!cfg.pwfile) cfg.pwfile = cfg_find_pwfile (); if (!cfg.pdbfile) cfg.pdbfile = cfg_find_pdbfile (); /* Find User ID of ftpuser */ if (!cfg.default_uid) cfg.default_uid = cfg_find_ftpuser_uid (); /* Find Group ID of ftpgroup */ if (!cfg.default_gid) cfg.default_gid = cfg_find_ftpgroup_gid (); if (!cfg.cmd_useradd) cfg.cmd_useradd = g_find_program_in_path ("useradd"); if (!cfg.cmd_groupadd) cfg.cmd_groupadd = g_find_program_in_path ("groupadd"); } /* cfg_set_defaults: Sets default values to the configuration struct. * This should only be called ONCE and before any * attempt to access or modify the cfg struct! * * Note: this function has no logic to make wise * decisions. See the cfg_fill_missing for that! */ void cfg_set_defaults (void) { memset (&cfg, 0, sizeof (cfg_t)); cfg.logfile = g_strdup ("/var/log/messages"); cfg.use_system_encoding = TRUE; cfg.uname_encoding = g_strdup ("UTF-8"); cfg.logmethod = LOG_SYSLOG; cfg.show_fam_errmsg = TRUE; }