summaryrefslogtreecommitdiffstats
path: root/scripts/identify-md5.pl
blob: f6680fdc16ed5133014b8e5c5c8a0d4976b0ae26 (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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
use Irssi;
use Digest::MD5 qw(md5_hex);
use strict;
use vars qw($VERSION %IRSSI @identify @reop);

$VERSION = '1.05';
%IRSSI = (
    authors 	=> 'Eric Jansen',
    contact 	=> 'chaos@sorcery.net',
    name 	=> 'identify-md5',
    description => 'MD5 NickServ identification script for SorceryNet',
    license 	=> 'GPL',
    modules	=> 'Digest::MD5',
    url		=> 'http://xyrion.org/irssi/',
    changed 	=> 'Sat Mar  1 13:32:30 CET 2003'
);

################################################################################
#
#  MD5 NickServ identification script for SorceryNet (irc.sorcery.net)
#
#  The script will do several things:
#  - It adds the command /identify-md5 to Irssi, which can be used to identify
#    to your current nickname or a list of nicknames given as arguments using 
#    the passwords provided below
#  - It will automatically issue this command whenever NickServ notices you 
#    that you need to identify (e.g. after a services outage)
#  - It will remember any channels ChanServ deopped you in and try to regain 
#    ops after authentication is accepted by NickServ
#
#  For more information on SorceryNets MD5 identification see:
#  http://www.sorcery.net/help/howto/MD5_identify
#
#  Put your nicknames and MD5-hashed passwords here:
#

my %nicknames = (
    lc('nick1')		=> md5_hex('password1'), 		# Plain text password 'password1'
    lc('nick2')		=> '6cb75f652a9b52798eb6cf2201057c73',	# MD5-hash of password 'password2'
    lc('nick3')		=> md5_hex('password3')
);

#
#  Please note: This file should NOT be world-readable. Although it's (quite) 
#               impossible to get the original passwords from the hashes, a
#               malicious person can identify using the hash and then change
#               your password without knowing the old password.
#
################################################################################

sub cmd_identify {

    my ($data, $server, $witem) = @_;

    # Are we connected?
    if(!$server || !$server->{'connected'}) {

	Irssi::print("Not connected to a server.");
	return;
    }

    # Did the user specify what nick(s) to identify to?
    if($data ne '') {

	# Store the list of nicknames to identify to then
	@identify = split /\s+/, $data;
    }
    else {

	# Or put our current nick on the list
	push @identify, $server->{'nick'};
    }

    # Start with some checks
    for(my $i = $#identify; $i >= 0; $i--) {

	# If we don't know the password
	if(!defined $nicknames{lc $identify[$i]}) {

	    # Send an error
	    Irssi::print("I do not know the password for ${identify[$i]}. Please add it to identify-md5.pl.");

	    # And remove the nick from the list
	    splice @identify, $i, 1;
	}
    }

    # Let's ask NickServ for a cookie if there are nicks left
    $server->command("QUOTE NickServ identify-md5") if $#identify >= 0;
}

sub event_notice {

    my ($server, $text, $nick, $address) = @_;

    # Just ignore it if we are not on SorceryNet
    return unless $server->{'real_address'} =~ /\.sorcery\.net$/;

    # Is it a notice from NickServ?
    if($nick eq 'NickServ') {

	# Is it a cookie and do we need one?
	if($text =~ /^205 S\/MD5 1\.0 (.+)$/ && $#identify >= 0) {

	    my $cookie = $1;

	    my $nickname = lc shift @identify;
	    my $password = $nicknames{$nickname};

	    # Create the hash and send it
	    my $hash = md5_hex("$nickname:$cookie:$password");
	    $server->command("QUOTE NickServ identify-md5 $nickname $hash");

	    # Suppress the notice from NickServ
	    Irssi::signal_stop();

	    # And get a new cookie if there are still nicks left to identify to
	    $server->command("QUOTE NickServ identify-md5") if $#identify >= 0;
	}

	# Is it a response?
	elsif($text =~ /^\d{3} \- (.+)$/) {

	    my $response = $1;

	    # Just print the text-part and suppress the notice
	    Irssi::print($response);

	    if($response eq 'Authentication accepted -- you are now identified.') {

		foreach my $channel (@reop) {
		    $server->command("QUOTE ChanServ $channel op $server->{nick}");
		}
		undef @reop;
	    }

	    Irssi::signal_stop();
	}

	# Do we know the password? Let's see what NickServ has to tell us then
	elsif(defined $nicknames{lc $server->{'nick'}}) {
	
	    # Identify when NickServ asks us to
	    if($text =~ /^This nick belongs to another user\./) {

		$server->command("identify-md5");
		Irssi::signal_stop();
	    }

	    # Just ignore this notice, we already identify when receiving the other one
	    elsif($text eq 'If this is your nick please try: /msg NickServ ID password') {

		Irssi::signal_stop();
	    }
	}
    }

    # If it's ChanServ saying it just deopped us, remember the channel so we can reop
    elsif($nick eq 'ChanServ' && $text =~ /^You are not allowed ops in ([^\s]+)$/) {

	push @reop, $1;

	Irssi::signal_stop();
    }
}

Irssi::command_bind('identify-md5', 'cmd_identify');
Irssi::signal_add('message irc notice', 'event_notice');