From: ianmdlvl Date: Wed, 2 Jul 2003 18:49:48 +0000 (+0000) Subject: found on davenant in /usr/local/src/misc X-Git-Tag: debian_version_3_99_1_0_4~6 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-utils.git;a=commitdiff_plain;h=856172213e27f81e1d3a1a3d5585dd21c706bf90 found on davenant in /usr/local/src/misc --- diff --git a/cprogs/myopt.c~ b/cprogs/myopt.c~ new file mode 100644 index 0000000..b3c2167 --- /dev/null +++ b/cprogs/myopt.c~ @@ -0,0 +1,84 @@ +/* + * libdpkg - Debian packaging suite library routines + * myopt.c - my very own option parsing + * + * Copyright (C) 1994,1995 Ian Jackson + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include "config.h" +#include "myopt.h" +#include "dpkg.h" + +void myopt(const char *const **argvp, const struct cmdinfo *cmdinfos) { + const struct cmdinfo *cip; + const char *p, *value; + int l; + + ++(*argvp); + while ((p= **argvp) && *p == '-') { + ++(*argvp); + if (!strcmp(p,"--")) break; + if (*++p == '-') { + ++p; value=0; + for (cip= cmdinfos; + cip->olong || cip->oshort; + cip++) { + if (!cip->olong) continue; + if (!strcmp(p,cip->olong)) break; + l= strlen(cip->olong); + if (!strncmp(p,cip->olong,l) && + (p[l]== ((cip->takesvalue==2) ? '-' : '='))) { value=p+l+1; break; } + } + if (!cip->olong) badusage("unknown option --%s",p); + if (cip->takesvalue) { + if (!value) { + value= *(*argvp)++; + if (!value) badusage("--%s option takes a value",cip->olong); + } + if (cip->call) cip->call(cip,value); + else *cip->sassignto= value; + } else { + if (value) badusage("--%s option does not take a value",cip->olong); + if (cip->call) cip->call(cip,0); + else *cip->iassignto= cip->arg; + } + } else { + while (*p) { + for (cip= cmdinfos; (cip->olong || cip->oshort) && *p != cip->oshort; cip++); + if (!cip->oshort) badusage("unknown option -%c",*p); + p++; + if (cip->takesvalue) { + if (!*p) { + value= *(*argvp)++; + if (!value) badusage("-%c option takes a value",cip->oshort); + } else { + value= p; p=""; + if (*value == '=') value++; + } + if (cip->call) cip->call(cip,value); + else *cip->sassignto= value; + } else { + if (*p == '=') badusage("-%c option does not take a value",cip->oshort); + if (cip->call) cip->call(cip,0); + else *cip->iassignto= cip->arg; + } + } + } + } +} diff --git a/cprogs/myopt.h~ b/cprogs/myopt.h~ new file mode 100644 index 0000000..0b28d09 --- /dev/null +++ b/cprogs/myopt.h~ @@ -0,0 +1,41 @@ +/* + * libdpkg - Debian packaging suite library routines + * myopt.h - declarations for my very own option parsing + * + * Copyright (C) 1994,1995 Ian Jackson + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * This is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this file; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef MYOPT_H +#define MYOPT_H + +typedef void (*voidfnp)(void); + +struct cmdinfo { + const char *olong; + char oshort; + int takesvalue; /* 0 = normal 1 = standard value 2 = option string cont */ + int *iassignto; + const char **sassignto; + void (*call)(const struct cmdinfo*, const char *value); + int arg; + void *parg; + voidfnp farg; +}; + +void myopt(const char *const **argvp, const struct cmdinfo *cmdinfos); + +#endif /* MYOPT_H */ diff --git a/cprogs/really b/cprogs/really index 20536a5..bf862f5 100755 Binary files a/cprogs/really and b/cprogs/really differ diff --git a/cprogs/really.c b/cprogs/really.c index b240ea4..39fe8dd 100644 --- a/cprogs/really.c +++ b/cprogs/really.c @@ -6,8 +6,8 @@ #include #include #include -#include #include +#include #include "myopt.h" diff --git a/cprogs/really.c~ b/cprogs/really.c~ new file mode 100644 index 0000000..19e642e --- /dev/null +++ b/cprogs/really.c~ @@ -0,0 +1,209 @@ +/**/ + +#include +#include +#include +#include +#include +#include +#include + +#include "myopt.h" + +void usagemessage(void) { + if (fputs("usage: really [] [ ...] [--]" + " [ [ ...]]\n" + "user-options:\n" + " if no options given, set the uid to 0;\n" + " -u|--user also sets their default group list\n" + " -i|--useronly } set the uid\n" + " -I|--uidonly } but inherits the group list\n" + "group-options:\n" + " -z|--groupsclear only groups specified are to be used\n" + " -g|--group } add this to\n" + " -G|--gid } the group list\n", + stderr) == EOF) { perror("write usage"); exit(-1); } +} + +static const char *opt_user, *opt_useronly; +static int opt_groupsclear= 0, opt_ngids= 0, opt_uidonly= -1; +static int opt_gids[512]; + +static void af_group(const struct cmdinfo *cip, const char *value) { + struct group *gr; + + if (opt_ngids >= sizeof(opt_gids)/sizeof(opt_gids[0])) + badusage("too many groups specified"); + gr= getgrnam(value); + if (!gr) { fprintf(stderr,"unknown group `%s'\n",value); exit(-1); } + opt_gids[opt_ngids++]= gr->gr_gid; +} + +static void af_gid(const struct cmdinfo *cip, const char *value) { + char *ep; + unsigned long ul; + + if (opt_ngids >= sizeof(opt_gids)/sizeof(opt_gids[0])) + badusage("too many gids specified"); + ul= strtoul(value,&ep,0); + if ((*ep) || (uid_t)ul != ul || ul>INT_MAX) badusage("bad gid `%s'",value); + opt_gids[opt_ngids++]= ul; +} + +static void af_help(const struct cmdinfo *cip, const char *value) { + usagemessage(); exit(0); +} + +static const struct cmdinfo cmdinfos[]= { + { "user", 'u', 1, 0, &opt_user, 0, }, + { "useronly", 'i', 1, 0, &opt_useronly, 0 }, + { "uidonly", 'I', 1, &opt_uidonly, 0, 0 }, + { "groupsclear", 'z', 0, &opt_groupsclear, 0, 0, 1 }, + { "group", 'g', 1, 0, 0, af_group }, + { "gid", 'G', 1, 0, 0, af_gid }, + { "help", 'h', 0, 0, 0, af_help }, + { 0, 0 } +}; + +#ifdef REALLY_CHECK_FILE +void checkroot(void) { + int r; + r= access(REALLY_CHECK_FILE,W_OK); + if (r) { perror("sorry"); exit(-1); } +} +#endif +#ifdef REALLY_CHECK_GID +void checkroot(void) { + gid_t groups[512]; + int r; + + r= getgid(); if (r==REALLY_CHECK_GID) return; + if (r<0) { perror("getgid check"); exit(-1); } + r= getgroups(sizeof(groups)/sizeof(groups[0]),groups); + if (r<0) { perror("getgroups check"); exit(-1); } + for (i=0; ipw_uid; + } + orgmaingid= getgid(); + orgmainuid= getuid(); + if (orgmaingid<0) { perror("getgid failed"); exit(-1); } + if (opt_user) { + r= initgroups(opt_user,pw->pw_gid); + if (r) { perror("initgroups failed"); exit(-1); } + maingid= pw->pw_gid; + } else { + maingid= -1; + } + if (opt_groupsclear) { + ngroups= 0; + if (opt_ngids > sizeof(groups)/sizeof(groups[0])) { + fputs("too many groups to set\n",stderr); + exit(-1); + } + } else { + ngroups= getgroups(0,0); + if (ngroups<0) { perror("getgroups(0,0) failed"); exit(-1); } + if (ngroups+opt_ngids > sizeof(groups)/sizeof(groups[0])) { + fputs("too many groups already set for total to fit\n",stderr); + exit(-1); + } + ngroups= getgroups(ngroups,groups); + if (ngroups<0) { perror("getgroups failed"); exit(-1); } + } + if (opt_ngids) { + maingid= opt_gids[0]; + } + if (opt_ngids || opt_groupsclear) { + ngroups_in= ngroups; ngroups= 0; + for (i=0; i=0) { fputs("could seteuid 0",stderr); exit(-1); } + if (errno != EPERM) { + perror("unexpected failure mode for seteuid 0"); exit(-1); + } + } + r= getuid(); if (r<0) { perror("getuid failed"); exit(-1); } + if (r != mainuid) { fputs("getuid mismatch",stderr); exit(-1); } + r= geteuid(); if (r<0) { perror("geteuid failed"); exit(-1); } + if (r != mainuid) { fputs("geteuid mismatch",stderr); exit(-1); } + if (maingid != -1) { + for (i=0; i=ngroups && maingid != orgmaingid) { + r= setgid(orgmaingid); + if (r>=0) { fputs("could setgid back",stderr); exit(-1); } + if (errno != EPERM) { + perror("unexpected failure mode for setgid back"); exit(-1); + } + } + r= getgid(); if (r<0) { perror("getgid failed"); exit(-1); } + if (r != maingid) { fputs("getgid mismatch",stderr); exit(-1); } + r= getegid(); if (r<0) { perror("getegid failed"); exit(-1); } + if (r != maingid) { fputs("getegid mismatch",stderr); exit(-1); } + } + if (!*argv) { + cp= getenv("SHELL"); + if (!cp) cp= "sh"; + execlp(cp,cp,"-i",(const char*)0); + } else { + execvp(argv[0],(char**)argv); + } + perror("exec failed"); + exit(-1); +} diff --git a/cprogs/really.testcases~ b/cprogs/really.testcases~ new file mode 100755 index 0000000..b16758d --- /dev/null +++ b/cprogs/really.testcases~ @@ -0,0 +1,121 @@ +#!/usr/bin/perl + +$testuser= 'testac'; +$testgroup= 'testac'; +$testuid= 1000; +$testgid= 1000; +@testxgids= qw(1000); +$numgid= 50008; +$othergroup= 'daemon'; +$othergid= 1; + +$tests= < + +_syscall2(long,socketcall,int,call,unsigned long *,args); +int real_connect(int sockfd, const struct sockaddr *saddr, int addrlen) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long)saddr; + args[2] = addrlen; + return socketcall(SYS_CONNECT, args); +} + +int connect(int fd, struct sockaddr_in *them, int *addrlen) { + int r,l; + struct sockaddr_in us; + pid_t c; + + if (*addrlen == sizeof(us) && + them->sin_family == AF_INET && + them->sin_port == htons(13)) { + r= getsockname(fd,&us,&l); if (r<0) return r; + if (!ntohs(us.port)) { + for (i=1023; i>0; i++) { + us.port= htons(i); + if (!bind(fd,&us,sizeof(us))) break; + if (errno != EADDRINUSE) return -1; + } + if (!i) return -1; + } + } + return real_connect(fd,them,addrlen); +} diff --git a/cprogs/usr-local-src-misc-Makefile b/cprogs/usr-local-src-misc-Makefile index a1a96f2..c2bfd7a 100644 --- a/cprogs/usr-local-src-misc-Makefile +++ b/cprogs/usr-local-src-misc-Makefile @@ -2,10 +2,14 @@ CFLAGS= -Wall -Wwrite-strings -Wmissing-prototypes -Wstrict-prototypes \ -Wpointer-arith -O2 -g -DREALLY_CHECK_FILE='"/etc/inittab"' LDFLAGS= -TARGETS=really +TARGETS=really ucgi ucgitarget all: $(TARGETS) +ucgi: ucgi.o ucgicommon.o + +ucgitarget: ucgitarget.o ucgicommon.o + really: really.o myopt.o really-test: really Makefile