|
Line 0
Link Here
|
|
|
1 |
/* Copyright (C) 2011 Frederic Crozat |
| 2 |
Author: Frederic Crozat <fcrozat@suse.com> |
| 3 |
|
| 4 |
This program is free software; you can redistribute it and/or modify |
| 5 |
it under the terms of the GNU General Public License version 2 as |
| 6 |
published by the Free Software Foundation. |
| 7 |
|
| 8 |
This program is distributed in the hope that it will be useful, |
| 9 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 10 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 11 |
GNU General Public License for more details. |
| 12 |
|
| 13 |
You should have received a copy of the GNU General Public License |
| 14 |
along with this program; if not, write to the Free Software Foundation, |
| 15 |
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
| 16 |
|
| 17 |
#ifdef HAVE_CONFIG_H |
| 18 |
#include <config.h> |
| 19 |
#endif |
| 20 |
|
| 21 |
#include <stdio.h> |
| 22 |
#include <string.h> |
| 23 |
#include <ctype.h> |
| 24 |
#include <dirent.h> |
| 25 |
#include <stdlib.h> |
| 26 |
|
| 27 |
#include "pam-config.h" |
| 28 |
#include "pam-module.h" |
| 29 |
|
| 30 |
extern char *confdir; |
| 31 |
|
| 32 |
static int |
| 33 |
session_pred_systemd (config_content_t *cfg_content) |
| 34 |
{ |
| 35 |
int do_insert = FALSE; |
| 36 |
/* insert if current line does not already contain this module */ |
| 37 |
do_insert = strcasestr (cfg_content->line, "pam_systemd.so") == NULL; |
| 38 |
/* and this line starts with 'session' */ |
| 39 |
do_insert &= strcasestr (cfg_content->line, "session") != NULL; |
| 40 |
|
| 41 |
/* and there is no next line, or the next line is something |
| 42 |
* different than session */ |
| 43 |
do_insert &= ( cfg_content->next == NULL || |
| 44 |
strcasestr (cfg_content->line, "pam_loginuid") == NULL); |
| 45 |
|
| 46 |
return do_insert; |
| 47 |
} |
| 48 |
|
| 49 |
/* |
| 50 |
* This implementation follows a different approach than the other |
| 51 |
* single service modules (lastlog, loginuid and mount): |
| 52 |
* |
| 53 |
* Rather than operating on the file directly, the config/service |
| 54 |
* file is parsed in first into *cfg_content. |
| 55 |
* |
| 56 |
* Then depending on the cmd line switch (-a/d), it operates on the |
| 57 |
* linked list instead, using insert_if() and remove_module(). |
| 58 |
* |
| 59 |
* I chose this solution because this way there is more flexibility |
| 60 |
* where to insert the module. |
| 61 |
* |
| 62 |
* You can specify the insertion point by writing a custom predicate |
| 63 |
* (see session_pred_systemd for examples). |
| 64 |
*/ |
| 65 |
|
| 66 |
static int |
| 67 |
write_config_systemd (pam_module_t *this, enum write_type op __attribute__((unused)), FILE *unused __attribute__((unused))) |
| 68 |
{ |
| 69 |
option_set_t *opt_set = this->get_opt_set (this, SESSION); |
| 70 |
int status = TRUE; |
| 71 |
config_content_t *cfg_content; |
| 72 |
int writeit = opt_set->is_enabled (opt_set, "is_enabled"); |
| 73 |
char *line; |
| 74 |
char *opt_create_session, *opt_kill_session, *opt_kill_user; |
| 75 |
char *opt_kill_only_users, *opt_kill_exclude_users, *opt_controllers, *opt_reset_controllers; |
| 76 |
char *opt; |
| 77 |
|
| 78 |
if (debug) |
| 79 |
debug_write_call (this, SESSION); |
| 80 |
|
| 81 |
load_single_config (gl_service, &cfg_content); |
| 82 |
|
| 83 |
/* remove every occurrence of pam_systemd.so from the service |
| 84 |
* file |
| 85 |
*/ |
| 86 |
remove_module (&cfg_content, "pam_systemd.so"); |
| 87 |
if (writeit) |
| 88 |
{ |
| 89 |
if (!is_module_enabled (service_module_list, "pam_loginuid.so", SESSION)) { |
| 90 |
fprintf (stderr, _("ERROR: pam_loginuid.so is not enabled for service '%s', but needed by pam_systemd.so\n"), gl_service); |
| 91 |
return 1; |
| 92 |
} |
| 93 |
|
| 94 |
if ((opt = opt_set->get_opt (opt_set, "create_session"))) |
| 95 |
{ |
| 96 |
if (asprintf(&opt_create_session, " create-session=%s",opt) == -1) |
| 97 |
return 1; |
| 98 |
} |
| 99 |
else |
| 100 |
opt_create_session = NULL; |
| 101 |
if ((opt = opt_set->get_opt (opt_set, "kill_session"))) |
| 102 |
{ |
| 103 |
if (asprintf(&opt_kill_session, " kill-session=%s",opt) == -1) |
| 104 |
return 1; |
| 105 |
} |
| 106 |
else |
| 107 |
opt_kill_session = NULL; |
| 108 |
if ((opt = opt_set->get_opt (opt_set, "kill_user"))) |
| 109 |
{ |
| 110 |
if (asprintf(&opt_kill_user, " kill-user=%s",opt) == -1) |
| 111 |
return 1; |
| 112 |
} |
| 113 |
else |
| 114 |
opt_kill_user = NULL; |
| 115 |
if ((opt = opt_set->get_opt (opt_set, "kill_only_users"))) |
| 116 |
{ |
| 117 |
if (asprintf(&opt_kill_only_users, " kill-only-users=%s",opt) == -1) |
| 118 |
return 1; |
| 119 |
} |
| 120 |
else |
| 121 |
opt_kill_only_users = NULL; |
| 122 |
if ((opt = opt_set->get_opt (opt_set, "kill_exclude_users"))) |
| 123 |
{ |
| 124 |
if (asprintf(&opt_kill_exclude_users, " kill-exclude-users=%s",opt) == -1) |
| 125 |
return 1; |
| 126 |
} |
| 127 |
else |
| 128 |
opt_kill_exclude_users = NULL; |
| 129 |
if ((opt = opt_set->get_opt (opt_set, "controllers"))) |
| 130 |
{ |
| 131 |
if (asprintf(&opt_controllers, " controllers=%s",opt) == -1) |
| 132 |
return 1; |
| 133 |
} |
| 134 |
else |
| 135 |
opt_controllers = NULL; |
| 136 |
if ((opt = opt_set->get_opt (opt_set, "reset_controllers"))) |
| 137 |
{ |
| 138 |
if (asprintf(&opt_reset_controllers, " reset-controllers=%s",opt) == -1) |
| 139 |
return 1; |
| 140 |
} |
| 141 |
else |
| 142 |
opt_reset_controllers = NULL; |
| 143 |
if (asprintf (&line, "session\t optional\tpam_systemd.so%s %s %s %s %s %s %s\n", |
| 144 |
opt_create_session ? opt_create_session : "", |
| 145 |
opt_kill_session ? opt_kill_session : "", |
| 146 |
opt_kill_user ? opt_kill_user : "", |
| 147 |
opt_kill_only_users ? opt_kill_only_users : "", |
| 148 |
opt_kill_exclude_users ? opt_kill_exclude_users : "", |
| 149 |
opt_controllers ? opt_controllers : "", |
| 150 |
opt_reset_controllers ? opt_reset_controllers : "") == -1) |
| 151 |
return 1; |
| 152 |
/* insert pam_systemd.so as the last module in the session |
| 153 |
* stack |
| 154 |
*/ |
| 155 |
status &= insert_if (&cfg_content, line , &session_pred_systemd, AFTER); |
| 156 |
free (line); |
| 157 |
} |
| 158 |
if (!status) |
| 159 |
{ |
| 160 |
fprintf (stderr, _("ERROR: Could not add pam_systemd.so to service '%s'"), gl_service); |
| 161 |
return 1; |
| 162 |
} |
| 163 |
|
| 164 |
return write_single_config (gl_service, &cfg_content); |
| 165 |
} |
| 166 |
|
| 167 |
|
| 168 |
static int |
| 169 |
parse_config_systemd (pam_module_t *this, char *args, write_type_t type) |
| 170 |
{ |
| 171 |
option_set_t *opt_set = this->get_opt_set (this, type); |
| 172 |
|
| 173 |
if (debug) |
| 174 |
printf ("**** parse_config_%s (%s): '%s'\n", this->name, |
| 175 |
type2string (type), args ? args : ""); |
| 176 |
|
| 177 |
opt_set->enable (opt_set, "is_enabled", TRUE); |
| 178 |
|
| 179 |
while (args && strlen (args) > 0) |
| 180 |
{ |
| 181 |
char *cp = strsep (&args, " \t"); |
| 182 |
|
| 183 |
if (args) |
| 184 |
while (isspace ((int) *args)) |
| 185 |
++args; |
| 186 |
|
| 187 |
if (strncmp (cp, "create-session=", 15) == 0) |
| 188 |
opt_set->set_opt (opt_set, "create_session", strdup(&cp[15])); |
| 189 |
else if (strncmp (cp, "kill-session=", 13) == 0) |
| 190 |
opt_set->set_opt (opt_set, "kill_session", strdup(&cp[13])); |
| 191 |
else if (strncmp (cp, "kill-user=", 10) == 0) |
| 192 |
opt_set->set_opt (opt_set, "kill_user", strdup(&cp[10])); |
| 193 |
else if (strncmp (cp, "kill-only-users=", 16) == 0) |
| 194 |
opt_set->set_opt (opt_set, "kill_only_users", strdup (&cp[16])); |
| 195 |
else if (strncmp (cp, "kill-exclude-users=", 19) == 0) |
| 196 |
opt_set->set_opt (opt_set, "kill_exclude_users", strdup (&cp[19])); |
| 197 |
else if (strncmp (cp, "controllers=", 12) == 0) |
| 198 |
opt_set->set_opt (opt_set, "controllers", strdup (&cp[12])); |
| 199 |
else if (strncmp (cp, "reset-controllers=", 18) == 0) |
| 200 |
opt_set->set_opt (opt_set, "reset_controllers", strdup (&cp[18])); |
| 201 |
else |
| 202 |
print_unknown_option_error ("pam_systemd.so", cp); |
| 203 |
} |
| 204 |
return 1; |
| 205 |
} |
| 206 |
|
| 207 |
GETOPT_START_1(SESSION) |
| 208 |
GETOPT_END_1(SESSION) |
| 209 |
|
| 210 |
PRINT_ARGS("systemd") |
| 211 |
PRINT_XMLHELP("systemd") |
| 212 |
|
| 213 |
/* ---- contruct module object ---- */ |
| 214 |
DECLARE_BOOL_OPTS_1 (is_enabled); |
| 215 |
DECLARE_STRING_OPTS_7 (create_session, kill_session, kill_user, kill_only_users, kill_exclude_users, controllers, reset_controllers); |
| 216 |
DECLARE_OPT_SETS; |
| 217 |
|
| 218 |
static module_helptext_t helptext[] = {{NULL, NULL, NULL}}; |
| 219 |
|
| 220 |
|
| 221 |
/* at last construct the complete module object */ |
| 222 |
pam_module_t mod_pam_systemd = { "pam_systemd.so", opt_sets, helptext, |
| 223 |
&parse_config_systemd, |
| 224 |
&def_print_module, |
| 225 |
&write_config_systemd, |
| 226 |
&get_opt_set, |
| 227 |
&getopt, |
| 228 |
&print_args, |
| 229 |
&print_xmlhelp}; |