2 # Functions for manipulating the PAM services file(s)
4 BEGIN { push(@INC, ".."); };
9 # Returns a list of services and their modules
13 local @ignore = split(/\s+/, $config{'ignore'});
14 opendir(DIR, &translate_filename($config{'pam_dir'}));
15 FILE: foreach $f (readdir(DIR)) {
16 next if ($f =~ /^\./);
17 foreach $i (@ignore) {
18 next FILE if ($f =~ /^$i$/i);
20 local $serv = { 'name' => $f,
21 'file' => "$config{'pam_dir'}/$f",
22 'index' => scalar(@rv) };
24 &open_tempfile(FILE, $serv->{'file'});
27 if (/^\s*#+\s*description:\s*([A-Za-z].*)/i &&
32 if (/^\s*\@include\s+(\S+)/) {
33 # Special include line
34 local $mod = { 'include' => $1,
36 'index' => @{$serv->{'mods'}}+0 };
37 push(@{$serv->{'mods'}}, $mod);
39 elsif (/^\s*(\S+)\s+\[([^\]]*)\]\s+(\S+)\s*(.*)$/) {
40 # Line with special rules .. ignore for now
42 elsif (/^\s*(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/) {
44 local $mod = { 'type' => $1, 'control' => $2,
45 'module' => $3, 'args' => $4,
47 'index' => @{$serv->{'mods'}}+0 };
48 push(@{$serv->{'mods'}}, $mod);
52 &close_tempfile(FILE);
59 # create_module(service, &module)
60 # Add a PAM module to some service
63 local $lref = &read_file_lines("$config{'pam_dir'}/$_[0]");
64 push(@$lref, &module_line($_[1]));
68 # modify_module(service, &module)
69 # Update a PAM module in some service
72 local $lref = &read_file_lines("$config{'pam_dir'}/$_[0]");
73 splice(@$lref, $_[1]->{'line'}, 1, &module_line($_[1]));
77 # delete_module(service, &module)
78 # Delete a PAM module from some service
81 local $lref = &read_file_lines("$config{'pam_dir'}/$_[0]");
82 splice(@$lref, $_[1]->{'line'}, 1);
86 # swap_modules(service, &module1, &module2)
87 # Swap two PAM module entries in a service
90 local $lref = &read_file_lines("$config{'pam_dir'}/$_[0]");
91 local $line = $lref->[$_[1]->{'line'}];
92 $lref->[$_[1]->{'line'}] = $lref->[$_[2]->{'line'}];
93 $lref->[$_[2]->{'line'}] = $line;
97 # module_line(&module)
98 # Returns text for a PAM module line
101 if ($_[0]->{'include'}) {
102 # Special include line
103 return "\@include ".$_[0]->{'include'};
107 local $l = join("\t", $_[0]->{'type'}, $_[0]->{'control'},
109 $l .= "\t$_[0]->{'args'}" if ($_[0]->{'args'});
115 # Returns a list of all PAM shared libraries
118 local (@rv, %done, %hasmod);
119 foreach $d (split(/\s+/, $config{'lib_dirs'})) {
120 opendir(DIR, &translate_filename($d));
121 foreach $f (readdir(DIR)) {
122 local @st = stat(&translate_filename("$d/$f"));
123 push(@rv, $f) if (!$done{$st[1]}++ && $f =~ /^pam_.*\.so$/);
124 $hasmod{$f}++ if ($f =~ /^pam_.*\.so$/);
128 foreach $q (split(/\s+/, $config{'mod_equiv'})) {
129 local ($q1, $q2) = split(/=/, $q);
131 @rv = grep { $_ ne $q1 } @rv;
137 # include_style(&pam)
138 # Returns 1 if includes are done with pam_stack.so, 2 if done with include
139 # lines, 3 if done with @include, 0 if not supported
143 local @allmods = map { @{$_->{'mods'}} } @$pam;
144 local ($atinc) = grep { $_->{'include'} } @allmods;
145 local ($inc) = grep { $_->{'control'} eq 'include' } @allmods;
146 local ($stack) = grep { $_ eq "pam_stack.so" } &list_modules();
147 return $atinc ? 3 : $inc ? 2 : $stack ? 1 : 0;