diff --git a/source/src/Makefile b/source/src/Makefile index 19bbfcdc..a6a2b455 100644 --- a/source/src/Makefile +++ b/source/src/Makefile @@ -30,6 +30,7 @@ CLIENT_LIBS= -L../enet/.libs -lenet -L$(USRLIB) `sdl-config --libs` -lSDL_image endif CLIENT_OBJS= \ + crypto.o \ audiomanager.o \ client.o \ clientgame.o \ @@ -56,9 +57,9 @@ CLIENT_OBJS= \ rendertext.o \ rndmap.o \ scoreboard.o \ + serverms.o \ server.o \ serverbrowser.o \ - serverms.o \ shadow.o \ sound.o \ soundlocation.o \ @@ -96,16 +97,19 @@ SERVER_LIBS= -L../enet/.libs -lenet -lz endif SERVER_OBJS= \ + crypto-standalone.o \ log-standalone.o \ protocol-standalone.o \ - server-standalone.o \ serverms-standalone.o \ + server-standalone.o \ stream-standalone.o \ tools-standalone.o \ wizard-standalone.o MASTER_OBJS= \ + crypto-standalone.o \ stream-standalone.o \ command-standalone.o \ + crypto_tools-standalone.o \ master-standalone.o ifeq ($(PLATFORM),SunOS) @@ -192,7 +196,7 @@ depend: makedepend -a -o-standalone.o -Y -I. $(subst -standalone.o,.cpp,$(filter-out $(SERVER_OBJS), $(MASTER_OBJS))) # DO NOT DELETE - +crypto.o: cube.h protos.h audiomanager.o: cube.h platform.h tools.h geom.h model.h protocol.h sound.h audiomanager.o: weapon.h entity.h world.h i18n.h command.h vote.h console.h audiomanager.o: protos.h @@ -243,7 +247,7 @@ physics.o: weapon.h entity.h world.h i18n.h command.h vote.h console.h physics.o: protos.h protocol.o: cube.h platform.h tools.h geom.h model.h protocol.h sound.h protocol.o: weapon.h entity.h world.h i18n.h command.h vote.h console.h -protocol.o: protos.h hash.h +protocol.o: protos.h rendercubes.o: cube.h platform.h tools.h geom.h model.h protocol.h sound.h rendercubes.o: weapon.h entity.h world.h i18n.h command.h vote.h console.h rendercubes.o: protos.h @@ -357,7 +361,7 @@ log-standalone.o: weapon.h entity.h world.h i18n.h command.h vote.h console.h log-standalone.o: protos.h protocol-standalone.o: cube.h platform.h tools.h geom.h model.h protocol.h protocol-standalone.o: sound.h weapon.h entity.h world.h i18n.h command.h -protocol-standalone.o: vote.h console.h protos.h hash.h +protocol-standalone.o: vote.h console.h protos.h server-standalone.o: cube.h platform.h tools.h geom.h model.h protocol.h server-standalone.o: sound.h weapon.h entity.h world.h i18n.h command.h server-standalone.o: vote.h console.h protos.h server.h servercontroller.h @@ -365,6 +369,8 @@ server-standalone.o: serverfiles.h serverevents.h serveractions.h serverchecks.h serverms-standalone.o: cube.h platform.h tools.h geom.h model.h protocol.h serverms-standalone.o: sound.h weapon.h entity.h world.h i18n.h command.h serverms-standalone.o: vote.h console.h protos.h +crypto-standalone.o: cube.h protos.h +crypto_tools-standalone.o: crypto_tools.h stream-standalone.o: cube.h platform.h tools.h geom.h model.h protocol.h stream-standalone.o: sound.h weapon.h entity.h world.h i18n.h command.h stream-standalone.o: vote.h console.h protos.h @@ -378,4 +384,4 @@ command-standalone.o: sound.h weapon.h entity.h world.h i18n.h command.h command-standalone.o: vote.h console.h protos.h master-standalone.o: cube.h platform.h tools.h geom.h model.h protocol.h master-standalone.o: sound.h weapon.h entity.h world.h i18n.h command.h -master-standalone.o: vote.h console.h protos.h +master-standalone.o: vote.h console.h protos.h crypto_tools.h diff --git a/source/src/client.cpp b/source/src/client.cpp index 4c4c98eb..8d2a2609 100644 --- a/source/src/client.cpp +++ b/source/src/client.cpp @@ -154,15 +154,17 @@ void modlanconnect() void whereami() { - conoutf("you are at (%.2f,%.2f)",player1->o.x,player1->o.y); + conoutf("you are at (%.2f,%.2f)", player1->o.x, player1->o.y); } void go_to(char *x, char *y) { - if ( player1->state != CS_EDITING ) return; - player1->newpos.x=(float)atoi(x); - player1->newpos.y=(float)atoi(y); - conoutf("you are going to (%.2f,%.2f)",(float)atoi(x),(float)atoi(y)); + if(player1->state != CS_EDITING) return; + float fx = 1.0f * atoi(x); + float fy = 1.0f * atoi(y); + player1->newpos.x = fx; + player1->newpos.y = fy; + conoutf("you are going to (%.2f; %.2f)", fx, fy); } void disconnect(int onlyclean, int async) @@ -568,6 +570,69 @@ void gets2c() // get updates from the server } } +// for AUTH: +vector authkeys; + +VARP(autoauth, 0, 1, 1); + +authkey *findauthkey(const char *desc) +{ + loopv(authkeys) if(!strcmp(authkeys[i]->desc, desc) && !strcmp(authkeys[i]->name, player1->name)) return authkeys[i]; + loopv(authkeys) if(!strcmp(authkeys[i]->desc, desc)) return authkeys[i]; + return NULL; +} + +void addauthkey(const char *name, const char *key, const char *desc) +{ + loopvrev(authkeys) if(!strcmp(authkeys[i]->desc, desc) && !strcmp(authkeys[i]->name, name)) delete authkeys.remove(i); + if(name[0] && key[0]) authkeys.add(new authkey(name, key, desc)); +} + +bool _hasauthkey(const char *name, const char *desc) +{ + if(!name[0] && !desc[0]) return authkeys.length() > 0; + loopvrev(authkeys) if(!strcmp(authkeys[i]->desc, desc) && !strcmp(authkeys[i]->name, name)) return true; + return false; +} + +void genauthkey(const char *secret) +{ + if(!secret[0]) { conoutf("you must specify a secret password"); return; } + vector privkey, pubkey; + genprivkey(secret, privkey, pubkey); + conoutf("private key: %s", privkey.getbuf()); + conoutf("public key: %s", pubkey.getbuf()); +} + +void saveauthkeys() +{ + stream *f = openfile("config/auth.cfg", "w"); + if(!f) { conoutf("failed to open config/auth.cfg for writing"); return; } + loopv(authkeys) + { + authkey *a = authkeys[i]; + f->printf("authkey \"%s\" \"%s\" \"%s\"\n", a->name, a->key, a->desc); + } + conoutf("saved authkeys to config/auth.cfg"); + delete f; +} + +bool tryauth(const char *desc) +{ + authkey *a = findauthkey(desc); + if(!a) return false; + a->lastauth = lastmillis; + addmsg(SV_AUTHTRY, "rss", a->desc, a->name); + return true; +} + +COMMANDN(authkey, addauthkey, ARG_3STR); +ICOMMANDF(hasauthkey, ARG_2EST, (char *name, char *desc) { return (_hasauthkey(name, desc) ? 1 : 0); }); +COMMAND(genauthkey, ARG_1STR); +COMMAND(saveauthkeys, ARG_NONE); +ICOMMANDF(auth, ARG_1EST, (char *desc) { return tryauth(desc); }); +// :for AUTH + // sendmap/getmap commands, should be replaced by more intuitive map downloading vector securemaps; diff --git a/source/src/clients2c.cpp b/source/src/clients2c.cpp index 7554ce17..211b984f 100644 --- a/source/src/clients2c.cpp +++ b/source/src/clients2c.cpp @@ -631,13 +631,32 @@ void parsemessages(int cn, playerent *d, ucharbuf &p) break; } - case SV_SCOPE: // FIXME remove in the next protocol change + // for AUTH: + case SV_AUTHREQ: { - getint(p); - getint(p); + extern int autoauth; + getstring(text, p); + if(autoauth && text[0] && tryauth(text)) conoutf("server requested authkey \"%s\"", text); break; } + case SV_AUTHCHAL: + { + getstring(text, p); + authkey *a = findauthkey(text); + uint id = (uint)getint(p); + getstring(text, p); + if(a && a->lastauth && lastmillis - a->lastauth < 60*1000) + { + vector buf; + answerchallenge(a->key, text, buf); + //conoutf("answering %u, challenge %s with %s", id, text, buf.getbuf()); + addmsg(SV_AUTHANS, "rsis", a->desc, id, buf.getbuf()); + } + break; + } + // :for AUTH + case SV_GIBDAMAGE: case SV_DAMAGE: { diff --git a/source/src/main.cpp b/source/src/main.cpp index 83e80eb1..beb991ef 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -990,6 +990,7 @@ int main(int argc, char **argv) firstrun = true; } execfile("config/autoexec.cfg"); + execfile("config/auth.cfg"); execute("addallfavcatmenus"); // exec here, to add all categories (including those defined in autoexec.cfg) initing = NOT_INITING; diff --git a/source/src/master.cpp b/source/src/master.cpp index 577d363a..74f1dfde 100644 --- a/source/src/master.cpp +++ b/source/src/master.cpp @@ -1,4 +1,5 @@ #include "cube.h" +#include "crypto_tools.h" #include #include @@ -7,6 +8,7 @@ #define CLIENT_TIME (3*60*1000) #define AUTH_TIME (60*1000) #define AUTH_LIMIT 100 +#define AUTH_THROTTLE 1000 #define CLIENT_LIMIT 8192 #define DUP_LIMIT 16 #define PING_TIME 3000 @@ -16,6 +18,31 @@ FILE *logfile = NULL; +// for AUTH: +struct userinfo +{ + char *name; + void *pubkey; +}; +hashtable users; + +void adduser(char *name, char *pubkey) +{ + name = newstring(name); + userinfo &u = users[name]; + u.name = name; + u.pubkey = parsepubkey(pubkey); +} +COMMAND(adduser, ARG_2STR); + +void clearusers() +{ + enumerate(users, userinfo, u, { delete[] u.name; freepubkey(u.pubkey); }); + users.clear(); +} +COMMAND(clearusers, ARG_NONE); +// :for AUTH + struct baninfo { enet_uint32 ip, mask; @@ -74,6 +101,15 @@ bool checkban(vector &bans, enet_uint32 host) return false; } +// for AUTH: +struct authreq +{ + enet_uint32 reqtime; + uint id; + void *answer; +}; +// :for AUTH + struct gameserver { ENetAddress address; @@ -124,9 +160,11 @@ struct client int inputpos, outputpos; enet_uint32 connecttime, lastinput; int servport; + enet_uint32 lastauth; // for AUTH + vector authreqs; // for AUTH bool shouldpurge; - client() : message(NULL), inputpos(0), outputpos(0), servport(-1), shouldpurge(false) {} + client() : message(NULL), inputpos(0), outputpos(0), servport(-1), lastauth(0), shouldpurge(false) {} }; vector clients; @@ -254,7 +292,7 @@ void gengbanlist() loopv(gbans) { baninfo &b = gbans[i]; - l->buf.put(cmd, printban(b, &cmd[cmdlen]) - cmd); + l->buf.put(cmd, printban(b, &cmd[cmdlen]) - cmd); l->buf.add('\n'); } if(gbanlists.length() && gbanlists.last()->equals(*l)) @@ -273,7 +311,7 @@ void gengbanlist() loopv(clients) { client &c = *clients[i]; - if(c.servport >= 0 && !c.message) + if(c.servport >= 0 && !c.message) { c.message = l; c.message->refs++; @@ -417,6 +455,94 @@ void messagebuf::purge() } } +// for AUTH: +void purgeauths(client &c) +{ + int expired = 0; + loopv(c.authreqs) + { + if(ENET_TIME_DIFFERENCE(servtime, c.authreqs[i].reqtime) >= AUTH_TIME) + { + outputf(c, "failauth %u\n", c.authreqs[i].id); + freechallenge(c.authreqs[i].answer); + expired = i + 1; + } + else break; + } + if(expired > 0) c.authreqs.remove(0, expired); +} + +void reqauth(client &c, uint id, char *name) +{ + if(ENET_TIME_DIFFERENCE(servtime, c.lastauth) < AUTH_THROTTLE) + return; + + c.lastauth = servtime; + + purgeauths(c); + + time_t t = time(NULL); + char *ct = ctime(&t); + if(ct) + { + char *newline = strchr(ct, '\n'); + if(newline) *newline = '\0'; + } + string ip; + if(enet_address_get_host_ip(&c.address, ip, sizeof(ip)) < 0) copystring(ip, "-"); + conoutf("%s: attempting \"%s\" as %u from %s", ct ? ct : "-", name, id, ip); + + userinfo *u = users.access(name); + if(!u) + { + outputf(c, "failauth %u\n", id); + return; + } + + if(c.authreqs.length() >= AUTH_LIMIT) + { + outputf(c, "failauth %u\n", c.authreqs[0].id); + freechallenge(c.authreqs[0].answer); + c.authreqs.remove(0); + } + + authreq &a = c.authreqs.add(); + a.reqtime = servtime; + a.id = id; + uint seed[3] = { starttime, servtime, randomMT() }; + static vector buf; + buf.setsize(0); + a.answer = genchallenge(u->pubkey, seed, sizeof(seed), buf); + + outputf(c, "chalauth %u %s\n", id, buf.getbuf()); +} + +void confauth(client &c, uint id, const char *val) +{ + purgeauths(c); + + loopv(c.authreqs) if(c.authreqs[i].id == id) + { + string ip; + if(enet_address_get_host_ip(&c.address, ip, sizeof(ip)) < 0) copystring(ip, "-"); + if(checkchallenge(val, c.authreqs[i].answer)) + { + outputf(c, "succauth %u\n", id); + conoutf("succeeded %u from %s", id, ip); + } + else + { + outputf(c, "failauth %u\n", id); + conoutf("failed %u from %s", id, ip); + } + freechallenge(c.authreqs[i].answer); + c.authreqs.remove(i--); + return; + } + outputf(c, "failauth %u\n", id); +} +// :for AUTH + bool checkclientinput(client &c) { if(c.inputpos<0) return true; @@ -426,6 +552,9 @@ bool checkclientinput(client &c) *end++ = '\0'; c.lastinput = servtime; + uint id; // for AUTH + string user, val; // for AUTH + int port; if(!strncmp(c.input, "list", 4) && (!c.input[4] || isspace(c.input[4]))) { @@ -448,6 +577,16 @@ bool checkclientinput(client &c) addgameserver(c); } } + // for AUTH: + else if(sscanf(c.input, "reqauth %u %100s", &id, user) == 2) + { + reqauth(c, id, user); + } + else if(sscanf(c.input, "confauth %u %100s", &id, val) == 2) + { + confauth(c, id, val); + } + // :for AUTH c.inputpos = &c.input[c.inputpos] - end; memmove(c.input, end, c.inputpos); @@ -518,9 +657,9 @@ void checkclients() { if(c.output.length()) c.output.setsize(0); else - { + { c.message->purge(); - c.message = NULL; + c.message = NULL; } c.outputpos = 0; if(!c.message && c.output.empty() && c.shouldpurge) diff --git a/source/src/protocol.cpp b/source/src/protocol.cpp index ddf4af12..a9ae015e 100644 --- a/source/src/protocol.cpp +++ b/source/src/protocol.cpp @@ -1,7 +1,6 @@ // misc useful functions used by the server #include "cube.h" -#include "hash.h" #ifdef _DEBUG bool protocoldbg = false; @@ -320,7 +319,7 @@ static const int msgsizes[] = // size inclusive message token, 0 f { SV_SERVINFO, 5, SV_WELCOME, 2, SV_INITCLIENT, 0, SV_POS, 0, SV_POSC, 0, SV_POSN, 0, SV_TEXT, 0, SV_TEAMTEXT, 0, SV_TEXTME, 0, SV_TEAMTEXTME, 0, SV_SOUND, 2, SV_VOICECOM, 2, SV_VOICECOMTEAM, 2, SV_CDIS, 2, - SV_SHOOT, 0, SV_EXPLODE, 0, SV_SUICIDE, 1, SV_AKIMBO, 2, SV_RELOAD, 3, SV_SCOPE, 3, + SV_SHOOT, 0, SV_EXPLODE, 0, SV_SUICIDE, 1, SV_AKIMBO, 2, SV_RELOAD, 3, SV_AUTHREQ, 0, SV_AUTHTRY, 0, SV_AUTHANS, 0, SV_AUTHCHAL, 0, SV_GIBDIED, 5, SV_DIED, 5, SV_GIBDAMAGE, 6, SV_DAMAGE, 6, SV_HITPUSH, 6, SV_SHOTFX, 6, SV_THROWNADE, 8, SV_TRYSPAWN, 1, SV_SPAWNSTATE, 23, SV_SPAWN, 3, SV_SPAWNDENY, 2, SV_FORCEDEATH, 2, SV_RESUME, 0, SV_DISCSCORES, 0, SV_TIMEUP, 2, SV_EDITENT, 10, SV_ITEMACC, 2, @@ -355,14 +354,3 @@ int msgsizelookup(int msg) return msg >= 0 && msg < SV_NUM ? sizetable[msg] : -1; } -const char *genpwdhash(const char *name, const char *pwd, int salt) -{ - static string temp; - formatstring(temp)("%s %d %s %s %d", pwd, salt, name, pwd, abs(PROTOCOL_VERSION)); - tiger::hashval hash; - tiger::hash((uchar *)temp, (int)strlen(temp), hash); - formatstring(temp)("%llx %llx %llx", hash.chunks[0], hash.chunks[1], hash.chunks[2]); - return temp; -} - - diff --git a/source/src/protocol.h b/source/src/protocol.h index 9461a855..316baa7b 100644 --- a/source/src/protocol.h +++ b/source/src/protocol.h @@ -5,7 +5,7 @@ #define CUBE_SERVINFO_PORT_LAN 28762 #define CUBE_SERVINFO_PORT(serverport) (serverport+1) #define CUBE_SERVINFO_TO_SERV_PORT(servinfoport) (servinfoport-1) -#define PROTOCOL_VERSION 1130 // bump when protocol changes (use negative numbers for mods!) +#define PROTOCOL_VERSION 1131 // bump when protocol changes (use negative numbers for mods!) #define DEMO_VERSION 2 // bump when demo format changes #define DEMO_MAGIC "ASSAULTCUBE_DEMO" #define DEMO_MINTIME 10000 // don't keep demo recordings with less than 10 seconds @@ -20,7 +20,7 @@ enum { SV_SERVINFO = 0, SV_WELCOME, SV_INITCLIENT, SV_POS, SV_POSC, SV_POSN, SV_TEXT, SV_TEAMTEXT, SV_TEXTME, SV_TEAMTEXTME, SV_SOUND, SV_VOICECOM, SV_VOICECOMTEAM, SV_CDIS, - SV_SHOOT, SV_EXPLODE, SV_SUICIDE, SV_AKIMBO, SV_RELOAD, SV_SCOPE, // FIXME remove SV_SCOPE in the next protocol change + SV_SHOOT, SV_EXPLODE, SV_SUICIDE, SV_AKIMBO, SV_RELOAD, SV_AUTHREQ, SV_AUTHTRY, SV_AUTHANS, SV_AUTHCHAL, SV_GIBDIED, SV_DIED, SV_GIBDAMAGE, SV_DAMAGE, SV_HITPUSH, SV_SHOTFX, SV_THROWNADE, SV_TRYSPAWN, SV_SPAWNSTATE, SV_SPAWN, SV_SPAWNDENY, SV_FORCEDEATH, SV_RESUME, SV_DISCSCORES, SV_TIMEUP, SV_EDITENT, SV_ITEMACC, diff --git a/source/src/protos.h b/source/src/protos.h index 44cd3298..f7bd524a 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -32,6 +32,25 @@ struct color color(float r, float g, float b, float a) : r(r), g(g), b(b), alpha(a) {} }; +struct authkey // for AUTH +{ + char *name, *key, *desc; + int lastauth; + + authkey(const char *name, const char *key, const char *desc) + : name(newstring(name)), key(newstring(key)), desc(newstring(desc)), + lastauth(0) + { + } + + ~authkey() + { + DELETEA(name); + DELETEA(key); + DELETEA(desc); + } +}; + // console extern void keypress(int code, bool isdown, int cooked, SDLMod mod = KMOD_NONE); extern int rendercommand(int x, int y, int w); @@ -330,6 +349,14 @@ extern bool securemapcheck(const char *map, bool msg = true); extern void sendintro(); extern void getdemo(char *idx, char *dsp); extern void listdemos(); +// for AUTH: +extern bool tryauth(const char *desc); +extern authkey *findauthkey(const char *desc); + +// serverms +bool requestmasterf(const char *fmt, ...); // for AUTH et al +//moving to server.cpp seems a bad idea. +// :for AUTH // clientgame extern flaginfo flaginfos[2]; @@ -669,6 +696,17 @@ extern void scrolldoc(int i); extern int stringsort(const char **a, const char **b); #endif +// crypto // for AUTH +extern void genprivkey(const char *seed, vector &privstr, vector &pubstr); +extern bool hashstring(const char *str, char *result, int maxlen); +const char *genpwdhash(const char *name, const char *pwd, int salt); +extern void answerchallenge(const char *privstr, const char *challenge, vector &answerstr); +extern void *parsepubkey(const char *pubstr); +extern void freepubkey(void *pubkey); +extern void *genchallenge(void *pubkey, const void *seed, int seedlen, vector &challengestr); +extern void freechallenge(void *answer); +extern bool checkchallenge(const char *answerstr, void *correct); + // console extern void conoutf(const char *s, ...); diff --git a/source/src/server.cpp b/source/src/server.cpp index 3f4cfbb3..7971a54f 100644 --- a/source/src/server.cpp +++ b/source/src/server.cpp @@ -2092,6 +2092,7 @@ void callvotepacket (int cn, voteinfo *v = curvote) sendpacket(cn, 1, q.finalize()); } +// TODO: use AUTH code void changeclientrole(int client, int role, char *pwd, bool force) { pwddetail pd; @@ -2171,6 +2172,66 @@ void disconnect_client(int n, int reason) if(*scoresaved && mastermode == MM_MATCH) senddisconnectedscores(-1); } +// for AUTH: +client *findauth(uint id) +{ + loopv(clients) if(clients[i]->authreq == id) return clients[i]; + return NULL; +} + +void authfailed(uint id) +{ + client *cl = findauth(id); + if(!cl) return; + cl->authreq = 0; +} + +void authsucceeded(uint id) +{ + client *cl = findauth(id); + if(!cl) return; + cl->authreq = 0; + //setmaster(cl, true, "", ci->authname);//TODO? compare to sauerbraten +} + +void authchallenged(uint id, const char *val) +{ + client *cl = findauth(id); + if(!cl) return; + sendf(cl->clientnum, 1, "risis", SV_AUTHCHAL, "", id, val); +} + +uint nextauthreq = 0; + +void tryauth(client *cl, const char *user) +{ + extern bool requestmasterf(const char *fmt, ...); + if(!nextauthreq) nextauthreq = 1; + cl->authreq = nextauthreq++; + filtertext(cl->authname, user, false, 100); + if(!requestmasterf("reqauth %u %s\n", cl->authreq, cl->authname)) + { + cl->authreq = 0; + sendf(cl->clientnum, 1, "ris", SV_SERVMSG, "not connected to authentication server"); + } +} + +void answerchallenge(client *cl, uint id, char *val) +{ + if(cl->authreq != id) return; + extern bool requestmasterf(const char *fmt, ...); + for(char *s = val; *s; s++) + { + if(!isxdigit(*s)) { *s = '\0'; break; } + } + if(!requestmasterf("confauth %u %s\n", id, val)) + { + cl->authreq = 0; + sendf(cl->clientnum, 1, "ris", SV_SERVMSG, "not connected to authentication server"); + } +} +// :for AUTH + void sendwhois(int sender, int cn) { if( !valid_client(sender) ) return; @@ -2846,11 +2907,27 @@ void process(ENetPacket *packet, int sender, int chan) break; } - case SV_SCOPE: // FIXME remove in the next protocol change + // for AUTH: + case SV_AUTHTRY: { + string desc, name; + getstring(desc, p, sizeof(desc)); // unused for now + getstring(name, p, sizeof(name)); + if(!desc[0]) tryauth(cl, name); break; } + case SV_AUTHANS: + { + string desc, ans; + getstring(desc, p, sizeof(desc)); // unused for now + uint id = (uint)getint(p); + getstring(ans, p, sizeof(ans)); + if(!desc[0]) answerchallenge(cl, id, ans); + break; + } + // :for AUTH + case SV_PING: sendf(sender, 1, "ii", SV_PONG, getint(p)); break; @@ -3748,11 +3825,13 @@ void localconnect() void processmasterinput(const char *cmd, int cmdlen, const char *args) { + uint id; string val; - if(!strncmp(cmd, "cleargbans", cmdlen)) - cleargbans(); - else if(sscanf(cmd, "addgban %s", val) == 1) - addgban(val); + if(sscanf(cmd, "failauth %u", &id) == 1) authfailed(id); + else if(sscanf(cmd, "succauth %u", &id) == 1) authsucceeded(id); + else if(sscanf(cmd, "chalauth %u %s", &id, val) == 2) authchallenged(id, val); + else if(!strncmp(cmd, "cleargbans", cmdlen)) cleargbans(); + else if(sscanf(cmd, "addgban %s", val) == 1) addgban(val); } string server_name = "unarmed server"; diff --git a/source/src/server.h b/source/src/server.h index ba83e623..0fe26407 100644 --- a/source/src/server.h +++ b/source/src/server.h @@ -255,6 +255,8 @@ struct client // server side version of "dynent" type int spawnperm, spawnpermsent; int salt; string pwd; + uint authreq; // for AUTH + string authname; // for AUTH int mapcollisions, farpickups; enet_uint32 bottomRTT; medals md; @@ -329,6 +331,7 @@ struct client // server side version of "dynent" type saychars = 0; spawnindex = -1; spectcn = FPCN_VOID; + authreq = 0; // for AUTH mapchange(); freshgame = false; // don't spawn into running games mute = spam = lastvc = badspeech = badmillis = nvotes = 0; @@ -400,7 +403,7 @@ const char *messagenames[SV_NUM] = { "SV_SERVINFO", "SV_WELCOME", "SV_INITCLIENT", "SV_POS", "SV_POSC", "SV_POSN", "SV_TEXT", "SV_TEAMTEXT", "SV_TEXTME", "SV_TEAMTEXTME", "SV_SOUND", "SV_VOICECOM", "SV_VOICECOMTEAM", "SV_CDIS", - "SV_SHOOT", "SV_EXPLODE", "SV_SUICIDE", "SV_AKIMBO", "SV_RELOAD", "SV_SCOPE", + "SV_SHOOT", "SV_EXPLODE", "SV_SUICIDE", "SV_AKIMBO", "SV_RELOAD", "SV_AUTHREQ", "SV_AUTHTRY", "SV_AUTHANS", "SV_AUTHCHAL", "SV_GIBDIED", "SV_DIED", "SV_GIBDAMAGE", "SV_DAMAGE", "SV_HITPUSH", "SV_SHOTFX", "SV_THROWNADE", "SV_TRYSPAWN", "SV_SPAWNSTATE", "SV_SPAWN", "SV_SPAWNDENY", "SV_FORCEDEATH", "SV_RESUME", "SV_DISCSCORES", "SV_TIMEUP", "SV_EDITENT", "SV_ITEMACC", @@ -425,9 +428,9 @@ const char *messagenames[SV_NUM] = const char *entnames[MAXENTTYPES] = { - "none?", + "none?", "light", "playerstart", "pistol", "ammobox","grenades", - "health", "helmet", "armour", "akimbo", + "health", "helmet", "armour", "akimbo", "mapmodel", "trigger", "ladder", "ctf-flag", "sound", "clip", "plclip" }; diff --git a/source/src/serverevents.h b/source/src/serverevents.h index 98b01e7b..ac74895c 100644 --- a/source/src/serverevents.h +++ b/source/src/serverevents.h @@ -94,7 +94,6 @@ void processevent(client *c, scopeevent &e) // FIXME remove in the next protocol clientstate &gs = c->state; if(!gs.isalive(gamemillis)/* || e.gun!=GUN_SNIPER*/) return; // currently we check the gun on the client-side only gs.scoped = e.scoped; - sendf(-1, 1, "ri3", SV_SCOPE, c->clientnum, gs.scoped); } void processevent(client *c, reloadevent &e) @@ -114,15 +113,6 @@ void processevent(client *c, reloadevent &e) gs.ammo[e.gun] -= numbullets; int wait = e.millis - gs.lastshot; - /* - // actually the clients sends this by itself, but sanity checks should be made!! - // does this state get reset on spawn etc? - if(gs.scoped) // the state of this needs to be verified in a number of places! (flowtron:2010jul05) - { - gs.scoped = false; - sendf(-1, 1, "ri3", SV_SCOPE, c->clientnum, gs.scoped); - } - */ sendf(-1, 1, "ri3", SV_RELOAD, c->clientnum, e.gun); if(gs.gunwait[e.gun] && wait