html/xauth.pl


   1 # Some code taken from `nickserv.pl' for convenience.
   2 # Credits Sami Haahtinen / ZaNaGa
   3 #
   4 
   5 # Don't forget to create the necessary chatnets in your irssi config file.
   6 # 
   7 # Example:
   8 # ....
   9 # {
  10 #   address = "irc.undernet.org";
  11 #   chatnet = "Undernet";
  12 #   port = "6668";
  13 #   autoconnect = no;
  14 #  }
  15 # .....
  16 #
  17 # 
  18 # Then connect with the server like this:
  19 # /server undernet (or set autoconnect to yes)
  20 
  21 # Make sure you fill in *all* necessary information without typos.
  22 #
  23 # Files you need to edit after first run:
  24 # x.users     -> For your x user/pw information.
  25 # x.channels  -> Channels to join after authing. (optional)
  26 #
  27 # Use /xrehash to reload if you edit the files.
  28 #
  29 # Var:
  30 # my (%masks) -> See help there.
  31 
  32 # Tested with X versions
  33 # Undernet P10 Channel Services II Release 1.1pl7
  34 # 
  35 
  36 #
  37 # This program is free software; you can redistribute it and/or modify
  38 # it under the terms of the GNU General Public License as published by
  39 # the Free Software Foundation; either version 2, or (at your option)
  40 # any later version.
  41 #
  42 # This program is distributed in the hope that it will be useful, but
  43 # WITHOUT ANY WARRANTY; without even the implied warranty of
  44 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the file
  45 # COPYING (included with this distribution) or the GNU General Public
  46 # License for more details.
  47 #
  48 # You should have received a copy of the GNU General Public License
  49 # along with this program; if not, write to the Free Software
  50 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  51 #
  52 
  53 use Irssi;
  54 use Irssi::Irc;
  55 
  56 use strict;
  57 
  58 use vars qw($VERSION %IRSSI);
  59 
  60 $VERSION = '1.02';
  61 
  62 %IRSSI = (
  63     authors     => 'Toshio R. Spoor',
  64     contact     => 't.spoor@gmail.com',
  65     name        => 'xauth',
  66     description => 'Undernet X Service Authentication Program',
  67     license     => 'GNU GPLv2 or later',
  68     changed     => '$Date: 2004/12/17 08:39:47 $'
  69 );
  70 
  71 my (%CONFIG) = (
  72     autostart	=> '',
  73     autojoin	=> '',
  74     hiddenhost	=> ''
  75 );
  76 
  77 Irssi::theme_register([
  78   xauth_rehash    => '{comment $0} %KRehashing configuration files and settings%n',
  79   xauth_autostart => '{comment $0} %KAuto-Start :%n $1',
  80   xauth_autojoin  => '{comment $0} %KAuto-Join  :%n $1',
  81   xauth_hiddenhost=> '{comment $0} %KHiddenhost :%n $1',
  82   xauth_auth      => '{comment $0} %KAuthorising%n $1 %Kwith%n $2 %Kon%n $3',
  83   xauth_load      => '{comment $0} %KScript %nv$1 %Kloaded ...%n',
  84   xauth_nocon     => '{comment $0} %KNot connected to server%n',
  85   xauth_noconn    => '{comment $0} %KThere does not exist a connection to $1%n',
  86   xauth_success   => '{comment $0} %KLogged in successfully on %n$1',
  87   xauth_failed    => '{comment $0} %KFailed to login on %n$1 ($2)',
  88   xauth_already   => '{comment $0} %KI am already logged in on%n $1',
  89   xauth_nouser    => '{comment $0} $1 %Kdoes not know who %n$2 %Kis on %n$3',
  90   xauth_nohost    => '{comment $0} %KNo hostmask found for %n$1%K, to fix this edit this script, see masks',
  91   xauth_noentry   => '{comment $0} %KI did not find an entry for %n$1 %Kcheck%n $2',
  92   xauth_missing   => '{comment $0} %KI am missing username, password or authentication host login information%n',
  93   xauth_join      => '{comment $0} %KJoined on%n $1%K : %n$2-'
  94 ]);
  95 
  96 my ($usage) = qq!X-Authentication v$VERSION by Toshio Spoor
  97 
  98 Usage:
  99 /auth <chatnet>
 100 
 101 Settings:
 102 /set xauth                      Shows current settings
 103 /toggle xauth_autostart         Toggle Auto Start
 104 /toggle xauth_autojoin          Toggle Auto Join
 105 /toggle xauth_hiddenhost        Toggle Hiddenhost (ircu u2.10.11+)
 106 
 107 Rehashing settings and user/channel file:
 108 /xrehash                        Run this after any changes
 109                                                                 made to settings/files
 110                                                                 
 111 /save                           Make settings permanent
 112 !;
 113 
 114 # The `masks' hash is very important:
 115 # Here we fill in the masks we need to authenticate with. 
 116 #
 117 # <chatnet> = <host> <authhost>
 118 #
 119 # You can find this very easily:
 120 # /msg x login
 121 #
 122 # 08:49 -!- Irssi: Starting query in Undernet with x
 123 # 08:49 <Foo> login
 124 # 08:49 -X(channels@undernet.org)- To use LOGIN, you must /msg X@services.undernet.org
 125 #
 126 # Keep the chatnet lowercase
 127 
 128 my (%masks) = (       
 129        undernet    => [ 'cservice@undernet.org', 'X@channels.undernet.org' ],
 130        worldirc    => [ 'cservice@worldirc.org','X@channels.worldirc.org' ]
 131 );
 132 
 133 # 0 = None
 134 # 1 = Normal
 135 # 2 = More
 136 
 137 my ($verbose) = 1;
 138 
 139 # Don't touch these, unless the signature changes.
 140 #
 141 my ($success) = "AUTHENTICATION SUCCESSFUL";
 142 my ($already) = "Sorry, You are already authenticated";
 143 my ($failed)  = "AUTHENTICATION FAILED";
 144 my ($remind)  = "Remember: Nobody from CService will ever ask you for your password, do NOT give";
 145 my ($nouser)  = "I don't know who";
 146 
 147 # Global Vars, don't change these.
 148 # 
 149 my ($x_passfile) = Irssi::get_irssi_dir() ."/x.users";
 150 my ($x_chanfile) = Irssi::get_irssi_dir() ."/x.channels";
 151 
 152 my (@users) = (); 
 153 my (@chans) = ();
 154 
 155 # Core Code
 156 #
 157 # 
 158 
 159 sub putlog() {
 160 
 161         my ($window) = Irssi::active_win();
 162 	Irssi::print("[$IRSSI{'name'}] @_", MSGLEVEL_CLIENTNOTICE);
 163 	
 164 }
 165 
 166 sub haltdef() {
 167 
 168         Irssi::signal_stop();
 169 
 170 }
 171 
 172 sub conn($) {
 173 
 174         my ($server) = @_;
 175 
 176         if (!$server || !$server->{connected}) {
 177                 return 0;
 178         } else {
 179         	return 1;
 180         }
 181 
 182 }
 183 
 184 sub join_channels($) {
 185 	
 186         my ($chatnet)  = @_;
 187         my (@channels) = ();
 188         my ($server)   = Irssi::server_find_tag($chatnet);
 189         
 190         if (!$server) {
 191         	Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_nocon", "$IRSSI{'name'}");
 192         	return;
 193         }
 194                          
 195         foreach (@chans) {
 196         	
 197                 my ($channel, $ircnet) = split(/:/);
 198                 
 199                 if (lc($chatnet) eq lc($ircnet)) {                
 200                 	# If we do it like this, the status window stays active.
 201                 	push (@channels, $channel);
 202                 	$server->send_raw("JOIN #$channel");
 203                 }
 204         }
 205         
 206         if ($verbose) {
 207         	if (@channels) {
 208         		Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_join", "$IRSSI{'name'}", $chatnet, @channels);
 209 	        }
 210 	}
 211 }
 212 
 213 sub mask_check($) {
 214 	
 215 	my ($address) = @_;
 216 	
 217 	foreach my $key (keys %masks) {
 218 		if (lc($masks{$key}->[0]) eq lc($address)) {
 219 			return $key;
 220 			last;
 221 		}
 222         }
 223 	
 224 	return 0;
 225 	
 226 }
 227 
 228 
 229 sub event_notice() {
 230 
 231         my ($server, $args, $nick, $nickad) = @_;
 232                
 233 	return unless (&mask_check($nickad));
 234 	
 235         my ($cnet) = $server->{'tag'};
 236         my ($version) = $server->{'version'};
 237         
 238         my ($target, $data) = $args =~ /^(\S*)\s+:(.*)$/;
 239         
 240         $_ = $data;
 241 
 242         if (/^$already/i) { 
 243                 Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_already", "$IRSSI{'name'}", $cnet);
 244                 &haltdef();
 245         }
 246 
 247         if (/^$success/i) {         
 248                 Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_success", "$IRSSI{'name'}", $cnet);
 249                 
 250                 if (($version) && ($CONFIG{'hiddenhost'})) {
 251                 	
 252         		my($app,$hi,$lo) = $version =~ /^(..).(..).(..)/;
 253         		$app =~ s/\D//g;
 254         		
 255         		if (($app >= 2) && ($lo >= 11)) {
 256         			&putlog("Found ircu $version, setting umode +x") if ($verbose > 1);
 257         			$server->command("mode $target +x");
 258         		}
 259         	}
 260         	
 261                 if ($CONFIG{'autojoin'}) {
 262                 	&join_channels($cnet);
 263                 }
 264                 &haltdef();
 265         }
 266 
 267         if (/^$failed/i) {
 268                 if (/\((.*?)\)/) { $args = $1 };
 269                 Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_failed", "$IRSSI{'name'}", $cnet, $args);
 270                 &haltdef();
 271         }
 272         
 273         if (/^$remind/i) {
 274                 &haltdef();
 275         }
 276         
 277         if (/^$nouser/i) {
 278         	if (/who\s(.*?)\s/) { $args = $1 };
 279         	Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_nouser", "$IRSSI{'name'}", "$nick", $args, $cnet);
 280         	&haltdef();
 281         }
 282 }
 283 
 284 sub cmd_auth() {
 285 
 286         my ($data, $server, $witem) = @_;
 287         my ($username, $ircnet, $password, $xlogin, $xmask, $chatnet, $found);
 288 
 289         if ($data) {
 290                 $chatnet = $data;
 291         } else {
 292                 &putlog("$usage");
 293                 return;
 294         }
 295         
 296         if (! &conn($server)) { 
 297                 Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_nocon", "$IRSSI{'name'}");
 298                 return;
 299         }
 300 
 301         my ($authserver) = Irssi::server_find_tag($chatnet);
 302 
 303         if (! $authserver) {
 304                 Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_noconn", "$IRSSI{'name'}", $chatnet);
 305                 return;
 306         }
 307 
 308         foreach (@users) {
 309 
 310                 ($username, $ircnet, $password) = split(/:/);
 311 
 312                 if (lc($ircnet) eq lc($chatnet)) {
 313                         $xmask  = $masks{lc($ircnet)}->[0];
 314                         $xlogin = $masks{lc($ircnet)}->[1];
 315                         
 316                         if ((!$xmask) || (!$xlogin)) {
 317                         	Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_nohost", "$IRSSI{'name'}", $chatnet);
 318                         	return;
 319                         }
 320                         
 321                         $found=1;
 322                         last;
 323                 }
 324         }
 325 
 326         if (! $found ) {
 327                 Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_noentry", "$IRSSI{'name'}", $chatnet, qq/"$x_passfile"/);
 328                 return;
 329         }
 330 
 331         if (($username) && ($password) && ($xlogin)) {
 332                 Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_auth", "$IRSSI{'name'}", $username, $xlogin, $chatnet);
 333                 $authserver->send_raw("PRIVMSG $xlogin :login $username $password");
 334         } else {
 335                 Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_missing", "$IRSSI{'name'}");
 336         }
 337 }
 338 
 339 # Code taken from nickserv.pl
 340 
 341 sub read_users() {
 342         my $count = 0;
 343                 
 344         # Lets reset @users so we can call this as a function.
 345         @users = ();            
 346                         
 347         if (!(open XUSERS, "<$x_passfile")) {
 348                 &create_users;
 349         };
 350        	&putlog("Running checks on the userfile.") if ($verbose > 1);
 351         # first we test the file with mask 066 (we don't actually care if the
 352         # file is executable by others.. what could they do with it =)
 353 
 354         # Well, according to my calculations umask 066 should be 54, go figure.
 355         
 356         my $mode = (stat($x_passfile))[2];
 357         if ($mode & 54) {
 358                 &putlog("your password file should be mode 0600. Go fix it!");
 359                 &putlog("use command: chmod 0600 $x_passfile");
 360         }
 361         
 362         # and then we read the userfile.
 363         # apparently Irssi resets $/, so we set it here.
 364 
 365         $/ = "\n";
 366         while( my $line = <XUSERS>) {
 367                 if( $line !~ /^(#|\s*$)/ ) { 
 368                         my ($nick, $ircnet, $password) = 
 369 				$line =~ /^\s*(\S+)\s+(\S+)\s+(.*?)$/;
 370                         push @users, "$nick:$ircnet:$password";
 371                         $count++;
 372                 }
 373         }
 374        	&putlog("Found $count accounts") if ($verbose > 1);
 375         close XUSERS;
 376 }
 377 
 378 sub create_users() {
 379 
 380         &putlog("Creating basic userfile in $x_passfile. Edit File.");
 381         
 382         if(!(open XUSERS, ">$x_passfile")) {
 383                &putlog("Unable to create file $x_passfile");
 384         }
 385 
 386         print XUSERS "# username and IrcNet Tag are case insensitive\n";
 387         print XUSERS "#\n";
 388         print XUSERS "# username      IrcNet Tag      Password\n";
 389         print XUSERS "# --------      ----------      --------\n";
 390 
 391         close XUSERS;
 392         chmod 0600, $x_passfile;
 393 }
 394 
 395 sub create_chans() {
 396         &putlog("Creating basic channelfile in $x_chanfile. Edit File.");
 397         if(!(open NICKCHANS, ">$x_chanfile")) {
 398                 &putlog("Unable to create file $x_chanfile");
 399         }
 400 
 401         print NICKCHANS "# This file should contain a list of all channels\n";
 402         print NICKCHANS "# which you don't want to join until after you've\n";
 403         print NICKCHANS "# successfully identified with x.  This is\n";
 404         print NICKCHANS "# useful if you have a hidden host (+x).\n";
 405         print NICKCHANS "# Enter Channel without `#'\n";
 406         print NICKCHANS "#\n";
 407         print NICKCHANS "# Channel       IrcNet Tag\n";
 408         print NICKCHANS "# --------      ----------\n";
 409 
 410         close NICKCHANS;
 411         chmod 0600, $x_chanfile;
 412 }
 413 
 414 sub read_chans() {
 415         my $count = 0;
 416 
 417         # Lets reset @users so we can call this as a function.
 418         @chans = ();
 419 
 420         if (!(open NICKCHANS, "<$x_chanfile")) {
 421                 create_chans;
 422         };
 423        	&putlog("Running checks on the channelfile.") if ($verbose > 1);
 424         # first we test the file with mask 066 (we don't actually care if the
 425         # file is executable by others.. what could they do with it =)
 426         
 427         # Well, according to my calculations umask 066 should be 54, go figure.
 428 
 429         my $mode = (stat($x_chanfile))[2];
 430         if ($mode & 54) {
 431                 &putlog("your channels file should be mode 0600. Go fix it!");
 432                 &putlog("use command: chmod 0600 $x_chanfile");
 433         }
 434         
 435         # and then we read the channelfile.
 436         # apparently Irssi resets $/, so we set it here.
 437 
 438         $/ = "\n";
 439         while( my $line = <NICKCHANS>) {
 440                 if( $line !~ /^(#|\s*$)/ ) { 
 441                         my ($channel, $ircnet) = 
 442                                 $line =~ /\s*(\S+)\s+(\S+)/;
 443                         push @chans, "$channel:$ircnet";
 444                         $count++;
 445                 }
 446         }
 447        	&putlog("Found $count channels") if ($verbose > 1);
 448         close NICKCHANS;
 449 }
 450 
 451 # End code from nickserv.pl
 452 
 453 sub event_connect() {
 454 
 455 	$CONFIG{'autostart'}  = Irssi::settings_get_bool('xauth_autostart');
 456 
 457 	return unless ($CONFIG{'autostart'});
 458 	
 459         my ($server) = @_;
 460         my ($cnet) = $server->{'tag'};
 461         my ($found);
 462         
 463         foreach my $key (keys %masks) {
 464         	if (lc($key) eq lc($cnet)) {
 465         		$found=1;
 466         		last;
 467         	}
 468 	}
 469 
 470 	return unless($found);
 471 
 472         $server->command("auth $cnet");
 473 
 474 }
 475 
 476 sub x_rehash() {
 477 	
 478 	Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_rehash", "$IRSSI{'name'}") if (($verbose) && (@_));
 479 	
 480 	&read_users();
 481 	&read_chans();
 482 	&get_set(@_);
 483 	
 484 }
 485 
 486 sub init_set() {
 487 
 488 	Irssi::settings_add_bool('misc', 'xauth_autostart', '0');
 489 	Irssi::settings_add_bool('misc', 'xauth_autojoin',  '1');
 490 	Irssi::settings_add_bool('misc', 'xauth_hiddenhost','0');	
 491 		
 492 }
 493 
 494 sub onoff($) {
 495 	
 496 	my ($value) = @_;
 497 	
 498 	if ($value) {
 499 		return "On";
 500 	} else {
 501 		return "Off";
 502 	}	
 503 	
 504 }
 505 
 506 sub get_set() {
 507 	
 508 	$CONFIG{'autostart'}  = Irssi::settings_get_bool('xauth_autostart');
 509 	$CONFIG{'autojoin'}   = Irssi::settings_get_bool('xauth_autojoin');
 510 	$CONFIG{'hiddenhost'} = Irssi::settings_get_bool('xauth_hiddenhost');
 511 	
 512 	Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_autostart", "$IRSSI{'name'}", &onoff("$CONFIG{'autostart'}"))   if (($verbose) && (@_));
 513 	Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_autojoin",  "$IRSSI{'name'}", &onoff("$CONFIG{'autojoin'}"))    if (($verbose) && (@_));
 514 	Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_hiddenhost", "$IRSSI{'name'}", &onoff("$CONFIG{'hiddenhost'}")) if (($verbose) && (@_));
 515 	
 516 }
 517 
 518 sub init() {
 519 
 520 	&init_set();
 521 	&x_rehash();
 522 
 523 	
 524 }
 525 
 526 sub x_help() {
 527 	
 528 	&putlog("$usage");
 529 	
 530 }
 531 
 532 
 533 # Main
 534 #
 535 #
 536 
 537 &init();
 538 
 539 Irssi::command_bind("auth", "cmd_auth");
 540 Irssi::command_bind("xrehash", "x_rehash");
 541 Irssi::command_bind("xhelp", "x_help");
 542 
 543 Irssi::signal_add("event notice", "event_notice");
 544 Irssi::signal_add("event connected", "event_connect");
 545 
 546 Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "xauth_load", "$IRSSI{'name'}", $VERSION);