1use Irssi;
2use Digest::MD5 qw(md5_hex);
3use strict;
4use vars qw($VERSION %IRSSI @identify @reop);
5
6$VERSION = '1.05';
7%IRSSI = (
8    authors 	=> 'Eric Jansen',
9    contact 	=> 'chaos@sorcery.net',
10    name 	=> 'identify-md5',
11    description => 'MD5 NickServ identification script for SorceryNet',
12    license 	=> 'GPL',
13    modules	=> 'Digest::MD5',
14    url		=> 'http://xyrion.org/irssi/',
15    changed 	=> 'Sat Mar  1 13:32:30 CET 2003'
16);
17
18################################################################################
19#
20#  MD5 NickServ identification script for SorceryNet (irc.sorcery.net)
21#
22#  The script will do several things:
23#  - It adds the command /identify-md5 to Irssi, which can be used to identify
24#    to your current nickname or a list of nicknames given as arguments using
25#    the passwords provided below
26#  - It will automatically issue this command whenever NickServ notices you
27#    that you need to identify (e.g. after a services outage)
28#  - It will remember any channels ChanServ deopped you in and try to regain
29#    ops after authentication is accepted by NickServ
30#
31#  For more information on SorceryNets MD5 identification see:
32#  http://www.sorcery.net/help/howto/MD5_identify
33#
34#  Put your nicknames and MD5-hashed passwords here:
35#
36
37my %nicknames = (
38    lc('nick1')		=> md5_hex('password1'), 		# Plain text password 'password1'
39    lc('nick2')		=> '6cb75f652a9b52798eb6cf2201057c73',	# MD5-hash of password 'password2'
40    lc('nick3')		=> md5_hex('password3')
41);
42
43#
44#  Please note: This file should NOT be world-readable. Although it's (quite)
45#               impossible to get the original passwords from the hashes, a
46#               malicious person can identify using the hash and then change
47#               your password without knowing the old password.
48#
49################################################################################
50
51sub cmd_identify {
52
53    my ($data, $server, $witem) = @_;
54
55    # Are we connected?
56    if(!$server || !$server->{'connected'}) {
57
58	Irssi::print("Not connected to a server.");
59	return;
60    }
61
62    # Did the user specify what nick(s) to identify to?
63    if($data ne '') {
64
65	# Store the list of nicknames to identify to then
66	@identify = split /\s+/, $data;
67    }
68    else {
69
70	# Or put our current nick on the list
71	push @identify, $server->{'nick'};
72    }
73
74    # Start with some checks
75    for(my $i = $#identify; $i >= 0; $i--) {
76
77	# If we don't know the password
78	if(!defined $nicknames{lc $identify[$i]}) {
79
80	    # Send an error
81	    Irssi::print("I do not know the password for ${identify[$i]}. Please add it to identify-md5.pl.");
82
83	    # And remove the nick from the list
84	    splice @identify, $i, 1;
85	}
86    }
87
88    # Let's ask NickServ for a cookie if there are nicks left
89    $server->command("QUOTE NickServ identify-md5") if $#identify >= 0;
90}
91
92sub event_notice {
93
94    my ($server, $text, $nick, $address) = @_;
95
96    # Just ignore it if we are not on SorceryNet
97    return unless $server->{'real_address'} =~ /\.sorcery\.net$/;
98
99    # Is it a notice from NickServ?
100    if($nick eq 'NickServ') {
101
102	# Is it a cookie and do we need one?
103	if($text =~ /^205 S\/MD5 1\.0 (.+)$/ && $#identify >= 0) {
104
105	    my $cookie = $1;
106
107	    my $nickname = lc shift @identify;
108	    my $password = $nicknames{$nickname};
109
110	    # Create the hash and send it
111	    my $hash = md5_hex("$nickname:$cookie:$password");
112	    $server->command("QUOTE NickServ identify-md5 $nickname $hash");
113
114	    # Suppress the notice from NickServ
115	    Irssi::signal_stop();
116
117	    # And get a new cookie if there are still nicks left to identify to
118	    $server->command("QUOTE NickServ identify-md5") if $#identify >= 0;
119	}
120
121	# Is it a response?
122	elsif($text =~ /^\d{3} \- (.+)$/) {
123
124	    my $response = $1;
125
126	    # Just print the text-part and suppress the notice
127	    Irssi::print($response);
128
129	    if($response eq 'Authentication accepted -- you are now identified.') {
130
131		foreach my $channel (@reop) {
132		    $server->command("QUOTE ChanServ $channel op $server->{nick}");
133		}
134		undef @reop;
135	    }
136
137	    Irssi::signal_stop();
138	}
139
140	# Do we know the password? Let's see what NickServ has to tell us then
141	elsif(defined $nicknames{lc $server->{'nick'}}) {
142
143	    # Identify when NickServ asks us to
144	    if($text =~ /^This nick belongs to another user\./) {
145
146		$server->command("identify-md5");
147		Irssi::signal_stop();
148	    }
149
150	    # Just ignore this notice, we already identify when receiving the other one
151	    elsif($text eq 'If this is your nick please try: /msg NickServ ID password') {
152
153		Irssi::signal_stop();
154	    }
155	}
156    }
157
158    # If it's ChanServ saying it just deopped us, remember the channel so we can reop
159    elsif($nick eq 'ChanServ' && $text =~ /^You are not allowed ops in ([^\s]+)$/) {
160
161	push @reop, $1;
162
163	Irssi::signal_stop();
164    }
165}
166
167Irssi::command_bind('identify-md5', 'cmd_identify');
168Irssi::signal_add('message irc notice', 'event_notice');
169