repo: games
action: commit
revision: 
path_from: 
revision_from: 464edcfc9df861311e6df40e1a545d92b1823c8b:
path_to: 
revision_to: 
git.thebackupbox.net
games
git clone git://git.thebackupbox.net/games
commit 464edcfc9df861311e6df40e1a545d92b1823c8b
Author: epoch 
Date:   Sat Apr 19 07:32:41 2025 +0000

    fix overflow through TTY env var in shoot. rewrite make-pond to do stuff itself.

diff --git a/duck/Makefile b/duck/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..4a42a19f33185579c55b5176fa298b9365951261
--- /dev/null
+++ b/duck/Makefile
@@ -0,0 +1,13 @@
+PREFIX:=/usr/local
+
+CFLAGS=-Wall -pedantic
+
+all: shoot make-pond
+
+install: all
+	install -t $(PREFIX)/bin shoot
+	chown duck:duck $(PREFIX)/bin/shoot
+	chmod u+s,g+s $(PREFIX)/bin/shoot
+	install -t $(PREFIX)/bin make-pond
+	chown root:duck $(PREFIX)/bin/make-pond
+	chmod u+s,o= $(PREFIX)/bin/make-pond
diff --git a/duck/make-pond.c b/duck/make-pond.c
new file mode 100644
index 0000000000000000000000000000000000000000..bf30f8102651990aec7eef67c6f38ab1a0151c08
--- /dev/null
+++ b/duck/make-pond.c
@@ -0,0 +1,27 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+// the script it runs is just mknod and chown. that should be easy for me to do.
+
+// /usr/bin/mknod /dev/pond c 4 0
+// /usr/bin/chown duck:duck /dev/pond
+
+int main(int argc,char *argv[]) {
+	char *pathname="/dev/pond";
+	mknod(pathname,S_IFCHR|0644,makedev(4,0));
+	struct passwd *pwd=getpwnam("duck");
+	if(!pwd) {
+		syslog(LOG_ERR,"duck user is missing!");
+	}
+	chown(pathname,pwd->pw_uid,pwd->pw_gid);
+	/*char *name[2];
+	name[0]="/etc/duck/MAKE_POND.sh";
+	name[1]=0;
+	execv(name[0],name);
+	perror("execve");*/
+	return 1;
+}
diff --git a/duck/shoot.c b/duck/shoot.c
new file mode 100644
index 0000000000000000000000000000000000000000..d6bca594e1ae0f8cee2794d6383cb7ddfaa9c5e7
--- /dev/null
+++ b/duck/shoot.c
@@ -0,0 +1,98 @@
+#include 
+#include  //strchr
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc,char *argv[]) {
+  FILE *fp;
+  int delta;
+  int l;
+  int duck_count=0;
+  char filename[PATH_MAX];
+  char tty[PATH_MAX];
+  //char remote_addr[PATH_MAX]="";
+  char identifier[PATH_MAX];
+  char duck[256];//long enough
+  char tmp[256];
+  char *user;
+  time_t t=time(0);
+//  struct passwd *pwd=getpwuid(getuid());
+//  printf("%s\n",pwd->pw_name);
+// what we need to do...
+// if there exists a duck in the wild
+  user=getenv("USER");
+  if(!user) {
+    struct passwd *pwd=getpwuid(getuid());
+    if(!pwd) {
+      fprintf(stderr,"shoot: USER env var is unset, and I can't find a username for your uid. who the fuck are you?\n");
+      return 5;
+    }
+    user=pwd->pw_name;
+  }
+
+  if((l=readlink("/proc/self/fd/0",tty,PATH_MAX)) == -1) {
+    fprintf(stderr,"failed to get your terminal, but you still have the duck.\n");
+    return 3;
+  } else {
+    tty[l]=0;
+  }
+  if(!strcmp(tty,"/dev/null") && getenv("TTY")) { //only allow env override if /dev/null
+    snprintf(tty,PATH_MAX,"%s",getenv("TTY"));
+  }
+  if(!strncmp("/dev/",tty,5)) {
+    memmove(tty,tty+5,strlen(tty));
+  }
+
+  if(strcmp(tty,"null")) {
+    if(getenv("REMOTE_ADDR"))  { //remote users
+      snprintf(identifier,PATH_MAX,"talk://%s@%s/%s",user,getenv("REMOTE_ADDR"),tty);
+    } else { //local users in a tty
+      snprintf(identifier,PATH_MAX,"talk://%s@%s/%s",user,"batou",tty);
+    }
+  } else { //IRC users
+    snprintf(identifier,PATH_MAX,"IRC user %s",user);
+  }
+
+  if((fp=fopen("/var/cache/duck/duck_time","r")) == NULL) {
+    fprintf(stderr,"shoot: %s, there is no duck to shoot\n",identifier);
+    return 1;
+  }
+  l=fread(duck,sizeof(char),sizeof(duck),fp);//it'll actually read less than duck.
+//  fprintf(stderr,"read duck: '%s'\n",duck);
+  fclose(fp);
+  unlink("/var/cache/duck/duck_time");
+  snprintf(filename,PATH_MAX,"/var/items/duck/%s",user);// user can be injected with USER= and stdin being null.
+  if((fp=fopen(filename,"a")) == NULL) {
+    fprintf(stderr,"shoot: unable to put the duck in your inventory (%s)\n",filename);
+    return 2;
+  }
+  if(strchr(duck,'\n')) *strchr(duck,'\n')=0;
+  fprintf(fp,"%s %ld\n",duck,t);
+  fclose(fp);
+  duck_count=0;
+  fp=fopen(filename,"r");//assume it'll work. we made it here with 'a' earlier
+  for(duck_count=0;fgets(tmp,sizeof(tmp)-1,fp);duck_count++);
+  fclose(fp);
+  printf("%s shot the duck\n",user);
+
+  if((fp=fopen("/home/segfault/files/default","a")) == NULL) {
+    fprintf(stderr,"shoot: couldn't open the file for telling IRC about your kill\n");
+    return 4;
+  }
+
+  delta=time(0) - atoi(duck);
+
+  if(strcmp(tty,"null")) {
+    fprintf(fp,"%s shot the duck from their terminal %s after %d seconds and now has %d ducks\n",user,tty,delta,duck_count);
+    fprintf(stderr,"%s shot the duck from their terminal %s after %d seconds and now has %d ducks\n",user,tty,delta,duck_count);
+  } else {
+    fprintf(fp,"%s shot the duck after %d seconds and now has %d ducks\n",user,delta,duck_count);
+    fprintf(stderr,"%s shot the duck after %d seconds and now has %d ducks\n",user,delta,duck_count);
+  }
+  fclose(fp);
+  return 0;
+}

-----END OF PAGE-----