+24Oct01=======================================================================
+1. added (un)set/register, show/registered commands which when a 'set/var
+$main::reqreg = 1' is done in the startup script will require users to
+be 'registered' in order for them to have 'write' access to the node. Non-
+registered users will only be allowed to TALK or SEND PRIVATE to the cluster
+sysop callsign.
+2. Added password interrogation to the ExtMsg connections. If a user comes
+in via telnet and this is being done with the internal listener and a pass-
+word has been set for that user - he will be asked for it. You can force
+a password interrogation (for ALL users) with a 'set/var $main::passwdreq = 1'
+in the node's startup script. It is anticipated that if you are using
+registration you will also issue passwords to those registered users.
+3. set/password has been changed so that users already with passwords can
+change them.
19Oct01=======================================================================
1. Allow DELETE (0x7f) for backspace in console.pl
+2. redo prefix table using latest cty.dat
14Oct01=======================================================================
1. Add the shortform SH/ST like display to sh/user <call> to make it more
AK1A compatible (G0RDI+G4PDQ pace).
either logout and login again (if you are on a console) or use the
SYSOP command.
+=== 0^SET/PASSWORD^Set your own password
+This command only works for a 'telnet' user (currently). It will
+only work if you have a password already set. This initial password
+can only be set by the sysop.
+
+When you execute this command it will ask you for your old password,
+then ask you to type in your new password twice (to make sure you
+get it right). You may or may not see the data echoed on the screen
+as you type, depending on the type of telnet client you have.
+
=== 9^SET/PASSWORD <callsign> <string>^Set a users password
The password for a user can only be set by a full sysop. The string
-can contain any characters but any spaces are removed (you can type in
-spaces - but they won't appear in the password). You can see the
-result with STAT/USER.
+can contain any characters.
+
+The way this field is used depends on context. If it is being used in
+the SYSOP command context then you are offered 5 random numbers and you
+have to supply the corresponding letters. This is now mainly for ax25
+connections.
+
+If it is being used on incoming telnet connections then, if a password
+is set or the:
+
+ set/var $main::passwdreq = 1
+
+command is executed in the startup script, then a password prompt is
+given after the normal 'login: ' prompt.
=== 5^SET/SPIDER <call> [<call>..]^Make the callsign an DXSpider node
Tell the system that the call(s) are to be treated as DXSpider node and
Tell the system where you are. For example:-
SET/QTH East Dereham, Norfolk
+=== 9^SET/REGISTER <call> ...^Mark a user as registered
+=== 9^UNSET/REGISTER <call> ...^Mark a user as not registered
+Registration is a concept that you can switch on by executing the
+
+ set/var $main::regreq = 1
+
+command (usually in your startup file)
+
+If a user is NOT registered then, firstly, instead of the normal
+motd file (/spider/data/motd) being sent to the user at startup, the
+user is sent the motd_nor file instead. Secondly, the non registered
+user only has READ-ONLY access to the node. The non-registered user
+cannot use DX, ANN etc.
+
+The only exception to this is that a non-registered user can TALK or
+SEND messages to the sysop.
+
=== 0^SET/TALK^Allow TALK messages to come out on your terminal
=== 0^UNSET/TALK^Stop TALK messages coming out on your terminal
=== 1^SHOW/ISOLATE^Show list of ISOLATED nodes
-=== 9^SHOW/LOCKOUT^Show the list of locked out or excluded callsigns
+=== 9^SHOW/LOCKOUT <prefix>|ALL^Show the list of locked out or excluded callsigns
=== 8^SHOW/LOG [<callsign>]^Show excerpts from the system log
This command outputs a short section of the system log. On its own
and returns any information available for that callsign. This service
is provided for users of this software by http://www.qrz.com
+=== 9^SHOW/REGISTERED [<prefix>]^Show the registered users
+
=== 0^SHOW/ROUTE <callsign> ...^Show the route to the callsign
This command allows you to see to which node the callsigns specified are
connected. It is a sort of inverse sh/config.
my @f = split /\s+/, $line;
return (1, $self->msg('e5')) if $self->remotecmd;
return (1, $self->msg('e9')) if !@f;
+return (1, $self->msg('e28')) unless $self->registered;
my $sort = uc $f[0];
my @locals = DXCommandmode->get_all();
my @all = grep {!$_->private || !($self->priv < 5 && $_->to ne $self->call && $_->from ne $self->call)} (DXMsg::get_all());
@all = grep {!$_->delete || ($self->priv >= 5 && $_->delete)} @all;
-return (1, $self->msg('e3', 'directory', $line)) unless @all;
+return (1, $self->msg('dir1')) unless @all;
my $sel = 0;
my $from = 0;
my $to = $all[@all-1]->msgno;
last if ++$count >= $n;
}
} else {
- push @out, $self->msg('e3', 'directory', $line);
+ push @out, $self->msg('dir1');
}
return (1, @out);
my $valid = 0;
my $localonly;
return (1, $self->msg('e5')) if $self->remotecmd;
+return (1, $self->msg('e28')) unless $self->registered;
my @bad;
if (@bad = BadWords::check($line)) {
# now deal with real message inputs
# parse out send line for various possibilities
- $loc = $self->{loc} = {};
+ $loc = {};
my $i = 0;
my @extra = ();
# $DB::single = 1;
$oref = DXMsg::get($msgno) if $msgno;
- unless ($oref) {
- delete $self->{loc};
- return (1, $self->msg('m4', $i));
- }
+ return (1, $self->msg('m4', $i)) unless $oref;
# now save all the 'to' callsigns for later
my $to;
$to = $oref->to;
@extra = ();
}
+
+ return (1, $self->msg('e28')) unless $self->registered || $to eq $main::myalias;
+
$loc->{to} = [ $to, @extra ]; # to is an array
$loc->{subject} = $oref->subject;
$loc->{subject} = "Re: " . $loc->{subject} if !($loc->{subject} =~ /^Re:\s/io);
# keep calling me for every line until I relinquish control
$self->func("DXMsg::do_send_stuff");
$self->state('sendbody');
+ $self->loc($loc);
push @out, $self->msg('m6', join(',', $to, @extra));
push @out, $self->msg('m7', $loc->{subject});
push @out, $self->msg('m8');
# any thing after send?
return (1, $self->msg('e6')) if !@f;
+ return (1, $self->msg('e28')) unless $self->registered || uc $f[0] eq $main::myalias;
while (@f) {
my $f = uc shift @f;
#
my ($self, $line) = @_;
-my @args = split /\s+/, $line;
+my @args = split /\s+/, $line, 2;
my $call = shift @args;
my @out;
my $user;
my $ref;
-return (1, $self->msg('e5')) if $self->priv < 9;
+if ($self->remotecmd) {
+ $call ||= $self->call;
+ Log('DXCommand', $self->call . " attempted to change password for $call remotely");
+ return (1, $self->msg('e5'));
+}
-if ($ref = DXUser->get_current($call)) {
- $line =~ s/^\s*$call\s+//;
- $line =~ s/\s+//og; # remove any blanks
- $line =~ s/[{}]//g; # no braces allowed
- $ref->passwd($line);
- $ref->put();
- push @out, $self->msg("password", $call);
+if ($call) {
+ if ($self->priv < 9) {
+ Log('DXCommand', $self->call . " attempted to change password for $call");
+ return (1, $self->msg('e5'));
+ }
+ return (1, $self->msg('e29')) unless @args;
+ if ($ref = DXUser->get_current($call)) {
+ $ref->passwd($args[0]);
+ $ref->put();
+ push @out, $self->msg("password", $call);
+ Log('DXCommand', $self->call . " changed password for $call");
+ } else {
+ push @out, $self->msg('e3', 'User record for', $call);
+ }
} else {
- push @out, $self->msg('e3', 'User record for', $call);
+ if ($self->conn->{csort} eq 'telnet' && $self->user->passwd) {
+ $self->conn->{decho} = $self->conn->{echo};
+ $self->conn->{echo} = 0;
+ push @out, $self->msg('pw0');
+ $self->state('passwd');
+ } else {
+ push @out, $self->msg('e5');
+ }
}
return (1, @out);
--- /dev/null
+#
+# register a user
+#
+# Copyright (c) 2001 Dirk Koopman G1TLH
+#
+# $Id$
+#
+my ($self, $line) = @_;
+my @args = split /\s+/, $line;
+my $call;
+# my $priv = shift @args;
+my @out;
+my $user;
+my $ref;
+
+if ($self->priv < 9) {
+ Log('DXCommand', $self->call . " attempted to register @args");
+ return (1, $self->msg('e5'));
+}
+return (1, $self->msg('reginac')) unless $main::reqreq;
+
+foreach $call (@args) {
+ $call = uc $call;
+ unless ($self->remotecmd) {
+ if ($ref = DXUser->get_current($call)) {
+ $ref->registered(1);
+ $ref->put();
+ push @out, $self->msg("reg", $call);
+ } else {
+ $ref = DXUser->new($call);
+ $ref->registered(1);
+ $ref->put();
+ push @out, $self->msg("regc", $call);
+ }
+ my $dxchan = DXChannel->get($call);
+ $dxchan->registered(1) if $dxchan;
+ Log('DXCommand', $self->call . " registered $call");
+ } else {
+ Log('DXCommand', $self->call . " attempted to register $call remotely");
+ push @out, $self->msg('sorry');
+ }
+}
+return (1, @out);
use DB_File;
if ($line) {
- $line =~ s/[^\w-\/]+//g;
+ $line =~ s/[^\w\-\/]+//g;
$line = "^\U\Q$line";
}
+return (1, $self->msg('lockoutuse')) unless $line;
+
my ($action, $count, $key, $data) = (0,0,0,0);
for ($action = DXUser::R_FIRST, $count = 0; !$DXUser::dbm->seq($key, $data, $action); $action = DXUser::R_NEXT) {
if ($data =~ m{lockout =>}) {
- if ($line && $key =~ /$line/) {
- my $u = DXUser->get_current($key);
- if ($u && $u->lockout) {
+ if ($line eq 'ALL' || $key =~ /$line/) {
+ my $ur = DXUser->get_current($key);
+ if ($ur && $ur->lockout) {
push @out, $key;
++$count;
}
--- /dev/null
+#
+# show/registered
+#
+# show all registered users
+#
+# Copyright (c) 2001 Dirk Koopman G1TLH
+#
+# $Id$
+#
+
+my ($self, $line) = @_;
+return (1, $self->msg('e5')) unless $self->priv >= 9;
+
+my @out;
+
+use DB_File;
+
+if ($line) {
+ $line =~ s/[^\w\-\/]+//g;
+ $line = "^\U\Q$line";
+}
+
+my ($action, $count, $key, $data) = (0,0,0,0);
+for ($action = DXUser::R_FIRST, $count = 0; !$DXUser::dbm->seq($key, $data, $action); $action = DXUser::R_NEXT) {
+ if ($data =~ m{registered =>}) {
+ if (!$line || ($line && $key =~ /$line/)) {
+ my $u = DXUser->get_current($key);
+ if ($u && $u->registered) {
+ push @out, $key;
+ ++$count;
+ }
+ }
+ }
+}
+
+return (1, @out, $self->msg('rec', $count));
+
+
my $clref = Route::get($call); # try an exact call
my $dxchan = $clref->dxchan if $clref;
return (1, $self->msg('e7', $call)) unless $dxchan;
+return (1, $self->msg('e28')) unless $self->registered || $to eq $main::myalias;
# if there is a line send it, otherwise add this call to the talk list
# and set talk mode for command mode
--- /dev/null
+#
+# unregister a user
+#
+# Copyright (c) 2001 Dirk Koopman G1TLH
+#
+# $Id$
+#
+my ($self, $line) = @_;
+my @args = split /\s+/, $line;
+my $call;
+# my $priv = shift @args;
+my @out;
+my $user;
+my $ref;
+
+if ($self->priv < 9) {
+ Log('DXCommand', $self->call . " attempted to unregister @args");
+ return (1, $self->msg('e5'));
+}
+return (1, $self->msg('reginac')) unless $main::reqreq;
+
+foreach $call (@args) {
+ $call = uc $call;
+ unless ($self->remotecmd) {
+ if ($ref = DXUser->get_current($call)) {
+ $ref->registered(0);
+ $ref->put();
+ my $dxchan = DXChannel->get($call);
+ $dxchan->registered(0) if $dxchan;
+ push @out, $self->msg("regun", $call);
+ Log('DXCommand', $self->call . " unregistered $call");
+ } else {
+ push @out, $self->msg('e3', 'unset/register', $call);
+ }
+ } else {
+ Log('DXCommand', $self->call . " attempted to unregister $call remotely");
+ push @out, $self->msg('sorry');
+ }
+}
+return (1, @out);
my $t = ztime(time);
my $tonode;
my $sysopflag;
+return (1, $self->msg('e5')) if $self->remotecmd;
+return (1, $self->msg('e28')) unless $self->registered;
if ($sort eq "FULL") {
$line =~ s/^$f[0]\s+//; # remove it
inwcyfilter => '5,WCY Filt-inp',
inspotsfilter => '5,Spot Filt-inp',
inroutefilter => '5,Route Filt-inp',
- passwd => '9,Passwd List,parray',
+ passwd => '9,Passwd List,yesno',
pingint => '5,Ping Interval ',
nopings => '5,Ping Obs Count',
lastping => '5,Ping last sent,atime',
$self->{name} = $name ? $name : $call;
$self->send($self->msg('l2',$self->{name}));
- $self->send_file($main::motd) if (-e $main::motd);
$self->state('prompt'); # a bit of room for further expansion, passwords etc
$self->{priv} = $user->priv || 0;
$self->{lang} = $user->lang || $main::lang || 'en';
$self->{pagelth} = $user->pagelth || 20;
- $self->{priv} = 0 if $line =~ /^(ax|te)/; # set the connection priv to 0 - can be upgraded later
($self->{width}) = $line =~ /width=(\d+)/;
$self->{width} = 80 unless $self->{width} && $self->{width} > 80;
$self->{consort} = $line; # save the connection type
$self->{ann_talk} = $user->wantann_talk;
$self->{here} = 1;
+ # sort out registration
+ if ($main::reqreq) {
+ $self->{registered} = $user->registered;
+ } else {
+ $self->{registered} = 1;
+ }
+
+
+ # decide which motd to send
+ my $motd = "${main::motd}_nor" unless $self->{registered};
+ $motd = $main::motd unless $motd && -e $motd;
+ $self->send_file($motd) if -e $motd;
+
+ # sort out privilege reduction
+ $self->{priv} = 0 if $line =~ /^(ax|te)/ && !$self->conn->{usedpasswd};
+
# get the filters
$self->{spotsfilter} = Filter::read_in('spots', $call, 0) || Filter::read_in('spots', 'user_default', 0);
$self->{wwvfilter} = Filter::read_in('wwv', $call, 0) || Filter::read_in('wwv', 'user_default', 0);
}
} elsif ($self->{state} eq 'sysop') {
my $passwd = $self->{user}->passwd;
- my @pw = split / */, $passwd;
if ($passwd) {
+ my @pw = grep {$_ !~ /\s/} split //, $passwd;
my @l = @{$self->{passwd}};
my $str = "$pw[$l[0]].*$pw[$l[1]].*$pw[$l[2]].*$pw[$l[3]].*$pw[$l[4]]";
if ($cmdline =~ /$str/) {
} else {
$self->send($self->msg('sorry'));
}
- delete $self->{passwd};
+ $self->state('prompt');
+ } elsif ($self->{state} eq 'passwd') {
+ my $passwd = $self->{user}->passwd;
+ if ($passwd && $cmdline eq $passwd) {
+ $self->send($self->msg('pw1'));
+ $self->state('passwd1');
+ } else {
+ $self->conn->{echo} = $self->conn->{decho};
+ delete $self->conn->{decho};
+ $self->send($self->msg('sorry'));
+ $self->state('prompt');
+ }
+ } elsif ($self->{state} eq 'passwd1') {
+ $self->{passwd} = $cmdline;
+ $self->send($self->msg('pw2'));
+ $self->state('passwd2');
+ } elsif ($self->{state} eq 'passwd2') {
+ if ($cmdline eq $self->{passwd}) {
+ $self->{user}->passwd($cmdline);
+ $self->send($self->msg('pw3'));
+ } else {
+ $self->send($self->msg('pw4'));
+ }
+ $self->conn->{echo} = $self->conn->{decho};
+ delete $self->conn->{decho};
$self->state('prompt');
} elsif ($self->{state} eq 'talk') {
if ($cmdline =~ m{^(?:/EX|/ABORT)}i) {
$self->{here} = 1;
$self->{width} = 80;
+ # sort out registration
+ $self->{registered} = 1;
+
# get the output filters
$self->{spotsfilter} = Filter::read_in('spots', $call, 0) || Filter::read_in('spots', 'node_default', 0);
$self->{wwvfilter} = Filter::read_in('wwv', $call, 0) || Filter::read_in('wwv', 'node_default', 0);
email => '0,E-mail Address',
priv => '9,Privilege Level',
lastin => '0,Last Time in,cldatetime',
- passwd => '9,Password',
+ passwd => '9,Password,yesno',
addr => '0,Full Address',
'sort' => '0,Type of User', # A - ak1a, U - User, S - spider cluster, B - BBS
xpert => '0,Expert Status,yesno',
lockout => '9,Locked out?,yesno', # won't let them in at all
dxok => '9,Accept DX Spots?,yesno', # accept his dx spots?
annok => '9,Accept Announces?,yesno', # accept his announces?
- reg => '0,Registered?,yesno', # is this user registered?
lang => '0,Language',
hmsgno => '0,Highest Msgno',
group => '0,Access Group,parray', # used to create a group of users/nodes for some purpose or other
# this really does need to change for your system!!!!
+# use CAPITAL LETTERS
$mycall = "GB7DJK";
# your name
$myname = "Dirk";
-# Your 'normal' callsign
+# Your 'normal' callsign (in CAPTTAL LETTERS)
$myalias = "G1TLH";
# Your latitude (+)ve = North (-)ve = South in degrees and decimal degrees
# Your Longtitude (+)ve = East, (-)ve = West in degrees and decimal degrees
$mylongitude = +0.94518260;
-# Your locator (yes I know I can calculate it - eventually)
+# Your locator (USE CAPITAL LETTERS)
$mylocator = "JO02LQ";
# Your QTH (roughly)
if (is_callsign($msg) && $msg !~ m|/| ) {
my $sort = $conn->{csort};
$sort = 'local' if $conn->{peerhost} eq "127.0.0.1";
- $conn->to_connected($msg, 'A', $sort);
+ my $uref;
+ if ($main::passwdreq || ($uref = DXUser->get_current($msg)) && $uref->passwd ) {
+ $conn->conns($msg);
+ $conn->{state} = 'WP';
+ $conn->{decho} = $conn->{echo};
+ $conn->{echo} = 0;
+ $conn->send_raw('password: ');
+ } else {
+ $conn->to_connected($msg, 'A', $sort);
+ }
} else {
$conn->send_now("Sorry $msg is an invalid callsign");
$conn->disconnect;
}
+ } elsif ($conn->{state} eq 'WP' ) {
+ my $uref = DXUser->get_current($conn->{call});
+ $msg =~ s/[\r\n]+$//;
+ if ($uref && $msg eq $uref->passwd) {
+ my $sort = $conn->{csort};
+ $conn->{echo} = $conn->{decho};
+ delete $conn->{decho};
+ $sort = 'local' if $conn->{peerhost} eq "127.0.0.1";
+ $conn->{usedpasswd} = 1;
+ $conn->to_connected($conn->{call}, 'A', $sort);
+ } else {
+ $conn->send_now("Sorry");
+ $conn->disconnect;
+ }
} elsif ($conn->{state} eq 'WC') {
if (exists $conn->{cmd} && @{$conn->{cmd}}) {
$conn->_docmd($msg);
db10 => '$_[0] records imported into $_[1]',
db11 => 'Sending your request(s) to $_[0], please stand by...',
dfreq1 => 'Invalid freq $_[0] need: eg 0/30000 or hf or hf/cw',
+ dir1 => 'No messages found',
disc1 => 'Disconnected by $_[0]',
disc2 => 'Channel $_[0] disconnected',
disc3 => 'No Channel, but connection $_[0] disconnected',
e25 => 'Sorry the value must be between $_[0] and $_[1]',
e26 => 'Too many concurrent errors, you are being disconnected',
e27 => '$_[0] not a numeric or a callsign prefix',
+ e28 => 'Sorry, you need to be registered (SP $main::myalias to register)',
+ e29 => 'Need a password',
echoon => 'Echoing enabled',
echooff => 'Echoing disabled',
lockout => '$_[0] Locked out',
lockoutc => '$_[0] Created and Locked out',
lockoutun => '$_[0] Unlocked',
+ lockoutuse => 'usage: sh/lockout <call>|ALL',
loginu => 'User $_[0] has logged in',
logoutu => 'User $_[0] has logged out',
loginn => 'Node $_[0] has logged in',
pr2 => '($_[0]) de $main::mycall $_[1] $_[2] >',
priv => 'Privilege level changed on $_[0]',
prx => '$main::mycall >',
+ pw0 => 'Enter old password: ',
+ pw1 => 'Enter new password: ',
+ pw2 => 'Re-enter new password: ',
+ pw3 => 'Password changed',
+ pw4 => 'Passwords differ, password NOT changed',
qll => 'Please enter your location with set/location or set/qra',
qthe1 => 'Please enter your QTH, set/qth <your qth>',
qth => 'Your QTH is now \"$_[0]\"',
qrae2 => 'Don\'t recognise \"$_[0]\" as a QRA locator (eg JO02LQ)',
qra => 'Your QRA Locator is now \"$_[0]\"',
rcmdo => 'RCMD \"$_[0]\" sent to $_[1]',
- rec => '$_[0] records',
read1 => 'Sorry, no new messages for you',
read2 => 'Msg $_[0] not found',
read3 => 'Msg $_[0] not available',
+ rec => '$_[0] records',
+ reg => '$_[0] registered',
+ regc => '$_[0] created and registered',
+ reginac => 'Registration is not active (set/var \$main::regreq = 1 to activate)',
+ regun => '$_[0] unregistered',
route => '$_[0] on $_[1] via $_[2]',
sat1 => 'Tracking Table for $_[0] for the next $_[1] hours every $_[2] mins',
sat2 => 'dd/mm UTC Lat Lon Alt Km Az El Dist Km',