// /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