// /bin/adm/login.c -- Vincent's Hollow Project.
#define DEBUG
#include <version.h>
#include <files.h>
#include <daemons.h>
#include <login.h>
// Magic numbers/phrases.
#define MAX_NAME 12
#define ASK_NAME "What is your name? "
#define ASK_PASS "What is your password, " + capitalize(name) + "? "
#define CRAP_NAME1 \
"\nSorry, but we can't accept your name in its current form.\n"+\
"Your name has to have at least 2 characters in it and no\n"+\
"more than " + MAX_NAME + " characters.\n\n"+\
"You may try again.\n\n"
#define CRAP_NAME2 \
"\nSorry, but we can't accept your name in its current form.\n"+\
"Your name can only have characters 'a' through 'z'.\n\n"+\
"You may try again.\n\n"
// Macros to make coding easier.
#define REMOVE signoff();
#define REMOVE_NONEWS call_out("signoff_cont",1);
#define NOWAIT if(find_call_out("signoff")) remove_call_out("signoff")
#define WAIT call_out("signoff", 60)
// Prototypings.
static void logon();
void get_name(string str);
void get_password(string pass);
int check_password(string pass);
void new_pass(string pass);
void new_pass2(string pass2);
void signoff();
void signoff_msg();
// Global var declarations.
private static string name, temp, password;
private static object player;
// Let the login start.
void
create()
{
#ifdef DEBUG
write("login: create\n");
#endif
seteuid((string)master()->get_root_uid());
}
// Start of the login server
static void
logon()
{
#ifdef DEBUG
write("login: logon\n");
#endif
if(!(KERBEROS_D->request_ticket()))
{
write("kerberos: ticket refused\n");
REMOVE;
return;
}
write(ASK_NAME);
WAIT;
input_to("get_name");
return;
}
static void
get_name(string str)
{
int i, size;
NOWAIT;
if(!str || str == "")
{
REMOVE;
return;
}
name = lower_case(str);
/*
* Check for logging on from restricted sites.
*/
if (KERBEROS_D->check_restricted(query_ip_name()))
{
write("You are logging in from a restricted site.\n");
if (!KERBEROS_D->check_restrict_ok(name))
{
cat(NEWS+"login.site_restrict");
REMOVE;
return;
}
write("You are o.k. to log in.\n");
}
/*
* Site is OK, next:
* Check name is acceptable.
*/
size = strlen(str);
if(size > MAX_NAME || size < 2)
{
write(CRAP_NAME1);
write(ASK_NAME);
WAIT;
input_to("get_name");
return;
}
for(i = 0; i < size; i++)
{
if(name[i] < 'a' || name[i] > 'z')
{
write(CRAP_NAME2);
write(ASK_NAME);
WAIT;
input_to("get_name");
return;
}
}
/*
* Site is allowed, name is acceptable:
* Check name is allowed to logon
*/
if(!KERBEROS_D->check_access(name))
{
write("\n");
REMOVE;
return;
}
/*
* Passed the access checks:
* Either get the password and check it,
* or get a new password.
*/
if(file_size(SAVE + name + ".o") < 0)
{
cat(NEWS + "login.newpass");
write(ASK_PASS);
WAIT;
input_to("new_pass", 1);
return;
}
write(ASK_PASS);
WAIT;
input_to("get_password", 1);
return;
}
/*
* Player already exists, get password
*/
static void
get_password(string pass)
{
object copy;
NOWAIT;
if(pass == "")
{
write("\n");
REMOVE;
return;
}
player=(object)KERBEROS_D->check_password_and_exec(name,pass);
if(player)
{
if((string)player->query_real_name()!="")
{
#ifdef DEBUG
write(
"exec to netdead >"+(string)player->query_real_name()+"<\n");
#endif
master()->remove_netdead(name);
player->restart_heart();
}
else
{
#ifdef DEBUG
write("execing to new player\n");
#endif
master()->add_login_count();
player->restore_player(name);
player->setup_ob();
}
REMOVE_NONEWS;
return;
}
write("\nkerberos error: failed login attempt\n");
write("\n"+ASK_NAME);
WAIT;
input_to("get_name");
return;
}
// Routines to get information from new players.
static void
new_pass(string pass)
{
NOWAIT;
if(!pass || pass == "")
{
write("\n");
REMOVE;
return;
}
if(strlen(pass) < 6)
{
write("\n\nYour password must be at least 6 characters in length.\n");
write("This is so that it is harder for others to guess it.\n");
write("\nYou may try again.\n\n");
write(ASK_PASS);
WAIT;
input_to("new_pass",1);
return;
}
temp = pass;
write("\n\nWe need to verify what you just typed in. This is so that\n");
write("if you made a mistake, you can correct it.\n");
write("\nPlease re-enter the new password for " + capitalize(name) + ": ");
WAIT;
input_to("new_pass2", 1);
return;
}
static void
new_pass2(string pass)
{
NOWAIT;
write("\n");
if(temp == pass)
{
pass = crypt(pass,0);
player=(object)KERBEROS_D->new_pass_and_exec(name, pass);
if(player)
player->setup_ob();
else
write("kerberos: refused addition and exec\n");
REMOVE_NONEWS;
return;
}
else
{
write("\nVerification failed. You better try to type in the " +
"password\n");
write("again. We'll repeat this process one more time.\n\n");
write(ASK_PASS);
WAIT;
input_to("new_pass", 1);
return;
}
}
// House cleaning functions.
void
signoff()
{
cat(NEWS + "login.signoff");
call_out("signoff_cont",1);
}
void
signoff_cont()
{
destruct(this_object());
}
// This function, in theory, would never be used. But, just in case.
void
clean_up()
{
destruct(this_object());
}
// EOF