/* * Determine if requester is allowed to update the given map, * and update it if so. Returns the yp status, which is zero * if there is no access violation. */ int mapupdate(char *requester, char *mapname, u_int op, u_int keylen, char *key, u_int datalen, char *data) { char updater[MAXMAPNAMELEN + 40]; FILE *childargs; FILE *childrslt; #ifdef WEXITSTATUS int status; #else union wait status; #endif pid_t pid; u_int yperrno; #ifdef DEBUG printf("%s %s\n", key, data); #endif (void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */ UPDATEFILE, mapname); pid = _openchild(updater, &childargs, &childrslt); if (pid < 0) { return (YPERR_YPERR); } /* * Write to child */ (void)fprintf(childargs, "%s\n", requester); (void)fprintf(childargs, "%u\n", op); (void)fprintf(childargs, "%u\n", keylen); (void)fwrite(key, (int)keylen, 1, childargs); (void)fprintf(childargs, "\n"); (void)fprintf(childargs, "%u\n", datalen); (void)fwrite(data, (int)datalen, 1, childargs); (void)fprintf(childargs, "\n"); (void)fclose(childargs); /* * Read from child */ (void)fscanf(childrslt, "%d", &yperrno); (void)fclose(childrslt); (void)wait(&status); #ifdef WEXITSTATUS if (WEXITSTATUS(status) != 0) #else if (status.w_retcode != 0) #endif return (YPERR_YPERR); return (yperrno); }
/* * Determine if requester is allowed to update the given map, * and update it if so. Returns the yp status, which is zero * if there is no access violation. */ int mapupdate(char *requester, char *mapname, u_int op, u_int keylen, char *key, u_int datalen, char *data) { char updater[MAXMAPNAMELEN + 40]; FILE *childargs; FILE *childrslt; #ifdef WEXITSTATUS int status; #else union wait status; #endif pid_t pid; u_int yperrno; #ifdef DEBUG printf("%s %s\n", key, data); #endif (void)sprintf(updater, "make -s -f %s/%s %s", YPDBPATH, /* !!! */ UPDATEFILE, mapname); pid = _openchild(updater, &childargs, &childrslt); if (pid < 0) { return (YPERR_YPERR); } /* * Write to child */ (void)fprintf(childargs, "%s\n", requester); (void)fprintf(childargs, "%u\n", op); (void)fprintf(childargs, "%u\n", keylen); (void)fwrite(key, (int)keylen, 1, childargs); (void)fprintf(childargs, "\n"); (void)fprintf(childargs, "%u\n", datalen); (void)fwrite(data, (int)datalen, 1, childargs); (void)fprintf(childargs, "\n"); (void)fclose(childargs); /* * Read from child */ (void)fscanf(childrslt, "%d", &yperrno); (void)fclose(childrslt); (void)wait(&status); #ifdef WEXITSTATUS if (WEXITSTATUS(status) != 0) { #else if (status.w_retcode != 0) { #endif return (YPERR_YPERR); } return (yperrno); } /* * returns pid, or -1 for failure */ static pid_t _openchild(char *command, FILE **fto, FILE **ffrom) { int i; pid_t pid; int pdto[2]; int pdfrom[2]; char *com; struct rlimit rl; if (pipe(pdto) < 0) { goto error1; } if (pipe(pdfrom) < 0) { goto error2; } switch (pid = fork()) { case -1: goto error3; case 0: /* * child: read from pdto[0], write into pdfrom[1] */ (void)close(0); (void)dup(pdto[0]); (void)close(1); (void)dup(pdfrom[1]); getrlimit(RLIMIT_NOFILE, &rl); for (i = rl.rlim_max - 1; i >= 3; i--) { (void) close(i); } com = malloc((unsigned) strlen(command) + 6); if (com == NULL) { _exit(~0); } (void)sprintf(com, "exec %s", command); execl(SHELL, basename(SHELL), "-c", com, (char *)NULL); _exit(~0); default: /* * parent: write into pdto[1], read from pdfrom[0] */ *fto = fdopen(pdto[1], "w"); (void)close(pdto[0]); *ffrom = fdopen(pdfrom[0], "r"); (void)close(pdfrom[1]); break; } return (pid); /* * error cleanup and return */ error3: (void)close(pdfrom[0]); (void)close(pdfrom[1]); error2: (void)close(pdto[0]); (void)close(pdto[1]); error1: return (-1); }
static int internal_function key_call_keyenvoy (u_long proc, xdrproc_t xdr_arg, char *arg, xdrproc_t xdr_rslt, char *rslt) { XDR xdrargs; XDR xdrrslt; FILE *fargs; FILE *frslt; sigset_t oldmask, mask; union wait status; int pid; int success; uid_t ruid; uid_t euid; static const char MESSENGER[] = "/usr/etc/keyenvoy"; success = 1; sigemptyset (&mask); sigaddset (&mask, SIGCHLD); __sigprocmask (SIG_BLOCK, &mask, &oldmask); /* * We are going to exec a set-uid program which makes our effective uid * zero, and authenticates us with our real uid. We need to make the * effective uid be the real uid for the setuid program, and * the real uid be the effective uid so that we can change things back. */ euid = __geteuid (); ruid = __getuid (); __setreuid (euid, ruid); pid = _openchild (MESSENGER, &fargs, &frslt); __setreuid (ruid, euid); if (pid < 0) { debug ("open_streams"); __sigprocmask (SIG_SETMASK, &oldmask, NULL); return (0); } xdrstdio_create (&xdrargs, fargs, XDR_ENCODE); xdrstdio_create (&xdrrslt, frslt, XDR_DECODE); if (!INTUSE(xdr_u_long) (&xdrargs, &proc) || !(*xdr_arg) (&xdrargs, arg)) { debug ("xdr args"); success = 0; } fclose (fargs); if (success && !(*xdr_rslt) (&xdrrslt, rslt)) { debug ("xdr rslt"); success = 0; } fclose(frslt); wait_again: if (__wait4 (pid, &status, 0, NULL) < 0) { if (errno == EINTR) goto wait_again; debug ("wait4"); if (errno == ECHILD || errno == ESRCH) perror ("wait"); else success = 0; } else if (status.w_retcode) { debug ("wait4 1"); success = 0; } __sigprocmask (SIG_SETMASK, &oldmask, NULL); return success; }
/* * Determine if requester is allowed to update the given map, * and update it if so. Returns the yp status, which is zero * if there is no access violation. */ int mapupdate(char *name, char *mapname, uint_t op, char *data) { char updater[MAXMAPNAMELEN + 40]; FILE *childargs; FILE *childrslt; #ifdef WEXITSTATUS int status; #else union wait status; #endif pid_t pid; uint_t yperrno; int namelen, datalen; struct stat stbuf; #ifdef DEBUG (void) fprintf(stderr, "%s %s\n", name, data); #endif namelen = strlen(name); datalen = strlen(data); errno = 0; if (stat(MAKE, &stbuf) < 0) switch (errno) { case ENOENT: (void) fprintf(stderr, "%s: %s not found, please install on the system\n", program_name, MAKE); return (1); default: (void) fprintf(stderr, "%s: cannot access %s, errno=%d.\n", program_name, MAKE, errno); return (1); } (void) sprintf(updater, "%s -s -f %s %s", MAKE, UPDATEFILE, mapname); pid = _openchild(updater, &childargs, &childrslt); if (pid < 0) return (YPERR_YPERR); /* * Write to child */ (void) fprintf(childargs, "%s\n", name); (void) fprintf(childargs, "%u\n", op); (void) fprintf(childargs, "%u\n", namelen); (void) fwrite(name, namelen, 1, childargs); (void) fprintf(childargs, "\n"); (void) fprintf(childargs, "%u\n", datalen); (void) fwrite(data, datalen, 1, childargs); (void) fprintf(childargs, "\n"); (void) fclose(childargs); /* * Read from child */ (void) fscanf(childrslt, "%d", &yperrno); (void) fclose(childrslt); (void) wait(&status); #ifdef WEXITSTATUS if (WEXITSTATUS(status) != 0) { #else if (status.w_retcode != 0) { #endif return (YPERR_YPERR); } return (yperrno); } /* * returns pid, or -1 for failure */ static int _openchild(char *command, FILE **fto, FILE **ffrom) { int i; pid_t pid; int pdto[2]; int pdfrom[2]; char *com; if (pipe(pdto) < 0) { goto error1; } if (pipe(pdfrom) < 0) { goto error2; } #ifdef VFORK switch (pid = vfork()) { #else switch (pid = fork()) { #endif case -1: goto error3; case 0: /* * child: read from pdto[0], write into pdfrom[1] */ (void) close(0); (void) dup(pdto[0]); (void) close(1); (void) dup(pdfrom[1]); closefrom(3); com = malloc((unsigned)strlen(command) + 6); if (com == NULL) { _exit(~0); } (void) sprintf(com, "exec %s", command); execl(SHELL, basename(SHELL), "-c", com, NULL); _exit(~0); default: /* * parent: write into pdto[1], read from pdfrom[0] */ *fto = fdopen(pdto[1], "w"); (void) close(pdto[0]); *ffrom = fdopen(pdfrom[0], "r"); (void) close(pdfrom[1]); break; } return (pid); /* * error cleanup and return */ error3: (void) close(pdfrom[0]); (void) close(pdfrom[1]); error2: (void) close(pdto[0]); (void) close(pdto[1]); error1: return (-1); } static char * basename(char *path) { char *p; p = strrchr(path, '/'); if (p == NULL) return (path); return (p + 1); }