Complete.Org: Mailing Lists: Archives: freeciv-dev: August 2004:
[Freeciv-Dev] Re: (PR#8570) no auth for gtk2 client
Home

[Freeciv-Dev] Re: (PR#8570) no auth for gtk2 client

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: jdorje@xxxxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#8570) no auth for gtk2 client
From: "Mike Kaufman" <kaufman@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 15 Aug 2004 11:18:22 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8570 >

attached is a patch that fixes authentication for freeciv. I've removed
capability requirement for auth. This means that all clients must be
auth-aware. I don't think that's the case for gui-win32, gui-sdl, gui-ftwl,
or gui-mui. This should be resolved asap.

It also permits single-player mode to work with auth compiled into
the server. It does this mainly by cheating.

I've added three commandline options to civserver

Valid options are:
  -a  --auth            Enable server authentication.
  -G  --Guests          Allow guests to login if auth is enabled.
  -N  --Newusers        Allow new users to login if auth is enabled.

So without any flags, the server will not be authenticating, allowing
single-player mode to work. Without -G or -N only preregistered users will
be allowed to login.

None of these options are available unless --enable-auth is passed to 
autogen.sh. I'm wondering if this is necessary anymore. Perhaps auth 
should be compiled in by default and --enable-auth should be replaced by a
--authdb-lib=[] option to allow changing the database. This is open for
discussion, but beyond the scope of the present patch.

-mike

diff -Nur -Xcvs/diff_ignore snap/server/civserver.c snap-auth/server/civserver.c
--- snap/server/civserver.c     2004-05-06 21:32:43.000000000 -0500
+++ snap-auth/server/civserver.c        2004-08-14 19:16:38.253040704 -0500
@@ -109,6 +109,14 @@
        showhelp = TRUE;
        break;
       }
+#ifdef AUTHENTICATION_ENABLED 
+    } else if (is_option("--auth", argv[inx])) {
+      srvarg.auth_enabled = TRUE;
+    } else if (is_option("--Guests", argv[inx])) {
+      srvarg.auth_allow_guests = TRUE;
+    } else if (is_option("--Newusers", argv[inx])) {
+      srvarg.auth_allow_newusers = TRUE;
+#endif
     } else if (is_option("--version", argv[inx]))
       showvers = TRUE;
     else {
@@ -129,6 +137,11 @@
 
   if (showhelp) {
     fprintf(stderr, _("Usage: %s [option ...]\nValid options are:\n"), 
argv[0]);
+#ifdef AUTHENTICATION_ENABLED 
+    fprintf(stderr, _("  -a  --auth\t\tEnable server authentication.\n"));
+    fprintf(stderr, _("  -G  --Guests\t\tAllow guests to login if auth is 
enabled.\n"));
+    fprintf(stderr, _("  -N  --Newusers\tAllow new users to login if auth is 
enabled.\n"));
+#endif
     fprintf(stderr, _("  -b  --bind ADDR\tListen for clients on ADDR\n"));
 #ifdef DEBUG
     fprintf(stderr, _("  -d, --debug NUM\tSet debug log level (0 to 4,"
diff -Nur -Xcvs/diff_ignore snap/server/connecthand.c 
snap-auth/server/connecthand.c
--- snap/server/connecthand.c   2004-05-12 17:31:34.000000000 -0500
+++ snap-auth/server/connecthand.c      2004-08-14 19:18:33.902311268 -0500
@@ -41,10 +41,6 @@
 
 #include "connecthand.h"
 
-/* TODO: these should probably server options */
-#define NEW_USERS_ALLOWED  /* if defined, new users may log in. */
-#define GUESTS_ALLOWED     /* if defined, users can log in as guests */
-
 #define GUEST_NAME "guest"
 
 #define MIN_PASSWORD_LEN  6  /* minimum length of password */
@@ -213,54 +209,6 @@
 {
   char msg[MAX_LEN_MSG];
   
-  remove_leading_trailing_spaces(req->username);
-
-  /* Name-sanity check: could add more checks? */
-  if (strlen(req->username) == 0 || my_isdigit(req->username[0])
-      || mystrcasecmp(req->username, "all") == 0
-      || mystrcasecmp(req->username, "none") == 0
-      || mystrcasecmp(req->username, ANON_USER_NAME) == 0) {
-    my_snprintf(msg, sizeof(msg), _("Invalid username '%s'"), req->username);
-    reject_new_connection(msg, pconn);
-    freelog(LOG_NORMAL, _("Rejected connection from %s with invalid name."),
-            pconn->addr);
-    return FALSE;
-  } 
-
-#ifdef AUTHENTICATION_ENABLED 
-  /* assign the client a unique guest name */
-  if (is_guest_name(req->username)) {
-#ifdef GUESTS_ALLOWED
-    char old_guest_name[MAX_LEN_NAME];
-
-    sz_strlcpy(old_guest_name, req->username);
-    get_unique_guest_name(req->username);
-
-    if (strncmp(old_guest_name, req->username, MAX_LEN_NAME) != 0) {
-      notify_conn(&pconn->self, _("Warning: the guest name '%s' has been "
-                                  "taken, renaming to user '%s'."),
-                                  old_guest_name, req->username);
-    }
-#else
-    reject_new_connection(_("Guests are not allowed on this server."), pconn);
-    return FALSE;
-#endif /* GUESTS_ALLOWED */
-  }
-#endif /* AUTHENTICATION_ENABLED */
-
-  /* don't allow duplicate logins */
-  conn_list_iterate(game.all_connections, aconn) {
-    if (strcmp(req->username, aconn->username) == 0) { 
-      my_snprintf(msg, sizeof(msg), _("'%s' already connected."), 
-                  req->username);
-      reject_new_connection(msg, pconn);
-      freelog(LOG_NORMAL,
-              _("Rejected connection from %s with duplicate login name."),
-              aconn->addr);
-      return FALSE;
-    }
-  } conn_list_iterate_end;
-
   freelog(LOG_NORMAL, _("Connection request from %s from %s"),
           req->username, pconn->addr);
   
@@ -302,73 +250,105 @@
     return FALSE;
   }
 
-#ifdef AUTHENTICATION_ENABLED 
-  /* if authentication is enabled, we need an extra check as to whether
-   * a connection can be established: the client must authenticate itself */
-
-  if (has_capability("auth", req->capability) 
-      && !is_guest_name(req->username)) {
-    char tmpname[MAX_LEN_NAME] = "\0";
-    char buffer[MAX_LEN_MSG];
+  remove_leading_trailing_spaces(req->username);
 
-    sz_strlcpy(pconn->username, req->username);
+  /* Name-sanity check: could add more checks? */
+  if (strlen(req->username) == 0 || my_isdigit(req->username[0])
+      || mystrcasecmp(req->username, "all") == 0
+      || mystrcasecmp(req->username, "none") == 0
+      || mystrcasecmp(req->username, ANON_USER_NAME) == 0) {
+    my_snprintf(msg, sizeof(msg), _("Invalid username '%s'"), req->username);
+    reject_new_connection(msg, pconn);
+    freelog(LOG_NORMAL, _("Rejected connection from %s with invalid name."),
+            pconn->addr);
+    return FALSE;
+  } 
 
-    switch(user_db_load(pconn)) {
-    case USER_DB_ERROR:
-#ifdef GUESTS_ALLOWED
-      sz_strlcpy(tmpname, pconn->username);
-      get_unique_guest_name(tmpname); /* do not pass pconn->username here! */
-      sz_strlcpy(pconn->username, tmpname);
-
-      freelog(LOG_ERROR, "Error reading database; connection -> guest");
-      notify_conn(&pconn->self, _("There was an error reading the user "
-                                  "database, logging in as guest connection "
-                                  "'%s'."), pconn->username);
-      establish_new_connection(pconn);
-#else
-      reject_new_connection(_("There was an error reading the user database "
-                            "and guest logins are not allowed. Sorry"), pconn);
-#endif /* GUESTS_ALLOWED */
-      break;
-    case USER_DB_SUCCESS:
-      /* we found a user */
-      my_snprintf(buffer, sizeof(buffer), _("Enter password for %s:"),
-                 pconn->username);
-      dsend_packet_authentication_req(pconn, AUTH_LOGIN_FIRST, buffer);
-      pconn->server.status = AS_REQUESTING_OLD_PASS;
-      break;
-    case USER_DB_NOT_FOUND:
-      /* we couldn't find the user, he is new */
-#ifdef NEW_USERS_ALLOWED
-      sz_strlcpy(buffer, _("Enter a password (and remember it)."));
-      dsend_packet_authentication_req(pconn, AUTH_NEWUSER_FIRST, buffer);
-      pconn->server.status = AS_REQUESTING_NEW_PASS;
-#else
-      reject_new_connection(_("This server allows only preregistered users. "
-                              "Sorry."), pconn);
-#endif /* NEW_USERS_ALLOWED */
-      break;
-    default:
-      assert(0);
-      break;
+  /* don't allow duplicate logins */
+  conn_list_iterate(game.all_connections, aconn) {
+    if (strcmp(req->username, aconn->username) == 0) { 
+      my_snprintf(msg, sizeof(msg), _("'%s' already connected."), 
+                  req->username);
+      reject_new_connection(msg, pconn);
+      freelog(LOG_NORMAL,
+              _("Rejected connection from %s with duplicate login name."),
+              aconn->addr);
+      return FALSE;
     }
+  } conn_list_iterate_end;
 
-    return TRUE;
-  } else if (!is_guest_name(req->username)) {
-#ifdef GUESTS_ALLOWED
-    get_unique_guest_name(req->username);
-    sz_strlcpy(pconn->username, req->username);
-
-    notify_conn(&pconn->self, _("Warning: your non-authenticating client "
-                                "is logging into an authenticating server, "
-                                "logging in as guest connection '%s'."), 
-                                pconn->username);
-#else
-    reject_new_connection(_("Your non-authenticating client is logging into "
-                            "an authenticating server. Guest logins are not "
-                            "allowed. Sorry") , pconn);
-    return FALSE;
-#endif /* GUESTS_ALLOWED */
+#ifdef AUTHENTICATION_ENABLED 
+  if (srvarg.auth_enabled) {
+    /* assign the client a unique guest name/reject if guests aren't allowed */
+    if (is_guest_name(req->username)) {
+      if (srvarg.auth_allow_guests) {
+        char old_guest_name[MAX_LEN_NAME];
+
+        sz_strlcpy(old_guest_name, req->username);
+        get_unique_guest_name(req->username);
+
+        if (strncmp(old_guest_name, req->username, MAX_LEN_NAME) != 0) {
+          notify_conn(&pconn->self, _("Warning: the guest name '%s' has been "
+                                      "taken, renaming to user '%s'."),
+                      old_guest_name, req->username);
+        }
+      } else {
+        reject_new_connection(_("Guests are not allowed on this server. "
+                                "Sorry."), pconn);
+        return FALSE;
+      }
+    } else {
+      /* we are not a guest, we need an extra check as to whether a 
+       * connection can be established: the client must authenticate itself */
+      char tmpname[MAX_LEN_NAME] = "\0";
+      char buffer[MAX_LEN_MSG];
+
+      sz_strlcpy(pconn->username, req->username);
+
+      switch(user_db_load(pconn)) {
+      case USER_DB_ERROR:
+        if (srvarg.auth_allow_guests) {
+          sz_strlcpy(tmpname, pconn->username);
+          get_unique_guest_name(tmpname); /* don't pass pconn->username here */
+          sz_strlcpy(pconn->username, tmpname);
+
+          freelog(LOG_ERROR, "Error reading database; connection -> guest");
+          notify_conn(&pconn->self, _("There was an error reading the user "
+                                      "database, logging in as guest "
+                                      "connection '%s'."), pconn->username);
+          establish_new_connection(pconn);
+        } else {
+          reject_new_connection(_("There was an error reading the user "
+                                  "database and guest logins are not "
+                                  "allowed. Sorry"), pconn);
+          return FALSE;
+        }
+        break;
+      case USER_DB_SUCCESS:
+        /* we found a user */
+        my_snprintf(buffer, sizeof(buffer), _("Enter password for %s:"),
+                    pconn->username);
+        dsend_packet_authentication_req(pconn, AUTH_LOGIN_FIRST, buffer);
+        pconn->server.status = AS_REQUESTING_OLD_PASS;
+        break;
+      case USER_DB_NOT_FOUND:
+        /* we couldn't find the user, he is new */
+        if (srvarg.auth_allow_newusers) {
+          sz_strlcpy(buffer, _("Enter a new password (and remember it)."));
+          dsend_packet_authentication_req(pconn, AUTH_NEWUSER_FIRST, buffer);
+          pconn->server.status = AS_REQUESTING_NEW_PASS;
+        } else {
+          reject_new_connection(_("This server allows only preregistered "
+                                  "users. Sorry."), pconn);
+          return FALSE;
+        }
+        break;
+      default:
+        assert(0);
+        break;
+      }
+      return TRUE;
+    }
   }
 #endif /* AUTHENTICATION_ENABLED */
 
diff -Nur -Xcvs/diff_ignore snap/server/srv_main.c snap-auth/server/srv_main.c
--- snap/server/srv_main.c      2004-08-08 09:03:19.000000000 -0500
+++ snap-auth/server/srv_main.c 2004-08-14 19:15:10.871960726 -0500
@@ -174,6 +174,10 @@
 
   srvarg.extra_metaserver_info[0] = '\0';
 
+  srvarg.auth_enabled = FALSE;
+  srvarg.auth_allow_guests = FALSE;
+  srvarg.auth_allow_newusers = FALSE;
+
   /* initialize teams */
   team_init();
 
diff -Nur -Xcvs/diff_ignore snap/server/srv_main.h snap-auth/server/srv_main.h
--- snap/server/srv_main.h      2004-05-29 13:18:41.000000000 -0500
+++ snap-auth/server/srv_main.h 2004-08-11 23:25:01.000000000 -0500
@@ -46,6 +46,10 @@
   bool exit_on_end;
   /* what kind of end game we should use */
   bv_draw draw;
+  /* authentication options */
+  bool auth_enabled;             /* defaults to FALSE */
+  bool auth_allow_guests;       /* defaults to TRUE */
+  bool auth_allow_newusers;     /* defaults to TRUE */
 };
 
 void srv_init(void);

[Prev in Thread] Current Thread [Next in Thread]