# HG changeset patch # User John "Elwin" Edwards # Date 1382316338 25200 # Node ID ce26225f7d9d2f65560e8ba48f4cfc143c6c2e44 # Parent 070a9ced4d3e9271b897ab260c62dad78f1c7708 Switch to the Git version of dgamelaunch. diff -r 070a9ced4d3e -r ce26225f7d9d README.txt --- a/README.txt Sat Oct 05 17:10:24 2013 -0700 +++ b/README.txt Sun Oct 20 17:45:38 2013 -0700 @@ -1,8 +1,8 @@ RLG: various files used by the Roguelike Gallery. dgl/ contains the Gallery's dgamelaunch.conf file, the dgamelaunch menus, and -a patch to dgamelaunch 1.5.1 which makes it compatible with the RLGWebD -player. +a patch to the Git version of dgamelaunch. The patch makes it compatible with +the RLGWebD player and adds properly salted passwords. py/ contains various Python scripts. diff -r 070a9ced4d3e -r ce26225f7d9d dgl/dgamelaunch.conf --- a/dgl/dgamelaunch.conf Sat Oct 05 17:10:24 2013 -0700 +++ b/dgl/dgamelaunch.conf Sun Oct 20 17:45:38 2013 -0700 @@ -1,4 +1,7 @@ -# rlgallery.org configuration file for dgamelaunch +# This is a sample dgamelaunch configuration file. Only bash-style comments +# are allowed, such as this. Each configuration option will be explained +# along with its default value. + # Global config variables: @@ -6,7 +9,7 @@ # Max amount of registered users to allow. Has no effect if dgl was # compiled with SQLite -maxusers = 4096 +maxusers = 64000 # Allow registration of new nicks? (yes or no) allow_new_nicks = yes @@ -17,23 +20,48 @@ maxnicklen = 10 # Set the default watching-screen sorting mode. Can be one of -# "unsorted", "username" or "idletime". Unsorted is the default. +# "username", "game", "windowsize", "starttime" or "idletime". +# "username" is the default. sortmode = "username" +# Set the columns displayed in the watching-screen. Each column definition +# must have four elements as: +# [ "", "", , "" ] +# +# may be "unsorted", "username", "game", "windowsize", "starttime", +# "duration", "idletime", or (if shmem is enabled) "watchers". +# +watch_columns = [ ["", "", 1, "%s)"], + ["User", "username", 4, "%-15s"], + ["Game", "game", 21, "%-11s"], + ["Term", "windowsize", 34, "%s"], + ["Idle", "idletime", 43, "%-10s"], + ["Started", "starttime", 60, "%s"] + ] + # Path to a prepared chroot jail. -chroot_path = "/var/dgl/" +chroot_path = "/var/dgl" # From inside the jail, dgamelaunch's working directory for rcfiles/ttyrec/etc dglroot = "/dgldir/" -# Server ID string -server_id = "Roguelike Gallery - rlgallery.org" +# Strings to be replaced in every banner +# you can have either direct string replacements, like +# "$FOO" = "BAR", or you can get the server time with +# "$FOO" = timeformat("%F %T") +# for the timeformat parameter string format, see man strftime +bannervars = [ "$MOTDTIME" = "2011.10.08", + "$SERVERID" = "$ATTR(14)Roguelike Gallery - rlgallery.org$ATTR()", + "$DATETIME" = timeformat("%F %T") + ] -# From inside the jail, location of a banner file, the topmost line will be +# From inside the jail, location of a banner file, which is # shown in submenus that cannot be defined separately. -# Some string substitution is done for the file: -# $VERSION replaced with "dgamelaunch v" + dgl version number. -# $SERVERID replaced with the server_id string, as defined above. +# Some string substitution is done for every banner file contents: +# - bannervars from above +# - $VERSION replaced with "dgamelaunch v" + dgl version number. +# - $USERNAME replaced with logged-in user's name, or with "[Anonymous]" +# - $INCLUDE(filename) the named file will be inserted here. banner = "/dgldir/dgl-banner" # The following two options are fairly insecure. They will force us to @@ -51,17 +79,39 @@ #shed_group = "games" # Preferably, you may use the respective gids/uids. This is for Debian: -# Use the rodney account instead of games:games shed_uid = 501 shed_gid = 501 -# The defaults are usually just fine for this. passwd refers to the file -# that stores the user database, and lockfile is only used internally by -# dgamelaunch. -# passwd doesn't matter if dgl was compiled with SQLite, as the name of -# the sqlite database will be defined at compile time. -passwd = "/dgldir/dgl-login" -lockfile = "/dgldir/dgl-lock" +# Locale. Leaving this out, dgamelaunch will not explicitly set locale. +locale = "en_US.UTF-8" + +# Default TERM, used if the user's $TERM is unknown. +# If undefined, dgamelaunch will just terminate in that case. +default_term = "xterm" + +# Should dgl send select-UTF8-charset escape code? (that is: ESC % G) +# default is no. +#utf8esc = yes + +# Should dgl allow XON/XOFF? Default is "yes", meaning "don't touch it". +# "no" disables XON/XOFF +#flowcontrol = no + +# Maximum time in seconds user can idle in the dgamelaunch menus +# before dgl exits. Default value is 0, which disables the idling timer. +# Does not apply to external programs or config editors. +# For setting game idle time, use max_idle_time in the game DEFINE. +# menu_max_idle_time = 1024 + +# Passwd refers to the file that stores the user database. +# The default passwd file is "/dgl-login" for flat-text database, and for +# sqlite, whatever value was defined for the sqlite database at compile time. +# This is also used for the shared memory key, if shmem is enabled at compile +# time. +#passwd = "/dgl-login" + +# Lockfile is used only when dgl was compiled without sqlite. +#lockfile = "/dgl-lock" # # define some commands that are run when something happens. format is @@ -72,6 +122,7 @@ # login = when user has logged in # register = right after a new user is registered # gamestart = just before a game is started +# gameend = after a game ends (see also per-game "postcommand" define) # # is: # mkdir "foo" = create a directory "foo" @@ -81,6 +132,7 @@ # unlink "foo" = delete file "foo" # setenv "foo" "bar" = set environment variable "foo" to "bar" # exec "foo" "bar" = execute "foo" with "bar" as it's param +# rawprint "foo" = output string "foo" # chpasswd = do the change password prompting, if logged in # chmail = do the change email prompting, if logged in # watch_menu = go to the watching menu @@ -88,24 +140,41 @@ # ask_login = do the login prompting, if not logged in # ask_register = do register new user prompting, if not logged in and # registration of new nicks is allowed. -# edit_options "foo" = edit options for game which has the short name "foo" -# (user must be logged in) # play_game "foo" = start game which has the short name "foo" # (user must be logged in) # submenu "foo" = go to submenu "foo" # return = return from submenu # +# NOTE: edit_options-command was removed. use ifnxcp and exec to simulate it. +# # The commands will be done inside the chroot and with the uid and gid # defined above. # Parameters to the commands are subject to variable substitution: # %r = dglroot, as defined above # %n = user nick, if user is logged in +# %N = first character of user name, if user is logged in # %u = shed_uid, as defined above, but numeric # %g = game name, if user has selected a game. +# %s = short game name, if user has selected a game. +# %t = ttyrec path & filename of the last game played. +# +# Also some escape codes: +# \\ = backslash +# \a = bell +# \b = backspace +# \e = escape character +# \f = form feed +# \n = newline +# \r = carriage return +# \t = tab +# \v = vertical tab # # eg. commands[login] = mkdir "foo", unlink "bar", setenv "Z" "foo" # +# Change the terminal title: (assuming terminals support the escape code) +#commands[dglstart] = rawprint "\e]2;nethack.alt.org\a" + # create the user's dirs when they register commands[register] = mkdir "%ruserdata/%n", mkdir "%rttyrec/%n", @@ -123,6 +192,9 @@ mkdir "%rttyrec/%n/srogue", mkdir "%rttyrec/%n/arogue5" +# file mode for when commands copy files. +# readable and writable by all. you could use eg. "0644" to be more secure. +filemode = "0644" @@ -134,6 +206,7 @@ # First, the menu shown to anonymous user: menu["mainmenu_anon"] { bannerfile = "/dgldir/dgl_menu_main_anon.txt" + cursor = (5,18) commands["l"] = ask_login commands["r"] = ask_register commands["w"] = watch_menu @@ -145,6 +218,17 @@ menu["mainmenu_user"] { # contents of this file are written to screen. # the file must be inside the chroot. +# Some string subsitutions can be done in the file: +# $INCLUDE(filename) = includes the file to this file. +# String substitutions defined in bannervars-section above. +# $VERSION = dgamelaunch version +# $USERNAME = user name (or [Anonymous] if not logged in) +# $ATTR(params) = change text color and attributes. +# params can be either number (to set the text color), +# one, or any of "b" (bold), "s" (standout), "u" (underline), +# "r" (reverse) or "d" (dim), +# or both color number and attribute characters, separated by colon. +# Empty param resets color and attributes to default. bannerfile = "/dgldir/dgl_menu_main_user.txt" # after which cursor is moved to this location # if cursor-definition is missing, the cursor is put @@ -170,73 +254,6 @@ commands["qQ "] = return } - -# Next, we'll define one game's data: - -#DEFINE { -# # From inside the jail, the location of the binary to be launched. -# game_path = "/bin/nethackstub" -# -# # Full name of the game -# game_name = "NetHack stub" -# -# # Short name, used in the watching menu -# short_name = "NHstb" -# -# # arguments for when we exec the binary -# game_args = "/bin/nethackstub", -# "foo", -# "user:%n", -# "shed_uid:%u", -# "bar" -# -# # From inside the jail, where dgamelaunch should put mail. -# spooldir = "/var/mail/" -# -# # From inside the jail, the default .nethackrc that is copied for new users. -# # rc_template = "/dgl-default-rcfile" -# -# # Make sure the inprogress dir actually exists. default is "inprogress/" -# # Each game you define here must have it's own. -# inprogressdir = "%rinprogress-nethackstub/" -# -# # We can also define per-game commands, that are executed -# # when the game starts: -# # commands = chdir "/dgldir", mkdir "foo_%u_%g" -#} - - -#DEFINE { -# game_path = "/nh343/nethack" -# game_name = "NetHack 3.4.3" -# short_name = "NH343" -# -# game_args = "/nh343/nethack", "-u", "%n" -# -# spooldir = "/mail/" -# rc_template = "/dgl-default-rcfile.nh343" -# -# rc_fmt = "%ruserdata/%n/%n.nh343rc" -# -# inprogressdir = "%rinprogress-nh343/" -# -## The place where ttyrecs are stored for this game. -## If this is not defined, ttyrecs are not saved for this game. -## Leaving this undefined also means the games cannot be spectated. -# ttyrecdir = "%ruserdata/%n/ttyrec/" -# -# -# # back up savefile -# commands = cp "/nh343/var/save/%u%n.gz" "/nh343/var/save/%u%n.gz.bak", -# # set NETHACKOPTIONS to point to the rcfile -# setenv "NETHACKOPTIONS" "@%ruserdata/%n/%n.nh343rc", -# # set up nethack mail stuff, assuming it's compiled with it... -# setenv "MAIL" "/mail/%n", -# setenv "SIMPLEMAIL" "1", -# # don't let the mail file grow -# unlink "/mail/%n" -#} - # Rogue V3: short and simple, like the game DEFINE { game_path = "/bin/rogue3" @@ -305,3 +322,143 @@ commands = cp "/var/games/roguelike/arogue5save/%u-%n.ar5sav" "%rbackup/%u-%n.ar5sav.bak" } + + +# Next, we'll define one game's data: + +#DEFINE { +# # From inside the jail, the location of the binary to be launched. +# game_path = "/bin/nethackstub" +# +# # Full name of the game +# game_name = "NetHack stub" +# +# # Short name, used in the watching menu +# short_name = "NHstb" +# +# # arguments for when we exec the binary +# game_args = "/bin/nethackstub", +# "foo", +# "user:%n", +# "shed_uid:%u", +# "bar" +# +# # From inside the jail, where dgamelaunch should put mail. +# spooldir = "/var/mail/" +# +# # From inside the jail, the default .nethackrc that is copied for new users. +# # rc_template = "/dgl-default-rcfile" +# +# # If player idles longer than max_idle_time seconds, the game will +# # receive a sighup. Default value is 0, which disables the idling timer. +# max_idle_time = 2000 +# +# # Player-specific path to an extra information file written by the game +# # The game should write the extra information on one line in this format: +# # |extra-information +# # For example, the game might write: "100|Astral", "1|D:1", etc. to indicate +# # where the player is in the game world. The numeric weight is used when +# # a spectator sorts games by the extra information field: higher weights +# # will be sorted to appear before lower weights. +# # +# extra_info_file = "%rgamedir/%n.extrainfo" +# +# # Make sure the inprogress dir actually exists. default is "inprogress/" +# # Each game you define here must have it's own. +# inprogressdir = "%rinprogress-nethackstub/" +# +# # We can also define per-game commands, that are executed +# # when the game starts: +# # commands = chdir "/dgldir", mkdir "foo_%u_%g" +# +# # We can also define per-game commands executed after the game ends, +# # but before commands[gameend] +# postcommands = chdir "/" +# +# # If the game uses an ancient encoding, you may specify "ibm" or "dec". +# # If set to "ask", the game will be run with --print-charset beforehand, +# # expected to return one of these values. +# encoding = "unicode" +#} + + +# +# the second game +# +# + +#DEFINE { +# game_path = "/nh343/nethack" +# game_name = "NetHack 3.4.3" +# short_name = "NH343" +# +# game_args = "/nh343/nethack", "-u", "%n" +# +# spooldir = "/mail/" +# rc_template = "/dgl-default-rcfile.nh343" +# +# rc_fmt = "%ruserdata/%n/%n.nh343rc" +# +# inprogressdir = "%rinprogress-nh343/" +# +## The place where ttyrecs are stored for this game. +## If this is not defined, ttyrecs are not saved for this game. +## Leaving this undefined also means the games cannot be spectated. +# ttyrecdir = "%ruserdata/%n/ttyrec/" +# +# +# # back up savefile +# commands = cp "/nh343/var/save/%u%n.gz" "/nh343/var/save/%u%n.gz.bak", +# # set NETHACKOPTIONS to point to the rcfile +# setenv "NETHACKOPTIONS" "@%ruserdata/%n/%n.nh343rc", +# # set up nethack mail stuff, assuming it's compiled with it... +# setenv "MAIL" "/mail/%n", +# setenv "SIMPLEMAIL" "1", +# # don't let the mail file grow +# unlink "/mail/%n" +#} + +# +# third game +# +# + +#DEFINE { +# game_path = "/bin/crawlss017" +# game_name = "Crawl Stone Soup 0.1.7" +# short_name = "Cr017" +# +# game_args = "/bin/crawlss017", +# "-name", "%n", +# "-dir", "/crawlss017/", +# "-rc", "%rrcfiles/%n.crawlrc", +# "-morgue", "/crawlss017/morgues/", +# "-macro", "/crawlss017/macros/%n.macro" +# +# rc_template = "/dgl-default-rcfile.crawl" +# rc_fmt = "%rrcfiles/%n.crawlrc" +# inprogressdir = "%rinprogress-crawlss017/" +# encoding = ask +#} + +# +# fourth game +# +# + +#DEFINE { +# game_path = "/bin/crawlss020" +# game_name = "Crawl Stone Soup 0.2.0" +# short_name = "Cr020" +# +# game_args = "/bin/crawlss020", +# "-name", "%n", +# "-dir", "/crawlss020/", +# "-rc", "/crawlss020/plr/%n/%n.crawlrc", +# "-morgue", "/crawlss020/plr/%n/", +# "-macro", "/crawlss020/plr/%n/" +# +# rc_template = "/dgl-default-rcfile.crawl" +# rc_fmt = "/crawlss020/plr/%n/%n.crawlrc" +# inprogressdir = "%rinprogress-crawlss020/" +#} diff -r 070a9ced4d3e -r ce26225f7d9d dgl/dgl-common.c.patch --- a/dgl/dgl-common.c.patch Sat Oct 05 17:10:24 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -504c504 -< int fd, len, n, is_nhext, pid; ---- -> int fd, len, n, is_nhext, is_node, pid; -538a539 -> is_node = strchr(pdirent->d_name, ':') && !strncmp(strchr(pdirent->d_name, ':'), ":node:", 6); -550c551 -< if (fd >= 0 && (is_nhext || fcntl (fd, F_SETLK, &fl) == -1)) ---- -> if (fd >= 0 && (is_nhext || is_node || fcntl (fd, F_SETLK, &fl) == -1)) -567a569,576 -> if (is_node) { -> replacestr = strchr(replacestr, ':'); -> if (!replacestr) { -> debug_write("inprogress-filename does not have ':', 1a"); -> graceful_exit(145); -> } -> replacestr++; -> } -589a599,602 -> if (is_node) { -> replacestr++; -> replacestr = strchr(replacestr, ':'); -> } diff -r 070a9ced4d3e -r ce26225f7d9d dgl/rlgwebd-compat.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dgl/rlgwebd-compat.patch Sun Oct 20 17:45:38 2013 -0700 @@ -0,0 +1,116 @@ +diff --git a/dgamelaunch.c b/dgamelaunch.c +index fbf6ef5..b52b545 100644 +--- a/dgamelaunch.c ++++ b/dgamelaunch.c +@@ -1489,7 +1489,10 @@ int + changepw (int dowrite) + { + char buf[DGL_PASSWDLEN+1]; ++ char salt[21]; + int error = 2; ++ int i; ++ FILE *urandom; + + /* A precondition is that struct `me' exists because we can be not-yet-logged-in. */ + if (!me) { +@@ -1553,8 +1556,28 @@ changepw (int dowrite) + error = 1; + } + ++ salt[0] = salt[2] = salt[19] = '$'; ++ salt[1] = '6'; ++ salt[20] = '\0'; ++ urandom = fopen("/dev/urandom", "r"); ++ for (i = 3; i < 19; i++) { ++ /* This does waste four random bytes. */ ++ fread(salt + i, 1, 1, urandom); ++ salt[i] &= 0x3f; ++ if (salt[i] < 26) ++ salt[i] += 'a'; ++ else if (salt[i] < 52) ++ salt[i] = 'A' + salt[i] - 26; ++ else if (salt[i] < 62) ++ salt[i] = '0' + salt[i] - 52; ++ else if (salt[i] == 62) ++ salt[i] = '.'; ++ else ++ salt[i] = '/'; ++ } ++ fclose(urandom); + free(me->password); +- me->password = strdup (crypt (buf, buf)); ++ me->password = strdup (crypt (buf, salt)); + + if (dowrite) + writefile (0); +@@ -2053,6 +2076,8 @@ passwordgood (char *cpw) + { + assert (me != NULL); + ++ if (!strncmp (crypt (cpw, me->password), me->password, DGL_PASSWDLEN)) ++ return 1; + if (!strncmp (crypt (cpw, cpw), me->password, DGL_PASSWDLEN)) + return 1; + if (!strncmp (cpw, me->password, DGL_PASSWDLEN)) +diff --git a/dgamelaunch.h b/dgamelaunch.h +index b9ce41c..ca5e11b 100644 +--- a/dgamelaunch.h ++++ b/dgamelaunch.h +@@ -20,7 +20,7 @@ + #define dglsign(x) (x < 0 ? -1 : (x > 0 ? 1 : 0)) + + #define DGL_PLAYERNAMELEN 30 /* max. length of player name */ +-#define DGL_PASSWDLEN 20 /* max. length of passwords */ ++#define DGL_PASSWDLEN 108 /* max. length of passwords */ + #define DGL_MAILMSGLEN 80 /* max. length of mail message */ + + #define DGL_MAXWATCHCOLS 10 +diff --git a/dgl-common.c b/dgl-common.c +index e5c80bc..fbc4eea 100644 +--- a/dgl-common.c ++++ b/dgl-common.c +@@ -593,7 +593,7 @@ game_read_extra_info(struct dg_game *game, const char *extra_info_file) + struct dg_game ** + populate_games (int xgame, int *l, struct dg_user *me) + { +- int fd, len, n, pid; ++ int fd, len, n, pid, is_node; + DIR *pdir; + struct dirent *pdirent; + struct stat pstat; +@@ -631,13 +631,15 @@ populate_games (int xgame, int *l, struct dg_user *me) + + if (!inprog) continue; + ++ is_node = strchr(pdirent->d_name, ':') && !strncmp(strchr(pdirent->d_name, ':'), ":node:", 6); ++ + snprintf (fullname, 130, "%s%s", inprog, pdirent->d_name); + + fd = 0; + /* O_RDWR here should be O_RDONLY, but we need to test for + * an exclusive lock */ + fd = open (fullname, O_RDWR); +- if (fd >= 0 && (fcntl (fd, F_SETLK, &fl) == -1)) ++ if (fd >= 0 && (is_node || (fcntl (fd, F_SETLK, &fl) == -1))) + { + char *ttrecdir = NULL; + strncpy(playername, pdirent->d_name, DGL_PLAYERNAMELEN); +@@ -651,6 +653,9 @@ populate_games (int xgame, int *l, struct dg_user *me) + graceful_exit(145); + } + replacestr++; ++ if (is_node) { ++ replacestr += 5; ++ } + + ttrecdir = dgl_format_str(game, me, myconfig[game]->ttyrecdir, playername); + if (!ttrecdir) continue; +@@ -673,6 +678,8 @@ populate_games (int xgame, int *l, struct dg_user *me) + strlcpy (games[len]->name, pdirent->d_name, + strlen (pdirent->d_name) + 1); + ++ if (is_node) ++ replacestr += 5; + games[len]->date = malloc (11); + strlcpy (games[len]->date, replacestr + 1, 11); +