src/player.c

Go to the documentation of this file.
00001 
00002 /*
00003  * player.c 
00004  */
00005 
00006 #include "copyright.h"
00007 #include "config.h"
00008 
00009 #include "mudconf.h"
00010 #include "config.h"
00011 #include "db.h"
00012 #include "interface.h"
00013 #include "externs.h"
00014 #include "alloc.h"
00015 #include "attrs.h"
00016 #include "powers.h"
00017 #include "command.h"
00018 
00019 #define NUM_GOOD        4                       /*
00020                                                                  * # of successful logins to save data for 
00021                                                                  */
00022 #define NUM_BAD         3                       /*
00023                                                                  * # of failed logins to save data for 
00024                                                                  */
00025 
00026 typedef struct hostdtm HOSTDTM;
00027 struct hostdtm {
00028         char *host;
00029         char *dtm;
00030 };
00031 
00032 typedef struct logindata LDATA;
00033 struct logindata {
00034         HOSTDTM good[NUM_GOOD];
00035         HOSTDTM bad[NUM_BAD];
00036         int tot_good;
00037         int tot_bad;
00038         int new_bad;
00039 };
00040 
00041 extern char *crypt(const char *, const char *);
00042 extern time_t time(time_t *);
00043 
00047 static void decrypt_logindata(char *atrbuf, LDATA * info)
00048 {
00049         int i;
00050         char *tmpc;
00051 
00052         info->tot_good = 0;
00053         info->tot_bad = 0;
00054         info->new_bad = 0;
00055         for(i = 0; i < NUM_GOOD; i++) {
00056                 info->good[i].host = NULL;
00057                 info->good[i].dtm = NULL;
00058         }
00059         for(i = 0; i < NUM_BAD; i++) {
00060                 info->bad[i].host = NULL;
00061                 info->bad[i].dtm = NULL;
00062         }
00063 
00064         if(*atrbuf == '#') {
00065                 atrbuf++;
00066                 if(!(tmpc = grabto(&atrbuf, ';')))
00067                         return;
00068                 info->tot_good = atoi(tmpc);
00069                 for(i = 0; i < NUM_GOOD; i++) {
00070                         if(!(tmpc = grabto(&atrbuf, ';')))
00071                                 return;
00072                         info->good[i].host = tmpc;
00073                         if(!(tmpc = grabto(&atrbuf, ';')))
00074                                 return;
00075                         info->good[i].dtm = tmpc;
00076                 }
00077                 if(!(tmpc = grabto(&atrbuf, ';')))
00078                         return;
00079                 info->new_bad = atoi(tmpc);
00080                 if(!(tmpc = grabto(&atrbuf, ';')))
00081                         return;
00082                 info->tot_bad = atoi(tmpc);
00083                 for(i = 0; i < NUM_BAD; i++) {
00084                         if(!(tmpc = grabto(&atrbuf, ';')))
00085                                 return;
00086                         info->bad[i].host = tmpc;
00087                         if(!(tmpc = grabto(&atrbuf, ';')))
00088                                 return;
00089                         info->bad[i].dtm = tmpc;
00090                 }
00091         }
00092 }
00093 
00097 static void encrypt_logindata(char *atrbuf, LDATA * info)
00098 {
00099         char *bp, nullc;
00100         int i;
00101 
00102         /*
00103          * Make sure the SPRINTF call tracks NUM_GOOD and NUM_BAD for the * * 
00104          * 
00105          * *  * * number of host/dtm pairs of each type. 
00106          */
00107 
00108         nullc = '\0';
00109         for(i = 0; i < NUM_GOOD; i++) {
00110                 if(!info->good[i].host)
00111                         info->good[i].host = &nullc;
00112                 if(!info->good[i].dtm)
00113                         info->good[i].dtm = &nullc;
00114         }
00115         for(i = 0; i < NUM_BAD; i++) {
00116                 if(!info->bad[i].host)
00117                         info->bad[i].host = &nullc;
00118                 if(!info->bad[i].dtm)
00119                         info->bad[i].dtm = &nullc;
00120         }
00121         bp = alloc_lbuf("encrypt_logindata");
00122         sprintf(bp, "#%d;%s;%s;%s;%s;%s;%s;%s;%s;%d;%d;%s;%s;%s;%s;%s;%s;",
00123                         info->tot_good, info->good[0].host, info->good[0].dtm,
00124                         info->good[1].host, info->good[1].dtm, info->good[2].host,
00125                         info->good[2].dtm, info->good[3].host, info->good[3].dtm,
00126                         info->new_bad, info->tot_bad, info->bad[0].host, info->bad[0].dtm,
00127                         info->bad[1].host, info->bad[1].dtm, info->bad[2].host,
00128                         info->bad[2].dtm);
00129         StringCopy(atrbuf, bp);
00130         free_lbuf(bp);
00131 }
00132 
00138 void record_login(dbref player, int isgood, char *ldate, char *lhost,
00139                                   char *lusername)
00140 {
00141         LDATA login_info;
00142         char *atrbuf;
00143         dbref aowner;
00144         int aflags, i;
00145 
00146         atrbuf = atr_get(player, A_LOGINDATA, &aowner, &aflags);
00147         decrypt_logindata(atrbuf, &login_info);
00148         if(isgood) {
00149                 if(login_info.new_bad > 0) {
00150                         notify(player, "");
00151                         notify_printf(player,
00152                                                   "**** %d failed connect%s since your last successful connect. ****",
00153                                                   login_info.new_bad,
00154                                                   (login_info.new_bad == 1 ? "" : "s"));
00155                         notify_printf(player,
00156                                                   "Most recent attempt was from %s on %s.",
00157                                                   login_info.bad[0].host, login_info.bad[0].dtm);
00158                         notify(player, "");
00159                         login_info.new_bad = 0;
00160                 }
00161                 if(login_info.good[0].host && *login_info.good[0].host &&
00162                    login_info.good[0].dtm && *login_info.good[0].dtm) {
00163                         notify_printf(player, "Last connect was from %s on %s.",
00164                                                   login_info.good[0].host, login_info.good[0].dtm);
00165                 }
00166                 if(mudconf.have_mailer)
00167                         check_mail(player, 0, 0);
00168                 for(i = NUM_GOOD - 1; i > 0; i--) {
00169                         login_info.good[i].dtm = login_info.good[i - 1].dtm;
00170                         login_info.good[i].host = login_info.good[i - 1].host;
00171                 }
00172                 login_info.good[0].dtm = ldate;
00173                 login_info.good[0].host = lhost;
00174                 login_info.tot_good++;
00175                 if(*lusername)
00176                         atr_add_raw(player, A_LASTSITE, tprintf("%s@%s", lusername,
00177                                                                                                         lhost));
00178                 else
00179                         atr_add_raw(player, A_LASTSITE, lhost);
00180         } else {
00181                 for(i = NUM_BAD - 1; i > 0; i--) {
00182                         login_info.bad[i].dtm = login_info.bad[i - 1].dtm;
00183                         login_info.bad[i].host = login_info.bad[i - 1].host;
00184                 }
00185                 login_info.bad[0].dtm = ldate;
00186                 login_info.bad[0].host = lhost;
00187                 login_info.tot_bad++;
00188                 login_info.new_bad++;
00189         }
00190         encrypt_logindata(atrbuf, &login_info);
00191         atr_add_raw(player, A_LOGINDATA, atrbuf);
00192         free_lbuf(atrbuf);
00193 }
00194 
00198 int check_pass(dbref player, const char *password)
00199 {
00200         dbref aowner;
00201         int aflags;
00202         char *target;
00203         char *hashed;
00204 
00205         target = atr_get(player, A_PASS, &aowner, &aflags);
00206         hashed = crypt(password, "XX");
00207         if(*target && strcmp(target, password) && strcmp(hashed, target)) {
00208                 free_lbuf(target);
00209                 return 0;
00210         }
00211         free_lbuf(target);
00212 
00213         /*
00214          * This is needed to prevent entering the raw encrypted password from
00215          * working. Do it better if you like, but it's needed. 
00216          *
00217          * Not really, you should just not really allow unencrypted passwords.
00218          * -Hag
00219          */
00220 
00221         if((strlen(password) == 13) && (password[0] == 'X') &&
00222            (password[1] == 'X'))
00223                 return 0;
00224 
00225         return 1;
00226 }
00227 
00231 dbref connect_player(char *name, char *password, char *host, char *username)
00232 {
00233         dbref player, aowner;
00234         int aflags;
00235         time_t tt;
00236         char *time_str, *player_last, *allowance;
00237 
00238         time(&tt);
00239         time_str = ctime(&tt);
00240         time_str[strlen(time_str) - 1] = '\0';
00241 
00242         if((player = lookup_player(NOTHING, name, 0)) == NOTHING)
00243                 return NOTHING;
00244         if(!check_pass(player, password)) {
00245                 record_login(player, 0, time_str, host, username);
00246                 return NOTHING;
00247         }
00248         time(&tt);
00249         time_str = ctime(&tt);
00250         time_str[strlen(time_str) - 1] = '\0';
00251 
00252         /*
00253          * compare to last connect see if player gets salary 
00254          */
00255         player_last = atr_get(player, A_LAST, &aowner, &aflags);
00256         if(strncmp(player_last, time_str, 10) != 0) {
00257                 allowance = atr_pget(player, A_ALLOWANCE, &aowner, &aflags);
00258                 if(*allowance == '\0')
00259                         giveto(player, mudconf.paycheck);
00260                 else
00261                         giveto(player, atoi(allowance));
00262                 free_lbuf(allowance);
00263         }
00264         atr_add_raw(player, A_LAST, time_str);
00265         free_lbuf(player_last);
00266         return player;
00267 }
00268 
00272 dbref create_player(char *name, char *password, dbref creator, int isrobot,
00273                                         int isguest)
00274 {
00275         dbref player;
00276         char *pbuf;
00277 
00278         /*
00279          * Make sure the password is OK.  Name is checked in create_obj 
00280          */
00281 
00282         pbuf = trim_spaces(password);
00283         if(!ok_password(pbuf)) {
00284                 free_lbuf(pbuf);
00285                 return NOTHING;
00286         }
00287         /*
00288          * If so, go create him 
00289          */
00290 
00291         player = create_obj(creator, TYPE_PLAYER, name, isrobot);
00292         if(player == NOTHING) {
00293                 free_lbuf(pbuf);
00294                 return NOTHING;
00295         }
00296         /*
00297          * initialize everything 
00298          */
00299         if(isguest) {
00300                 if(*mudconf.guests_channel)
00301                         do_addcom(player, player, 0, "g", mudconf.guests_channel);
00302         } else {
00303                 if(*mudconf.public_channel)
00304                         do_addcom(player, player, 0, "pub", mudconf.public_channel);
00305         }
00306 
00307         s_Pass(player, crypt(pbuf, "XX"));
00308         s_Home(player, start_home());
00309         s_Fixed(player);
00310         free_lbuf(pbuf);
00311         return player;
00312 }
00313 
00317 void do_password(dbref player, dbref cause, int key, char *oldpass,
00318                                  char *newpass)
00319 {
00320         dbref aowner;
00321         int aflags;
00322         char *target;
00323 
00324         target = atr_get(player, A_PASS, &aowner, &aflags);
00325         if(!*target || !check_pass(player, oldpass)) {
00326                 notify(player, "Sorry.");
00327         } else if(!ok_password(newpass)) {
00328                 notify(player, "Bad new password.");
00329         } else {
00330                 atr_add_raw(player, A_PASS, crypt(newpass, "XX"));
00331                 notify(player, "Password changed.");
00332         }
00333         free_lbuf(target);
00334 }
00335 
00339 static void disp_from_on(dbref player, char *dtm_str, char *host_str)
00340 {
00341         if(dtm_str && *dtm_str && host_str && *host_str) {
00342                 notify_printf(player, "     From: %s   On: %s", dtm_str, host_str);
00343         }
00344 }
00345 
00346 void do_last(dbref player, dbref cause, int key, char *who)
00347 {
00348         dbref target, aowner;
00349         LDATA login_info;
00350         char *atrbuf;
00351         int i, aflags;
00352 
00353         if(!who || !*who) {
00354                 target = Owner(player);
00355         } else if(!(string_compare(who, "me"))) {
00356                 target = Owner(player);
00357         } else {
00358                 target = lookup_player(player, who, 1);
00359         }
00360 
00361         if(target == NOTHING) {
00362                 notify(player, "I couldn't find that player.");
00363         } else if(!Controls(player, target)) {
00364                 notify(player, "Permission denied.");
00365         } else {
00366                 atrbuf = atr_get(target, A_LOGINDATA, &aowner, &aflags);
00367                 decrypt_logindata(atrbuf, &login_info);
00368 
00369                 notify_printf(player, "Total successful connects: %d",
00370                                           login_info.tot_good);
00371                 for(i = 0; i < NUM_GOOD; i++) {
00372                         disp_from_on(player, login_info.good[i].host,
00373                                                  login_info.good[i].dtm);
00374                 }
00375                 notify_printf(player, "Total failed connects: %d",
00376                                           login_info.tot_bad);
00377                 for(i = 0; i < NUM_BAD; i++) {
00378                         disp_from_on(player, login_info.bad[i].host,
00379                                                  login_info.bad[i].dtm);
00380                 }
00381                 free_lbuf(atrbuf);
00382         }
00383 }
00384 
00385 /*
00386  * add_player_name, delete_player_name, lookup_player:
00387  * Manage playername->dbref mapping
00388  */
00389 int add_player_name(dbref player, char *name)
00390 {
00391         int stat;
00392         dbref *p;
00393         char *temp, *tp;
00394 
00395         /*
00396          * Convert to all lowercase 
00397          */
00398 
00399         tp = temp = alloc_lbuf("add_player_name");
00400         safe_str(name, temp, &tp);
00401         *tp = '\0';
00402         for(tp = temp; *tp; tp++)
00403                 *tp = ToLower(*tp);
00404 
00405         p = (int *) hashfind(temp, &mudstate.player_htab);
00406         if(p) {
00407 
00408                 /*
00409                  * Entry found in the hashtable.  If a player, succeed if the
00410                  * * * numbers match (already correctly in the hash table),
00411                  * fail * * if they don't.  Fail if the name is a disallowed
00412                  * name * * (value AMBIGUOUS). 
00413                  */
00414 
00415                 if(*p == AMBIGUOUS) {
00416                         free_lbuf(temp);
00417                         return 0;
00418                 }
00419                 if(Good_obj(*p) && (Typeof(*p) == TYPE_PLAYER)) {
00420                         free_lbuf(temp);
00421                         if(*p == player) {
00422                                 return 1;
00423                         } else {
00424                                 return 0;
00425                         }
00426                 }
00427                 /*
00428                  * It's an alias (or an incorrect entry).  Clobber it 
00429                  */
00430                 free(p);
00431                 p = (dbref *) malloc(sizeof(int));
00432 
00433                 *p = player;
00434                 stat = hashrepl(temp, p, &mudstate.player_htab);
00435                 free_lbuf(temp);
00436         } else {
00437                 p = (dbref *) malloc(sizeof(int));
00438 
00439                 *p = player;
00440                 stat = hashadd(temp, p, &mudstate.player_htab);
00441                 free_lbuf(temp);
00442                 stat = (stat < 0) ? 0 : 1;
00443         }
00444         return stat;
00445 }
00446 
00447 int delete_player_name(dbref player, char *name)
00448 {
00449         dbref *p;
00450         char *temp, *tp;
00451 
00452         tp = temp = alloc_lbuf("delete_player_name");
00453         safe_str(name, temp, &tp);
00454         *tp = '\0';
00455         for(tp = temp; *tp; tp++)
00456                 *tp = ToLower(*tp);
00457 
00458         p = (int *) hashfind(temp, &mudstate.player_htab);
00459         if(!p || (*p == NOTHING) || ((player != NOTHING) && (*p != player))) {
00460                 free_lbuf(temp);
00461                 return 0;
00462         }
00463         free(p);
00464         hashdelete(temp, &mudstate.player_htab);
00465         free_lbuf(temp);
00466         return 1;
00467 }
00468 
00469 dbref lookup_player(dbref doer, char *name, int check_who)
00470 {
00471         dbref *p, thing;
00472         char *temp, *tp;
00473 
00474         if(!string_compare(name, "me"))
00475                 return doer;
00476 
00477         if(*name == NUMBER_TOKEN) {
00478                 name++;
00479                 if(!is_number(name))
00480                         return NOTHING;
00481                 thing = atoi(name);
00482                 if(!Good_obj(thing))
00483                         return NOTHING;
00484                 if(!((Typeof(thing) == TYPE_PLAYER) || God(doer)))
00485                         thing = NOTHING;
00486                 return thing;
00487         }
00488         tp = temp = alloc_lbuf("lookup_player");
00489         safe_str(name, temp, &tp);
00490         *tp = '\0';
00491         for(tp = temp; *tp; tp++)
00492                 *tp = ToLower(*tp);
00493         p = (int *) hashfind(temp, &mudstate.player_htab);
00494         free_lbuf(temp);
00495         if(!p) {
00496                 if(check_who) {
00497                         thing = find_connected_name(doer, name);
00498                         if(Dark(thing))
00499                                 thing = NOTHING;
00500                 } else
00501                         thing = NOTHING;
00502         } else if(!Good_obj(*p)) {
00503                 thing = NOTHING;
00504         } else
00505                 thing = *p;
00506 
00507         return thing;
00508 }
00509 
00510 void load_player_names(void)
00511 {
00512         dbref i, j, aowner;
00513         int aflags;
00514         char *alias;
00515 
00516         j = 0;
00517         DO_WHOLE_DB(i) {
00518                 if(Typeof(i) == TYPE_PLAYER) {
00519                         add_player_name(i, Name(i));
00520                 }
00521         }
00522         alias = alloc_lbuf("load_player_names");
00523         j = 0;
00524         DO_WHOLE_DB(i) {
00525                 if(Typeof(i) == TYPE_PLAYER) {
00526                         alias = atr_pget_str(alias, i, A_ALIAS, &aowner, &aflags);
00527                         if(*alias)
00528                                 add_player_name(i, alias);
00529                 }
00530         }
00531         free_lbuf(alias);
00532 }
00533 
00537 void badname_add(char *bad_name)
00538 {
00539         BADNAME *bp;
00540 
00541         /*
00542          * Make a new node and link it in at the top 
00543          */
00544 
00545         bp = (BADNAME *) XMALLOC(sizeof(BADNAME), "badname.struc");
00546         bp->name = XMALLOC(strlen(bad_name) + 1, "badname.name");
00547         bp->next = mudstate.badname_head;
00548         mudstate.badname_head = bp;
00549         StringCopy(bp->name, bad_name);
00550 }
00551 
00552 void badname_remove(char *bad_name)
00553 {
00554         BADNAME *bp, *backp;
00555 
00556         /*
00557          * Look for an exact match on the bad name and remove if found 
00558          */
00559 
00560         backp = NULL;
00561         for(bp = mudstate.badname_head; bp; backp = bp, bp = bp->next) {
00562                 if(!string_compare(bad_name, bp->name)) {
00563                         if(backp)
00564                                 backp->next = bp->next;
00565                         else
00566                                 mudstate.badname_head = bp->next;
00567                         XFREE(bp->name, "badname.name");
00568                         XFREE(bp, "badname.struc");
00569                         return;
00570                 }
00571         }
00572 }
00573 
00574 int badname_check(char *bad_name)
00575 {
00576         BADNAME *bp;
00577 
00578         /*
00579          * Walk the badname list, doing wildcard matching.  If we get a hit * 
00580          * 
00581          * *  * *  * * then return false.  If no matches in the list, return
00582          * true.  
00583          */
00584 
00585         for(bp = mudstate.badname_head; bp; bp = bp->next) {
00586                 if(quick_wild(bp->name, bad_name))
00587                         return 0;
00588         }
00589         return 1;
00590 }
00591 
00592 void badname_list(dbref player, const char *prefix)
00593 {
00594         BADNAME *bp;
00595         char *buff, *bufp;
00596 
00597         /*
00598          * Construct an lbuf with all the names separated by spaces 
00599          */
00600 
00601         buff = bufp = alloc_lbuf("badname_list");
00602         safe_str((char *) prefix, buff, &bufp);
00603         for(bp = mudstate.badname_head; bp; bp = bp->next) {
00604                 safe_chr(' ', buff, &bufp);
00605                 safe_str(bp->name, buff, &bufp);
00606         }
00607         *bufp = '\0';
00608 
00609         /*
00610          * Now display it 
00611          */
00612 
00613         notify(player, buff);
00614         free_lbuf(buff);
00615 }

Generated on Mon May 28 04:25:25 2007 for BattletechMUX by  doxygen 1.4.7