tHTTP and SOCKS authentication improved; now also works for servers and AI players - vaccinewars - be a doctor and try to vaccinate the world (HTM) git clone git://src.adamsgaard.dk/vaccinewars (DIR) Log (DIR) Files (DIR) Refs (DIR) README (DIR) LICENSE --- (DIR) commit bc1834ece535f81b294b3e9167728116ef3d4bf7 (DIR) parent d6e0ec90931c5375b3157cfbb9e4bb42c8cf13f6 (HTM) Author: Ben Webb <ben@salilab.org> Date: Tue, 16 Oct 2001 16:44:30 +0000 HTTP and SOCKS authentication improved; now also works for servers and AI players Diffstat: M doc/configfile.html | 32 +++++++++++++++++++++++++++++-- M src/AIPlayer.c | 19 ++++++++++++++----- M src/curses_client.c | 48 +++++++++++++++---------------- M src/dopewars.c | 33 +++++++++++++++++++++++++++---- M src/dopewars.h | 1 + M src/gtk_client.c | 56 +++++++++---------------------- M src/network.c | 49 ++++++++++++++++--------------- M src/network.h | 27 ++++++++++++++------------- M src/serverside.c | 43 +++++++++++++++++++++++++++++-- 9 files changed, 193 insertions(+), 115 deletions(-) --- (DIR) diff --git a/doc/configfile.html b/doc/configfile.html t@@ -120,6 +120,16 @@ be <i>"socks"</i>. <dd>Uses SOCKS version <i>4</i>. Version 5 is also supported; SOCKS5 servers support username/password authentication, unlike SOCKS4. +<dt><b>Socks.Auth.User=<i>""</i></b></a> +<dd>If using SOCKS5 with user/password authentication, with the server or AI +player (which can both run unattended) then setting this variable to something +other than "" will enable them to authenticate themselves with the SOCKS +server, provided Socks.Auth.Password is also set. (The game clients prompt +the user for a username and password on each connect instead.) + +<dt><b>Socks.Auth.Password=<i>""</i></b></a> +<dd>The corresponding password for Socks.Auth.User, above. + <dt><a name="HiScoreFile"><b>HiScoreFile=<i>"/var/lib/dopewars.sco"</i></b></a> <dd>Tells the dopewars server (or the client, if running in single-player mode, not connected to a server) to use the file <i>/var/lib/dopewars.sco</i> t@@ -152,7 +162,7 @@ This setting, if set to TRUE, can be overridden by the -S about connecting to the dopewars metaserver via. a proxy web server. <dt><b>MetaServer.Port=<i>80</i></b> -<dd>Instructs dopewarsclient that the metaserver can be found on TCP port +<dd>Instructs dopewars that the metaserver can be found on TCP port <i>80</i>. This is the standard HTTP port for Web access. (You shouldn't need to change this, even if you connect via. a proxy.) t@@ -195,6 +205,24 @@ hostname (see MetaServer.LocalName above) with the metaserver. <dd>Even if "Socks.Active" is TRUE, do not use SOCKS for metaserver communication - connect directly to the metaserver or proxy. +<dt><b>MetaServer.Auth.User=<i>""</i></b></a> +<dd>If the metaserver webpage is on a restricted access server (i.e. it +requires HTTP Basic authentication), and you wish to connect with the server +or AI player (which can both run unattended) then setting this variable to +something other than "" will enable them to authenticate themselves, +provided MetaServer.Auth.Password is also set. (The game clients prompt +the user for a username and password on each connect instead.) + +<dt><b>MetaServer.Auth.Password=<i>""</i></b></a> +<dd>The corresponding password for MetaServer.Auth.User, above. + +<dt><b>MetaServer.Proxy.User=<i>""</i></b></a> +<dd>In a similar way to MetaServer.Auth.User, above, this enables a dopewars +server or AI player to authenticate itself with a web proxy. + +<dt><b>MetaServer.Proxy.Password=<i>""</i></b></a> +<dd>The corresponding password for MetaServer.Proxy.User, above. + </dl> <h2><a name="places">Basic configuration: places in the game</a></h2> t@@ -542,6 +570,6 @@ any drugs, and clients will display this information if available. <ul> <li><a href="index.html">Main index</a> </ul> -<p>Last update: <b>23-09-2001</b></p> +<p>Last update: <b>16-10-2001</b></p> </body> </html> (DIR) diff --git a/src/AIPlayer.c b/src/AIPlayer.c t@@ -110,6 +110,12 @@ static void DisplayConnectStatus(NetworkBuffer *netbuf,NBStatus oldstatus, } } +static void NetBufAuth(NetworkBuffer *netbuf,gpointer data) { + g_print(_("Using Socks.Auth.User and Socks.Auth.Password " + "for SOCKS5 authentication\n")); + SendSocks5UserPasswd(netbuf,Socks.authuser,Socks.authpassword); +} + void AIPlayerLoop() { /* Main loop for AI players. Connects to server, plays game, */ /* and then disconnects. */ t@@ -138,10 +144,13 @@ void AIPlayerLoop() { if (!StartNetworkBufferConnect(netbuf,ServerName,Port)) { AIConnectFailed(netbuf); return; - } else if (netbuf->status==NBS_CONNECTED) { - AIStartGame(AIPlay); } else { - DisplayConnectStatus(netbuf,oldstatus,oldsocks); + SetNetworkBufferUserPasswdFunc(netbuf,NetBufAuth,NULL); + if (netbuf->status==NBS_CONNECTED) { + AIStartGame(AIPlay); + } else { + DisplayConnectStatus(netbuf,oldstatus,oldsocks); + } } while (1) { t@@ -301,12 +310,12 @@ int HandleAIMessage(char *Message,Player *AIPlay) { } break; case C_SUBWAYFLASH: + dpg_print(_("Jetting to %tde with %P cash and %P debt\n"), + Location[(int)AIPlay->IsAt].Name,AIPlay->Cash,AIPlay->Debt); /* Use bselect rather than sleep, as this is portable to Win32 */ tv.tv_sec=AITurnPause; tv.tv_usec=0; bselect(0,NULL,NULL,NULL,&tv); - dpg_print(_("Jetting to %tde with %P cash and %P debt\n"), - Location[(int)AIPlay->IsAt].Name,AIPlay->Cash,AIPlay->Debt); if (brandom(0,100)<10) AISendRandomMessage(AIPlay); break; case C_UPDATE: (DIR) diff --git a/src/curses_client.c b/src/curses_client.c t@@ -231,7 +231,7 @@ static gboolean SelectServerFromMetaServer(Player *Play,GString *errstr) { gint index; fd_set readfds,writefds; int maxsock; - gboolean DoneOK,authOK; + gboolean DoneOK; HttpConnection *MetaConn; attrset(TextAttr); t@@ -240,8 +240,8 @@ static gboolean SelectServerFromMetaServer(Player *Play,GString *errstr) { refresh(); if (OpenMetaHttpConnection(&MetaConn)) { - SetHttpAuthFunc(MetaConn,HttpAuthFunc,&authOK); - SetNetworkBufferUserPasswdFunc(&MetaConn->NetBuf,SocksAuthFunc,&authOK); + SetHttpAuthFunc(MetaConn,HttpAuthFunc,NULL); + SetNetworkBufferUserPasswdFunc(&MetaConn->NetBuf,SocksAuthFunc,NULL); } else { g_string_assign_error(errstr,MetaConn->NetBuf.error); CloseHttpConnection(MetaConn); t@@ -266,11 +266,10 @@ static gboolean SelectServerFromMetaServer(Player *Play,GString *errstr) { if (c=='\f') wrefresh(curscr); #endif } - authOK=TRUE; /* Gets set to FALSE if authentication fails */ if (RespondToSelect(&MetaConn->NetBuf,&readfds,&writefds,NULL,&DoneOK)) { while (HandleWaitingMetaServerData(MetaConn,&ServerList,&DoneOK)) {} } - if ((!DoneOK || !authOK) && HandleHttpCompletion(MetaConn)) { + if (!DoneOK && HandleHttpCompletion(MetaConn)) { if (IsHttpError(MetaConn)) { g_string_assign_error(errstr,MetaConn->NetBuf.error); CloseHttpConnection(MetaConn); t@@ -381,10 +380,7 @@ static void DisplayConnectStatus(NetworkBuffer *netbuf, void HttpAuthFunc(HttpConnection *conn,gboolean proxyauth, gchar *realm,gpointer data) { - gchar *text,*user,*password; - gboolean *authOK; - - authOK = (gboolean *)data; + gchar *text,*user,*password=NULL; attrset(TextAttr); clear_bottom(); t@@ -395,29 +391,32 @@ void HttpAuthFunc(HttpConnection *conn,gboolean proxyauth, text = g_strdup_printf(_("Authentication required for realm %s"),realm); } mvaddstr(17,1,text); + mvaddstr(18,1,_("(Enter a blank username to cancel)")); g_free(text); - user=nice_input(_("User name: "),18,1,FALSE,NULL,'\0'); - password=nice_input(_("Password: "),19,1,FALSE,NULL,'*'); + user=nice_input(_("User name: "),19,1,FALSE,NULL,'\0'); + if (user && user[0]) { + password=nice_input(_("Password: "),20,1,FALSE,NULL,'*'); + } - *authOK = SetHttpAuthentication(conn,proxyauth,user,password); + SetHttpAuthentication(conn,proxyauth,user,password); g_free(user); g_free(password); } void SocksAuthFunc(NetworkBuffer *netbuf,gpointer data) { - gchar *user,*password; - gboolean *authOK; - - authOK = (gboolean *)data; + gchar *user,*password=NULL; attrset(TextAttr); clear_bottom(); - mvaddstr(17,1,_("SOCKS authentication required")); + mvaddstr(17,1, + _("SOCKS authentication required (enter a blank username to cancel)")); user=nice_input(_("User name: "),18,1,FALSE,NULL,'\0'); - password=nice_input(_("Password: "),19,1,FALSE,NULL,'*'); + if (user && user[0]) { + password=nice_input(_("Password: "),19,1,FALSE,NULL,'*'); + } - *authOK = SendSocks5UserPasswd(netbuf,user,password); + SendSocks5UserPasswd(netbuf,user,password); g_free(user); g_free(password); } t@@ -425,7 +424,7 @@ static gboolean DoConnect(Player *Play,GString *errstr) { NetworkBuffer *netbuf; fd_set readfds,writefds; int maxsock,c; - gboolean doneOK=TRUE,authOK=TRUE; + gboolean doneOK=TRUE; NBStatus oldstatus; NBSocksStatus oldsocks; t@@ -436,7 +435,7 @@ static gboolean DoConnect(Player *Play,GString *errstr) { if (!StartNetworkBufferConnect(netbuf,ServerName,Port)) { doneOK=FALSE; } else { - SetNetworkBufferUserPasswdFunc(netbuf,SocksAuthFunc,&authOK); + SetNetworkBufferUserPasswdFunc(netbuf,SocksAuthFunc,NULL); if (netbuf->status!=NBS_CONNECTED) { DisplayConnectStatus(netbuf,oldstatus,oldsocks); do { t@@ -456,16 +455,15 @@ static gboolean DoConnect(Player *Play,GString *errstr) { } oldstatus = netbuf->status; oldsocks = netbuf->sockstat; - authOK=TRUE; RespondToSelect(netbuf,&readfds,&writefds,NULL,&doneOK); if (netbuf->status==NBS_CONNECTED) break; DisplayConnectStatus(netbuf,oldstatus,oldsocks); - } while (doneOK && authOK); + } while (doneOK); } } - if (!doneOK || !authOK) g_string_assign_error(errstr,netbuf->error); - return (doneOK && authOK); + if (!doneOK) g_string_assign_error(errstr,netbuf->error); + return doneOK; } static gboolean ConnectToServer(Player *Play) { (DIR) diff --git a/src/dopewars.c b/src/dopewars.c t@@ -160,14 +160,14 @@ struct BITCH Bitch = { #ifdef NETWORKING struct METASERVER MetaServer = { FALSE,NULL,0,NULL,0,NULL,NULL,NULL, - NULL,FALSE }; + NULL,FALSE,NULL,NULL,NULL,NULL }; struct METASERVER DefaultMetaServer = { TRUE,"dopewars.sourceforge.net",80,"",8080,"/metaserver.php", - "","","dopewars server", FALSE + "","","dopewars server", FALSE, "", "", "", "" }; -SocksServer Socks = { NULL,0,0,FALSE,NULL }; +SocksServer Socks = { NULL,0,0,FALSE,NULL,NULL,NULL }; gboolean UseSocks; #endif t@@ -209,6 +209,12 @@ struct GLOBALS Globals[] = { { &Socks.version,NULL,NULL,NULL,NULL,"Socks.Version", N_("The version of the SOCKS protocol to use (4 or 5)"), NULL,NULL,0,"",NULL,NULL }, + { NULL,NULL,NULL,&Socks.authuser,NULL,"Socks.Auth.User", + N_("Username for SOCKS5 authentication"), + NULL,NULL,0,"",NULL,NULL }, + { NULL,NULL,NULL,&Socks.authpassword,NULL,"Socks.Auth.Password", + N_("Password for SOCKS5 authentication"), + NULL,NULL,0,"",NULL,NULL }, { NULL,&MetaServer.Active,NULL,NULL,NULL,"MetaServer.Active", N_("TRUE if server should report to a metaserver"), NULL,NULL,0,"",NULL,NULL }, t@@ -238,6 +244,19 @@ struct GLOBALS Globals[] = { { NULL,&MetaServer.UseSocks,NULL,NULL,NULL,"MetaServer.UseSocks", N_("If TRUE, use SOCKS for metaserver communication"), NULL,NULL,0,"",NULL,NULL }, + { NULL,NULL,NULL,&MetaServer.authuser,NULL,"MetaServer.Auth.User", + N_("Username for HTTP Basic authentication"), + NULL,NULL,0,"",NULL,NULL }, + { NULL,NULL,NULL,&MetaServer.authpassword,NULL,"MetaServer.Auth.Password", + N_("Password for HTTP Basic authentication"), + NULL,NULL,0,"",NULL,NULL }, + { NULL,NULL,NULL,&MetaServer.proxyuser,NULL,"MetaServer.Proxy.User", + N_("Username for HTTP Basic proxy authentication"), + NULL,NULL,0,"",NULL,NULL }, + { NULL,NULL,NULL,&MetaServer.proxypassword,NULL, + "MetaServer.Proxy.Password", + N_("Password for HTTP Basic proxy authentication"), + NULL,NULL,0,"",NULL,NULL }, #endif { NULL,NULL,NULL,&Pager,NULL,"Pager", N_("Program used to display multi-page output"),NULL,NULL,0,"",NULL,NULL }, t@@ -1264,6 +1283,10 @@ void CopyMetaServer(struct METASERVER *dest,struct METASERVER *src) { AssignName(&dest->LocalName,src->LocalName); AssignName(&dest->Password,src->Password); AssignName(&dest->Comment,src->Comment); + AssignName(&dest->authuser,src->authuser); + AssignName(&dest->authpassword,src->authpassword); + AssignName(&dest->proxyuser,src->proxyuser); + AssignName(&dest->proxypassword,src->proxypassword); } #endif t@@ -1726,8 +1749,10 @@ void SetupParameters() { AssignName(&Socks.name,"socks"); Socks.port = 1080; Socks.version = 4; - Socks.user = NULL; + Socks.user = g_strdup(""); Socks.numuid = FALSE; + Socks.authuser = g_strdup(""); + Socks.authpassword = g_strdup(""); UseSocks = FALSE; #endif (DIR) diff --git a/src/dopewars.h b/src/dopewars.h t@@ -86,6 +86,7 @@ struct METASERVER { unsigned ProxyPort; gchar *Path,*LocalName,*Password,*Comment; gboolean UseSocks; + gchar *authuser,*authpassword,*proxyuser,*proxypassword; }; #endif (DIR) diff --git a/src/gtk_client.c b/src/gtk_client.c t@@ -107,9 +107,10 @@ static void MetaSocksAuthDialog(NetworkBuffer *netbuf,gpointer data); static void SocksAuthDialog(NetworkBuffer *netbuf,gpointer data); static void GetClientMessage(gpointer data,gint socket, GdkInputCondition condition); -static void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write); +static void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write, + gboolean CallNow); static void MetaSocketStatus(NetworkBuffer *NetBuf,gboolean Read, - gboolean Write); + gboolean Write,gboolean CallNow); static void FinishServerConnect(struct StartGameStruct *widgets, gboolean ConnectOK); t@@ -330,7 +331,8 @@ void GetClientMessage(gpointer data,gint socket, } } -void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { +void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write, + gboolean CallNow) { if (NetBuf->InputTag) gdk_input_remove(NetBuf->InputTag); NetBuf->InputTag=0; if (Read || Write) { t@@ -339,6 +341,7 @@ void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { (Write ? GDK_INPUT_WRITE : 0), GetClientMessage,NetBuf->CallBackData); } + if (CallNow) GetClientMessage(NetBuf->CallBackData,NetBuf->fd,0); } #endif /* NETWORKING */ t@@ -2030,7 +2033,7 @@ static void DoConnect(struct StartGameStruct *widgets) { oldsocks = NetBuf->sockstat; if (StartNetworkBufferConnect(NetBuf,ServerName,Port)) { DisplayConnectStatus(widgets,FALSE,oldstatus,oldsocks); - SetNetworkBufferUserPasswdFunc(NetBuf,SocksAuthDialog,(gpointer)widgets); + SetNetworkBufferUserPasswdFunc(NetBuf,SocksAuthDialog,NULL); SetNetworkBufferCallBack(NetBuf,SocketStatus,(gpointer)widgets); } else { ConnectError(widgets,FALSE); t@@ -2175,7 +2178,8 @@ static void HandleMetaSock(gpointer data,gint socket, } } -void MetaSocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { +void MetaSocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write, + gboolean CallNow) { if (NetBuf->InputTag) gdk_input_remove(NetBuf->InputTag); NetBuf->InputTag=0; if (Read || Write) { t@@ -2184,6 +2188,7 @@ void MetaSocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { (Write ? GDK_INPUT_WRITE : 0), HandleMetaSock,NetBuf->CallBackData); } + if (CallNow) HandleMetaSock(NetBuf->CallBackData,NetBuf->fd,0); } static void UpdateMetaServerList(GtkWidget *widget, t@@ -2206,9 +2211,9 @@ static void UpdateMetaServerList(GtkWidget *widget, if (OpenMetaHttpConnection(&widgets->MetaConn)) { metaserv=widgets->metaserv; - SetHttpAuthFunc(widgets->MetaConn,AuthDialog,(gpointer)widgets); + SetHttpAuthFunc(widgets->MetaConn,AuthDialog,NULL); SetNetworkBufferUserPasswdFunc(&widgets->MetaConn->NetBuf, - MetaSocksAuthDialog,(gpointer)widgets); + MetaSocksAuthDialog,NULL); SetNetworkBufferCallBack(&widgets->MetaConn->NetBuf, MetaSocketStatus,(gpointer)widgets); } else { t@@ -3226,34 +3231,22 @@ static void DestroyAuthDialog(GtkWidget *window,gpointer data) { GtkWidget *userentry,*passwdentry; gchar *username=NULL,*password=NULL; gpointer proxy,authok; - struct StartGameStruct *widgets; HttpConnection *conn; - NBStatus oldstatus; - NBSocksStatus oldsocks; authok = gtk_object_get_data(GTK_OBJECT(window),"authok"); proxy = gtk_object_get_data(GTK_OBJECT(window),"proxy"); userentry = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(window),"username"); passwdentry = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(window), "password"); - widgets = (struct StartGameStruct *)gtk_object_get_data(GTK_OBJECT(window), - "widgets"); conn = (HttpConnection *)gtk_object_get_data(GTK_OBJECT(window),"httpconn"); - g_assert(userentry && passwdentry && conn && widgets); + g_assert(userentry && passwdentry && conn); if (authok) { username = gtk_editable_get_chars(GTK_EDITABLE(userentry),0,-1); password = gtk_editable_get_chars(GTK_EDITABLE(passwdentry),0,-1); } - oldstatus = widgets->MetaConn->NetBuf.status; - oldsocks = widgets->MetaConn->NetBuf.sockstat; - - if (!SetHttpAuthentication(conn,GPOINTER_TO_INT(proxy),username,password)) { - MetaDone(widgets); - } else { - DisplayConnectStatus(widgets,TRUE,oldstatus,oldsocks); - } + SetHttpAuthentication(conn,GPOINTER_TO_INT(proxy),username,password); g_free(username); g_free(password); } t@@ -3261,16 +3254,12 @@ static void DestroyAuthDialog(GtkWidget *window,gpointer data) { void AuthDialog(HttpConnection *conn,gboolean proxy,gchar *realm, gpointer data) { GtkWidget *window,*button,*hsep,*vbox,*label,*entry,*table,*hbbox; - struct StartGameStruct *widgets; - - widgets = (struct StartGameStruct *)data; window=gtk_window_new(GTK_WINDOW_DIALOG); gtk_signal_connect(GTK_OBJECT(window),"destroy", GTK_SIGNAL_FUNC(DestroyAuthDialog),NULL); gtk_object_set_data(GTK_OBJECT(window),"proxy",GINT_TO_POINTER(proxy)); gtk_object_set_data(GTK_OBJECT(window),"httpconn",(gpointer)conn); - gtk_object_set_data(GTK_OBJECT(window),"widgets",(gpointer)widgets); if (proxy) { gtk_window_set_title(GTK_WINDOW(window), t@@ -3352,9 +3341,6 @@ static void DestroySocksAuth(GtkWidget *window,gpointer data) { gchar *username=NULL,*password=NULL; gpointer authok,meta; NetworkBuffer *netbuf; - struct StartGameStruct *widgets; - NBStatus oldstatus; - NBSocksStatus oldsocks; authok = gtk_object_get_data(GTK_OBJECT(window),"authok"); meta = gtk_object_get_data(GTK_OBJECT(window),"meta"); t@@ -3362,8 +3348,6 @@ static void DestroySocksAuth(GtkWidget *window,gpointer data) { passwdentry = (GtkWidget *)gtk_object_get_data(GTK_OBJECT(window), "password"); netbuf = (NetworkBuffer *)gtk_object_get_data(GTK_OBJECT(window),"netbuf"); - widgets = (struct StartGameStruct *)gtk_object_get_data(GTK_OBJECT(window), - "widgets"); g_assert(userentry && passwdentry && netbuf); t@@ -3372,29 +3356,19 @@ static void DestroySocksAuth(GtkWidget *window,gpointer data) { password = gtk_editable_get_chars(GTK_EDITABLE(passwdentry),0,-1); } - oldstatus = netbuf->status; - oldsocks = netbuf->sockstat; - if (!SendSocks5UserPasswd(netbuf,username,password)) { - if (meta) MetaDone(widgets); else ConnectError(widgets,FALSE); - } else { - DisplayConnectStatus(widgets,GPOINTER_TO_INT(meta),oldstatus,oldsocks); - } + SendSocks5UserPasswd(netbuf,username,password); g_free(username); g_free(password); } static void RealSocksAuthDialog(NetworkBuffer *netbuf,gboolean meta, gpointer data) { GtkWidget *window,*button,*hsep,*vbox,*label,*entry,*table,*hbbox; - struct StartGameStruct *widgets; - - widgets = (struct StartGameStruct *)data; window=gtk_window_new(GTK_WINDOW_DIALOG); gtk_signal_connect(GTK_OBJECT(window),"destroy", GTK_SIGNAL_FUNC(DestroySocksAuth),NULL); gtk_object_set_data(GTK_OBJECT(window),"netbuf",(gpointer)netbuf); gtk_object_set_data(GTK_OBJECT(window),"meta",GINT_TO_POINTER(meta)); - gtk_object_set_data(GTK_OBJECT(window),"widgets",(gpointer)widgets); /* Title of dialog for authenticating with a SOCKS server */ gtk_window_set_title(GTK_WINDOW(window),_("SOCKS Authentication Required")); (DIR) diff --git a/src/network.c b/src/network.c t@@ -125,20 +125,20 @@ void SetBlocking(int sock,gboolean blocking) { static gboolean FinishConnect(int fd,LastError **error); -static void NetBufCallBack(NetworkBuffer *NetBuf) { +static void NetBufCallBack(NetworkBuffer *NetBuf,gboolean CallNow) { if (NetBuf && NetBuf->CallBack) { (*NetBuf->CallBack)(NetBuf,NetBuf->status!=NBS_PRECONNECT, (NetBuf->status==NBS_CONNECTED && NetBuf->WriteBuf.DataPresent) || (NetBuf->status==NBS_SOCKSCONNECT && NetBuf->negbuf.DataPresent) || - NetBuf->WaitConnect); + NetBuf->WaitConnect,CallNow); } } static void NetBufCallBackStop(NetworkBuffer *NetBuf) { if (NetBuf && NetBuf->CallBack) { - (*NetBuf->CallBack)(NetBuf,FALSE,FALSE); + (*NetBuf->CallBack)(NetBuf,FALSE,FALSE,FALSE); } } t@@ -181,7 +181,7 @@ void SetNetworkBufferCallBack(NetworkBuffer *NetBuf,NBCallBack CallBack, NetBufCallBackStop(NetBuf); NetBuf->CallBack=CallBack; NetBuf->CallBackData=CallBackData; - NetBufCallBack(NetBuf); + NetBufCallBack(NetBuf,FALSE); } void SetNetworkBufferUserPasswdFunc(NetworkBuffer *NetBuf, t@@ -238,7 +238,7 @@ gboolean StartNetworkBufferConnect(NetworkBuffer *NetBuf,gchar *RemoteHost, /* Notify the owner if necessary to check for the connection completing and/or for data to be writeable */ - NetBufCallBack(NetBuf); + NetBufCallBack(NetBuf,FALSE); return TRUE; } else { t@@ -401,22 +401,23 @@ static gboolean Socks5UserPasswd(NetworkBuffer *NetBuf) { } } -gboolean SendSocks5UserPasswd(NetworkBuffer *NetBuf,gchar *user, - gchar *password) { +void SendSocks5UserPasswd(NetworkBuffer *NetBuf,gchar *user,gchar *password) { gchar *addpt; guint addlen; ConnBuf *conn; if (!user || !password || !user[0] || !password[0]) { SetError(&NetBuf->error,&ETSocks,SEC_USERCANCEL,NULL); - return FALSE; + NetBufCallBack(NetBuf,TRUE); + return; } conn=&NetBuf->negbuf; addlen = 3 + strlen(user) + strlen(password); addpt = ExpandWriteBuffer(conn,addlen,&NetBuf->error); if (!addpt || strlen(user)>255 || strlen(password)>255) { SetError(&NetBuf->error,ET_CUSTOM,E_FULLBUF,NULL); - return FALSE; + NetBufCallBack(NetBuf,TRUE); + return; } addpt[0] = 1; /* Subnegotiation version code */ addpt[1] = strlen(user); t@@ -425,8 +426,6 @@ gboolean SendSocks5UserPasswd(NetworkBuffer *NetBuf,gchar *user, strcpy(&addpt[3+strlen(user)],password); CommitWriteBuffer(NetBuf,conn,addpt,addlen); - - return TRUE; } static gboolean Socks5Connect(NetworkBuffer *NetBuf) { t@@ -520,7 +519,7 @@ static gboolean HandleSocksReply(NetworkBuffer *NetBuf) { else g_print("FQDN\n");*/ NetBuf->status = NBS_CONNECTED; g_free(data); - NetBufCallBack(NetBuf); /* status has changed */ + NetBufCallBack(NetBuf,FALSE); /* status has changed */ } } } t@@ -535,7 +534,7 @@ static gboolean HandleSocksReply(NetworkBuffer *NetBuf) { } else { if (data[1]==90) { NetBuf->status = NBS_CONNECTED; - NetBufCallBack(NetBuf); /* status has changed */ + NetBufCallBack(NetBuf,FALSE); /* status has changed */ retval=TRUE; } else if (data[1]>=SEC_REJECT && data[1]<=SEC_IDMISMATCH) { SetError(&NetBuf->error,&ETSocks,data[1],NULL); t@@ -561,7 +560,7 @@ static gboolean DoNetworkBufferStuff(NetworkBuffer *NetBuf,gboolean ReadReady, gboolean retval; *ReadOK=*WriteOK=*ErrorOK=TRUE; - if (ErrorReady) *ErrorOK=FALSE; + if (ErrorReady || NetBuf->error) *ErrorOK=FALSE; else if (NetBuf->WaitConnect) { if (WriteReady) { retval=FinishConnect(NetBuf->fd,&NetBuf->error); t@@ -587,7 +586,10 @@ static gboolean DoNetworkBufferStuff(NetworkBuffer *NetBuf,gboolean ReadReady, *ReadOK=ReadDataFromWire(NetBuf); if (NetBuf->ReadBuf.DataPresent>0 && NetBuf->status==NBS_SOCKSCONNECT) { - if (!HandleSocksReply(NetBuf)) *ErrorOK=FALSE; + if (!HandleSocksReply(NetBuf) + || NetBuf->error) { /* From SendSocks5UserPasswd, possibly */ + *ErrorOK=FALSE; + } } if (NetBuf->ReadBuf.DataPresent>0 && NetBuf->status!=NBS_SOCKSCONNECT) { t@@ -605,7 +607,7 @@ static gboolean DoNetworkBufferStuff(NetworkBuffer *NetBuf,gboolean ReadReady, } else if (ConnectDone) { /* If we just connected, then no need to listen for write-ready status any more */ - NetBufCallBack(NetBuf); + NetBufCallBack(NetBuf,FALSE); } else if (WriteReady && ((NetBuf->status==NBS_CONNECTED && NetBuf->WriteBuf.DataPresent==0) || t@@ -613,7 +615,7 @@ static gboolean DoNetworkBufferStuff(NetworkBuffer *NetBuf,gboolean ReadReady, NetBuf->negbuf.DataPresent==0))) { /* If we wrote out everything, then tell the owner so that the socket no longer needs to be checked for write-ready status */ - NetBufCallBack(NetBuf); + NetBufCallBack(NetBuf,FALSE); } return DataWaiting; t@@ -787,7 +789,7 @@ void CommitWriteBuffer(NetworkBuffer *NetBuf,ConnBuf *conn, /* If the buffer was empty before, we may need to tell the owner to check the socket for write-ready status */ - if (NetBuf && addpt==conn->Data) NetBufCallBack(NetBuf); + if (NetBuf && addpt==conn->Data) NetBufCallBack(NetBuf,FALSE); } void QueueMessageForSend(NetworkBuffer *NetBuf,gchar *data) { t@@ -1065,8 +1067,8 @@ void CloseHttpConnection(HttpConnection *conn) { g_free(conn); } -gboolean SetHttpAuthentication(HttpConnection *conn,gboolean proxy, - gchar *user,gchar *password) { +void SetHttpAuthentication(HttpConnection *conn,gboolean proxy, + gchar *user,gchar *password) { gchar **ptuser,**ptpassword; g_assert(conn); if (proxy) { t@@ -1082,8 +1084,9 @@ gboolean SetHttpAuthentication(HttpConnection *conn,gboolean proxy, *ptuser = *ptpassword = NULL; } conn->waitinput=FALSE; - if (conn->Status==HS_WAITCOMPLETE) return !HandleHttpCompletion(conn); - else return TRUE; + if (conn->Status==HS_WAITCOMPLETE) { + NetBufCallBack(&conn->NetBuf,TRUE); + } } void SetHttpAuthFunc(HttpConnection *conn,HCAuthFunc authfunc,gpointer data) { t@@ -1158,7 +1161,7 @@ static void ParseHtmlHeader(gchar *line,HttpConnection *conn) { if (g_strcasecmp(split[0],"Location:")==0 && (conn->StatusCode==HEC_MOVETEMP || conn->StatusCode==HEC_MOVEPERM)) { if (ParseHtmlLocation(split[1],&host,&port,&query)) { - g_print("Redirect to %s:%u%s\n",host,port,query); + g_print("FIXME: Redirect to %s:%u%s\n",host,port,query); g_free(conn->RedirHost); g_free(conn->RedirQuery); conn->RedirHost=host; conn->RedirQuery=query; conn->RedirPort=port; (DIR) diff --git a/src/network.h b/src/network.h t@@ -63,22 +63,25 @@ typedef struct _ConnBuf { typedef struct _NetworkBuffer NetworkBuffer; -typedef void (*NBCallBack)(NetworkBuffer *NetBuf,gboolean Read,gboolean Write); +typedef void (*NBCallBack)(NetworkBuffer *NetBuf,gboolean Read,gboolean Write, + gboolean CallNow); typedef void (*NBUserPasswd)(NetworkBuffer *NetBuf,gpointer data); /* Information about a SOCKS server */ typedef struct _SocksServer { - gchar *name; /* hostname */ - unsigned port; /* port number */ - int version; /* desired protocol version (usually 4 or 5) */ - gboolean numuid; /* if TRUE, send numeric user IDs rather than names */ - char *user; /* if not blank, override the username with this */ + gchar *name; /* hostname */ + unsigned port; /* port number */ + int version; /* desired protocol version (usually 4 or 5) */ + gboolean numuid; /* if TRUE, send numeric user IDs rather than names */ + char *user; /* if not blank, override the username with this */ + gchar *authuser; /* if set, the username for SOCKS5 auth */ + gchar *authpassword; /* if set, the password for SOCKS5 auth */ } SocksServer; /* The status of a network buffer */ typedef enum { - NBS_PRECONNECT, /* Socket is not connected */ + NBS_PRECONNECT, /* Socket is not yet connected */ NBS_SOCKSCONNECT, /* A CONNECT request is being sent to a SOCKS server */ NBS_CONNECTED /* Socket is connected */ } NBStatus; t@@ -94,8 +97,7 @@ typedef enum { struct _NetworkBuffer { int fd; /* File descriptor of the socket */ gint InputTag; /* Identifier for gdk_input routines */ - NBCallBack CallBack; /* Function called when the socket read- or - write-able status changes */ + NBCallBack CallBack; /* Function called when the socket status changes */ gpointer CallBackData; /* Data accessible to the callback function */ char Terminator; /* Character that separates messages */ char StripChar; /* Char that should be removed from messages */ t@@ -179,8 +181,7 @@ gboolean WriteDataToWire(NetworkBuffer *NetBuf); void QueueMessageForSend(NetworkBuffer *NetBuf,gchar *data); gint CountWaitingMessages(NetworkBuffer *NetBuf); gchar *GetWaitingMessage(NetworkBuffer *NetBuf); -gboolean SendSocks5UserPasswd(NetworkBuffer *NetBuf,gchar *user, - gchar *password); +void SendSocks5UserPasswd(NetworkBuffer *NetBuf,gchar *user,gchar *password); gchar *GetWaitingData(NetworkBuffer *NetBuf,int numbytes); gchar *PeekWaitingData(NetworkBuffer *NetBuf,int numbytes); gchar *ExpandWriteBuffer(ConnBuf *conn,int numbytes,LastError **error); t@@ -194,8 +195,8 @@ gboolean OpenHttpConnection(HttpConnection **conn,gchar *HostName, gchar *Headers,gchar *Body); void CloseHttpConnection(HttpConnection *conn); gchar *ReadHttpResponse(HttpConnection *conn); -gboolean SetHttpAuthentication(HttpConnection *conn,gboolean proxy, - gchar *user,gchar *password); +void SetHttpAuthentication(HttpConnection *conn,gboolean proxy, + gchar *user,gchar *password); void SetHttpAuthFunc(HttpConnection *conn,HCAuthFunc authfunc,gpointer data); gboolean HandleHttpCompletion(HttpConnection *conn); gboolean IsHttpError(HttpConnection *conn); (DIR) diff --git a/src/serverside.c b/src/serverside.c t@@ -135,7 +135,7 @@ static gboolean HighScoreWrite(FILE *fp,struct HISCORE *MultiScore, static void GuiHandleMeta(gpointer data,gint socket, GdkInputCondition condition); static void MetaSocketStatus(NetworkBuffer *NetBuf, - gboolean Read,gboolean Write); + gboolean Read,gboolean Write,gboolean CallNow); #endif #ifdef NETWORKING t@@ -149,6 +149,37 @@ static gboolean MetaConnectError(HttpConnection *conn) { g_string_free(errstr,TRUE); return TRUE; } + +static void ServerHttpAuth(HttpConnection *conn,gboolean proxyauth, + gchar *realm,gpointer data) { + gchar *user=NULL,*password=NULL; + if (proxyauth) { + if (MetaServer.proxyuser[0] && MetaServer.proxypassword[0]) { + user = MetaServer.proxyuser; password = MetaServer.proxypassword; + dopelog(3,_("Using MetaServer.Proxy.User and MetaServer.Proxy.Password " + "for HTTP proxy authentication")); + } else { + dopelog(0,_("Unable to authenticate with HTTP proxy; please set " + "MetaServer.Proxy.User and MetaServer.Proxy.Password variables")); + } + } else { + if (MetaServer.authuser[0] && MetaServer.authpassword[0]) { + user = MetaServer.authuser; password = MetaServer.authpassword; + dopelog(3,_("Using MetaServer.Auth.User and MetaServer.Auth.Password " + "for HTTP authentication")); + } else { + dopelog(0,_("Unable to authenticate with HTTP server; please set " + "MetaServer.Auth.User and MetaServer.Auth.Password variables")); + } + } + SetHttpAuthentication(conn,proxyauth,user,password); +} + +static void ServerNetBufAuth(NetworkBuffer *netbuf,gpointer data) { + dopelog(3,_("Using Socks.Auth.User and Socks.Auth.Password " + "for SOCKS5 authentication")); + SendSocks5UserPasswd(netbuf,Socks.authuser,Socks.authpassword); +} #endif void RegisterWithMetaServer(gboolean Up,gboolean SendData, t@@ -234,6 +265,12 @@ void RegisterWithMetaServer(gboolean Up,gboolean SendData, CloseHttpConnection(MetaConn); MetaConn=NULL; return; } + SetHttpAuthFunc(MetaConn,ServerHttpAuth,NULL); + + if (Socks.authuser && Socks.authuser[0] && + Socks.authpassword && Socks.authpassword[0]) { + SetNetworkBufferUserPasswdFunc(&MetaConn->NetBuf,ServerNetBufAuth,NULL); + } #ifdef GUI_SERVER SetNetworkBufferCallBack(&MetaConn->NetBuf,MetaSocketStatus,NULL); #endif t@@ -1083,7 +1120,8 @@ void SocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { } } -void MetaSocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { +void MetaSocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write, + gboolean CallNow) { if (NetBuf->InputTag) gdk_input_remove(NetBuf->InputTag); NetBuf->InputTag=0; if (Read || Write) { t@@ -1092,6 +1130,7 @@ void MetaSocketStatus(NetworkBuffer *NetBuf,gboolean Read,gboolean Write) { (Write ? GDK_INPUT_WRITE : 0), GuiHandleMeta,NetBuf->CallBackData); } + if (CallNow) GuiHandleMeta(NetBuf->CallBackData,NetBuf->fd,0); } static void GuiNewConnect(gpointer data,gint socket,