aboutsummaryrefslogtreecommitdiff
path: root/doc/plugins/contrib/unixauth.mdwn
blob: 12f885c3342115c96c51b874f052adb0155d4c66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
[[!template id=plugin name=unixauth core=0 author="[[schmonz]]"]]
[[!tag type/auth]]

This plugin authenticates users against the Unix user database. It presents a similar UI to [[plugins/passwordauth]], but simpler, as there's no need to be able to register or change one's password.

[pwauth](http://www.unixpapa.com/pwauth/) must be installed and working. In particular, it must be configured to recognize the UID of the calling web server, or authentication will always fail. Set `pwauth_path` to the full path of your pwauth binary.

As [with passwordauth](/security/#index14h2), be wary of sending usernames and passwords in cleartext. Unlike with passwordauth, sniffing these credentials can get an attacker much further than mere wiki access. SSL with this plugin is a __must__.

[[!toggle id="code" text="unixauth.pm"]]

[[!toggleable id="code" text="""

    #!/usr/bin/perl
    # Ikiwiki unixauth authentication.
    package IkiWiki::Plugin::unixauth;
    
    use warnings;
    use strict;
    use IkiWiki 2.00;
    
    sub import { #{{{
            hook(type => "formbuilder_setup", id => "unixauth",
                call => \&formbuilder_setup);
            hook(type => "formbuilder", id => "unixauth",
                call => \&formbuilder);
        hook(type => "sessioncgi", id => "unixauth", call => \&sessioncgi);
    } # }}}
    
    # Checks if a string matches a user's password, and returns true or false.
    sub checkpassword ($$;$) { #{{{
        my $user=shift;
        my $password=shift;
        my $field=shift || "password";
    
        # It's very important that the user not be allowed to log in with
        # an empty password!
        if (! length $password) {
                return 0;
        }
    
        my $ret=0;
        if (! exists $config{pwauth_path}) {
                $config{pwauth_path}="/usr/libexec/pwauth";
        }
        open PWAUTH, "|$config{pwauth_path}" or die("Could not run pwauth");
        print PWAUTH "$user\n$password\n";
        close PWAUTH;
        $ret=!($?>>8);
    
        if ($ret) {
            my $userinfo=IkiWiki::userinfo_retrieve();
            if (! length $user || ! defined $userinfo ||
                ! exists $userinfo->{$user} || ! ref $userinfo->{$user}) {
                    IkiWiki::userinfo_setall($user, {
                        'email' => '',
                        'regdate' => time,
                    });
            }
        }
    
        return $ret;
    } #}}}
    
    sub formbuilder_setup (@) { #{{{
        my %params=@_;
    
        my $form=$params{form};
        my $session=$params{session};
        my $cgi=$params{cgi};
    
        if ($form->title eq "signin") {
                $form->field(name => "name", required => 0);
                $form->field(name => "password", type => "password", required => 0);
                
                if ($form->submitted) {
                        my $submittype=$form->submitted;
                        # Set required fields based on how form was submitted.
                        my %required=(
                                "Login" => [qw(name password)],
                        );
                        foreach my $opt (@{$required{$submittype}}) {
                                $form->field(name => $opt, required => 1);
                        }
        
                        # Validate password against name for Login.
                        if ($submittype eq "Login") {
                                $form->field(
                                        name => "password",
                                        validate => sub {
                                                checkpassword($form->field("name"), shift);
                                        },
                                );
                        }
                        
                        elsif ($submittype eq "Login") {
                                $form->field( 
                                        name => "name",
                                        validate => sub {
                                                my $name=shift;
                                                length $name &&
                                                IkiWiki::userinfo_get($name, "regdate");
                                        },
                                );
                        }
                }
                else {
                        # First time settings.
                        $form->field(name => "name");
                        if ($session->param("name")) {
                                $form->field(name => "name", value => $session->param("name"));
                        }
                }
        }
        elsif ($form->title eq "preferences") {
                $form->field(name => "name", disabled => 1, 
                        value => $session->param("name"), force => 1,
                        fieldset => "login");
                $form->field(name => "password", disabled => 1, type => "password",
                        fieldset => "login"),
        }
    }
    
    sub formbuilder (@) { #{{{
        my %params=@_;
    
        my $form=$params{form};
        my $session=$params{session};
        my $cgi=$params{cgi};
        my $buttons=$params{buttons};
    
        if ($form->title eq "signin") {
                if ($form->submitted && $form->validate) {
                        if ($form->submitted eq 'Login') {
                                $session->param("name", $form->field("name"));
                                IkiWiki::cgi_postsignin($cgi, $session);
                        }
                }
        }
        elsif ($form->title eq "preferences") {
                if ($form->submitted eq "Save Preferences" && $form->validate) {
                        my $user_name=$form->field('name');
                }
        }
    } #}}}
    
    sub sessioncgi ($$) { #{{{
        my $q=shift;
        my $session=shift;
    } #}}}
    
    1

"""]]