Exemplo n.º 1
0
Arquivo: elfload.c Projeto: CPFL/gxen
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
                                   struct elfhdr * exec,
                                   abi_ulong load_addr,
                                   abi_ulong load_bias,
                                   abi_ulong interp_load_addr, int ibcs,
                                   struct image_info *info)
{
        abi_ulong sp;
        int size;
        abi_ulong u_platform;
        const char *k_platform;
        const int n = sizeof(elf_addr_t);

        sp = p;
        u_platform = 0;
        k_platform = ELF_PLATFORM;
        if (k_platform) {
            size_t len = strlen(k_platform) + 1;
            sp -= (len + n - 1) & ~(n - 1);
            u_platform = sp;
            /* FIXME - check return value of memcpy_to_target() for failure */
            memcpy_to_target(sp, k_platform, len);
        }
        /*
         * Force 16 byte _final_ alignment here for generality.
         */
        sp = sp &~ (abi_ulong)15;
        size = (DLINFO_ITEMS + 1) * 2;
        if (k_platform)
          size += 2;
#ifdef DLINFO_ARCH_ITEMS
        size += DLINFO_ARCH_ITEMS * 2;
#endif
        size += envc + argc + 2;
        size += (!ibcs ? 3 : 1);        /* argc itself */
        size *= n;
        if (size & 15)
            sp -= 16 - (size & 15);

        /* This is correct because Linux defines
         * elf_addr_t as Elf32_Off / Elf64_Off
         */
#define NEW_AUX_ENT(id, val) do {               \
            sp -= n; put_user_ual(val, sp);     \
            sp -= n; put_user_ual(id, sp);      \
          } while(0)

        NEW_AUX_ENT (AT_NULL, 0);

        /* There must be exactly DLINFO_ITEMS entries here.  */
        NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
        NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
        NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
        NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
        NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
        NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
        NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
        NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
        NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
        NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
        NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
        NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
        NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
        if (k_platform)
            NEW_AUX_ENT(AT_PLATFORM, u_platform);
#ifdef ARCH_DLINFO
        /*
         * ARCH_DLINFO must come last so platform specific code can enforce
         * special alignment requirements on the AUXV if necessary (eg. PPC).
         */
        ARCH_DLINFO;
#endif
#undef NEW_AUX_ENT

        sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
        return sp;
}
Exemplo n.º 2
0
static KMETHOD System_getegid(KonohaContext *kctx, KonohaStack *sfp)
{
	KReturnUnboxValue(getegid());
}
static int program_client_local_connect
(struct program_client *pclient)
{
	struct program_client_local *slclient = 
		(struct program_client_local *) pclient;
	int fd[2] = { -1, -1 };
	struct program_client_extra_fd *efds = NULL;
	int *parent_extra_fds = NULL, *child_extra_fds = NULL;
	unsigned int xfd_count = 0, i;

	/* create normal I/O fd */
	if ( pclient->input != NULL || pclient->output != NULL ||
		pclient->output_seekable ) {
		if ( socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0 ) {
			i_error("socketpair() failed: %m");
			return -1;
		}
	}

	/* create pipes for additional output through side-channel fds */
	if ( array_is_created(&pclient->extra_fds) ) {
		int extra_fd[2];
		
		efds = array_get_modifiable(&pclient->extra_fds, &xfd_count);
		if (	xfd_count > 0 ) {
			parent_extra_fds = t_malloc(sizeof(int) * xfd_count);
			child_extra_fds = t_malloc(sizeof(int) * xfd_count * 2 + 1);
			for ( i = 0; i < xfd_count; i++ ) {
				if ( pipe(extra_fd) < 0 ) {
					i_error("pipe() failed: %m");
					return -1;
				}
				parent_extra_fds[i] = extra_fd[0];
				child_extra_fds[i*2+0] = extra_fd[1];
				child_extra_fds[i*2+1] = efds[i].child_fd;
			}
			child_extra_fds[xfd_count*2] = -1;
		}
	}

	/* fork child */
	if ( (slclient->pid = fork()) == (pid_t)-1 ) {
		i_error("fork() failed: %m");

		/* clean up */
		if ( fd[0] >= 0 && close(fd[0]) < 0 ) {
			i_error("close(pipe_fd[0]) failed: %m");
		}
		if ( fd[1] >= 0 && close(fd[1]) < 0 ) {
			i_error("close(pipe_fd[1]) failed: %m");
		}
		for ( i = 0; i < xfd_count; i++ ) {
			if ( close(child_extra_fds[i*2]) < 0 ) {
				i_error("close(extra_fd[1]) failed: %m");
			}
			if ( close(parent_extra_fds[i]) < 0 ) {
				i_error("close(extra_fd[0]) failed: %m");
			}
		}
		return -1;
	}

	if ( slclient->pid == 0 ) {
		unsigned int count;
		const char *const *envs = NULL;

		/* child */
		if ( fd[1] >= 0 && close(fd[1]) < 0 ) {
			i_error("close(pipe_fd[1]) failed: %m");
		}
		for ( i = 0; i < xfd_count; i++ ) {
			if ( close(parent_extra_fds[i]) < 0 )
				i_error("close(extra_fd[0]) failed: %m");
		}

		/* drop privileges if we have any */
		if ( getuid() == 0 ) {
			uid_t uid;
			gid_t gid;

			/* switch back to root */
			if (seteuid(0) < 0)
				i_fatal("seteuid(0) failed: %m");

			/* drop gids first */
			gid = getgid();
			if ( gid == 0 || gid != pclient->set.gid ) {
				if ( pclient->set.gid != 0 )
					gid = pclient->set.gid;
				else
					gid = getegid();
			}
	    if ( setgroups(1, &gid) < 0 )
				i_fatal("setgroups(%d) failed: %m", gid);
			if ( gid != 0 && setgid(gid) < 0 )
				i_fatal("setgid(%d) failed: %m", gid);
		
			/* drop uid */
			if ( pclient->set.uid != 0 )
				uid = pclient->set.uid;
			else
				uid = geteuid();
			if ( uid != 0 && setuid(uid) < 0 )
				i_fatal("setuid(%d) failed: %m", uid);
		}

		i_assert(pclient->set.uid == 0 || getuid() != 0);
		i_assert(pclient->set.gid == 0 || getgid() != 0);

		if ( array_is_created(&pclient->envs) )
			envs = array_get(&pclient->envs, &count);

		exec_child(pclient->path, pclient->args, envs,
			( pclient->input != NULL ? fd[0] : -1 ),
			( pclient->output != NULL || pclient->output_seekable ? fd[0] : -1 ),
			child_extra_fds, pclient->set.drop_stderr);
		i_unreached();
	}

	/* parent */
	if ( fd[0] >= 0 && close(fd[0]) < 0 )
		i_error("close(pipe_fd[0]) failed: %m");
	if ( fd[1] >= 0 ) {
		net_set_nonblock(fd[1], TRUE);
		pclient->fd_in =
			( pclient->output != NULL || pclient->output_seekable ? fd[1] : -1 );
		pclient->fd_out = ( pclient->input != NULL ? fd[1] : -1 );
	}
	for ( i = 0; i < xfd_count; i++ ) {
		if ( close(child_extra_fds[i*2]) < 0 )
			i_error("close(extra_fd[1]) failed: %m");
		net_set_nonblock(parent_extra_fds[i], TRUE);
		efds[i].parent_fd = parent_extra_fds[i];
	}

	program_client_init_streams(pclient);
	return program_client_connected(pclient);
}
Exemplo n.º 4
0
static int process_mount(struct fuse_client * c)
{
	struct afp_server_mount_request * req;
	struct afp_server  * s=NULL;
	struct afp_volume * volume;
	struct afp_connection_request conn_req;
	int ret;
	struct stat lstat;

	if ((c->incoming_size-1) < sizeof(struct afp_server_mount_request)) 
		goto error;

	req=(void *) c->incoming_string+1;

	/* Todo should check the existance and perms of the mount point */

	if ((ret=access(req->mountpoint,X_OK))!=0) {
		log_for_client((void *)c,AFPFSD,LOG_DEBUG,
			"Incorrect permissions on mountpoint %s: %s\n",
			req->mountpoint, strerror(errno));

		goto error;
	}

	if (stat(FUSE_DEVICE,&lstat)) {
		printf("Could not find %s\n",FUSE_DEVICE);
		goto error;
	}

	if (access(FUSE_DEVICE,R_OK | W_OK )!=0) {
		log_for_client((void *)c, AFPFSD,LOG_NOTICE, 
			"Incorrect permissions on %s, mode of device"
			" is %o, uid/gid is %d/%d.  But your effective "
			"uid/gid is %d/%d\n", 
				FUSE_DEVICE,lstat.st_mode, lstat.st_uid, 
				lstat.st_gid, 
				geteuid(),getegid());
		goto error;
	}

	log_for_client((void *)c,AFPFSD,LOG_NOTICE,
		"Mounting %s from %s on %s\n",
		(char *) req->url.servername, 
		(char *) req->url.volumename,req->mountpoint);

	if ((afp_default_connection_request(&conn_req,&req->url))==-1) {
		log_for_client((void *)c,AFPFSD,LOG_ERR,
			"Unknown UAM");
		return -1;
	}

	conn_req.uam_mask=req->uam_mask;

	if ((s=afp_server_full_connect(c,&conn_req))==NULL) {
		signal_main_thread();
		goto error;
	}
	
	if ((volume=mount_volume(c,s,req->url.volumename,
		req->url.volpassword))==NULL) {
		goto error;
	}

	volume->extra_flags|=req->volume_options;

	volume->mapping=req->map;
	afp_detect_mapping(volume);

	snprintf(volume->mountpoint,255,req->mountpoint);

	/* Create the new thread and block until we get an answer back */
	{
		pthread_mutex_t mutex;
		struct timespec ts;
		struct timeval tv;
		int ret;
		struct start_fuse_thread_arg arg;
		memset(&arg,0,sizeof(arg));
		arg.client = c;
		arg.volume = volume;
		arg.wait = 1;
		arg.changeuid=req->changeuid;

		gettimeofday(&tv,NULL);
		ts.tv_sec=tv.tv_sec;
		ts.tv_sec+=5;
		ts.tv_nsec=tv.tv_usec*1000;
		pthread_mutex_init(&mutex,NULL);
		pthread_cond_init(&volume->startup_condition_cond,NULL);

		/* Kickoff a thread to see how quickly it exits.  If
		 * it exits quickly, we have an error and it failed. */

		pthread_create(&volume->thread,NULL,start_fuse_thread,&arg);

		if (arg.wait) ret = pthread_cond_timedwait(
				&volume->startup_condition_cond,&mutex,&ts);

		report_fuse_errors(c);
		
		switch (arg.fuse_result) {
		case 0:
		if (volume->mounted==AFP_VOLUME_UNMOUNTED) {
			/* Try and discover why */
			switch(arg.fuse_errno) {
			case ENOENT:
				log_for_client((void *)c,AFPFSD,LOG_ERR,
					"Permission denied, maybe a problem with the fuse device or mountpoint?\n");
				break;
			default:
				log_for_client((void *)c,AFPFSD,LOG_ERR,
					"Mounting of volume %s of server %s failed.\n", 
						volume->volume_name_printable, 
						volume->server->server_name_printable);
			}
			goto error;
		} else {
			log_for_client((void *)c,AFPFSD,LOG_NOTICE,
				"Mounting of volume %s of server %s succeeded.\n", 
					volume->volume_name_printable, 
					volume->server->server_name_printable);
			return 0;
		}
		break;
		case ETIMEDOUT:
			log_for_client((void *)c,AFPFSD,LOG_NOTICE,
				"Still trying.\n");
			return 0;
			break;
		default:
			volume->mounted=AFP_VOLUME_UNMOUNTED;
			log_for_client((void *)c,AFPFSD,LOG_NOTICE,
				"Unknown error %d, %d.\n", 
				arg.fuse_result,arg.fuse_errno);
			goto error;
		}

	}
	return AFP_SERVER_RESULT_OKAY;
error:
	if ((s) && (!something_is_mounted(s))) {
		afp_server_remove(s);
	}
	signal_main_thread();
	return AFP_SERVER_RESULT_ERROR;
}
Exemplo n.º 5
0
/* Modify the auxv the kernel gave us to make it look like we were
   execed as the shared object.

   This also inserts a new entry into the auxv table so we can
   communicate some extra information to stage2 (namely, the fd of the
   padding file, so it can identiry and remove the padding later).
*/
static void *fix_auxv(void *v_init_esp, const struct exeinfo *info,
                      int padfile)
{
    struct ume_auxv *auxv;
    int *newesp;
    int seen;
    int delta;
    int i;
#if defined(VGO_netbsdelf2)
    static const int new_entries = 14;
#else
    static const int new_entries = 2;
#endif
    /* make sure we're running on the private stack */
    assert(&delta >= stack && &delta < &stack[sizeof(stack)/sizeof(*stack)]);

    /* find the beginning of the AUXV table */
    auxv = find_auxv(v_init_esp);
    printf("auxv[0].u.a_val : %d, auxv[0].a_type : %d\n",auxv[0].u.a_val, auxv[0].a_type);
    /* Work out how we should move things to make space for the new
       auxv entry. It seems that ld.so wants a 16-byte aligned stack on
       entry, so make sure that's the case. */
#if defined(VGO_netbsdelf2)
    newesp = (int *)(((unsigned long)v_init_esp - new_entries * sizeof(*auxv)));
#else
    newesp = (int *)(((unsigned long)v_init_esp - new_entries * sizeof(*auxv)) & ~0xf);
#endif
    delta = (char *)v_init_esp - (char *)newesp;

    memmove(newesp, v_init_esp, (char *)auxv - (char *)v_init_esp);

    v_init_esp = (void *)newesp;
    /* we need to see whats the size of delta, we are freeing up space to
       throw our own auxv headers in 3, */
    printf("Space for auxv %d\n",delta/sizeof(*auxv));
    printf("sizeof delta :%d , sizeof auxv : %d\n",delta, sizeof(*auxv));
    /* if auxv is not aligned, we move it backward till its aligned. We
       find out how much space is required, walk tmp_auxv to the last auxv
       entry.  then move the junk forward. Remeber that the AT_NULL entry
       also needs to be moved forward. */

    /*    if( ( delta%sizeof(*auxv) ) != 0 ) */
    /*     {	    int j = 0; */
    /*     printf("adjusting auxv\n"); */
    /* 	    struct ume_auxv* tmp = auxv; /\* to top *\/ */
    /* 	    void * new_auxv = (void *) auxv - delta%(sizeof(*auxv)); */
    /* 	    for (j=0; tmp->a_type != AT_NULL;j++,tmp++ ); */
    /* 	    memmove( new_auxv,auxv,(j+1)* sizeof(*auxv) ); */
    /* 	    auxv = (struct ume_auxv *)new_auxv; */
    /*     } */
    auxv -= delta/sizeof(*auxv) ; /* move it back even further for 2
				  * new */

    /* stage2 needs this so it can clean up the padding we leave in
       place when we start it */
    auxv[0].a_type = AT_UME_PADFD;
    auxv[0].u.a_val = padfile;
    /* This will be needed by valgrind itself so that it can
       subsequently execve() children.  This needs to be done here
       because /proc/self/exe will go away once we unmap stage1. */
    auxv[1].a_type = AT_UME_EXECFD;
#if defined(VGO_netbsdelf2)
    auxv[1].u.a_val = open("/proc/curproc/file", O_RDONLY);
    /* fill in the rest */
    auxv[2].a_type= AT_PHDR;
    auxv[2].u.a_val = info->phdr;
    auxv[3].a_type = AT_PHNUM;
    auxv[3].u.a_val = info->phnum;
    auxv[4].a_type = AT_BASE;
    auxv[4].u.a_val = info->interp_base;
    auxv[5].a_type = AT_ENTRY;
    auxv[5].u.a_val = info->entry;
    auxv[6].a_type = AT_PAGESZ;
    auxv[6].u.a_val = 4096;
    auxv[7].a_type = AT_PHENT;
    auxv[7].u.a_val = 32; /*sizeof(info->phdr);*/
    auxv[8].a_type = AT_FLAGS;
    auxv[8].u.a_val = 0; /* ? */
    auxv[9].a_type = AT_EUID;
    auxv[9].u.a_val = geteuid();
    auxv[10].a_type = AT_RUID;
    auxv[10].u.a_val = getuid();
    auxv[11].a_type = AT_EGID;
    auxv[11].u.a_val = getegid();
    auxv[12].a_type = AT_RGID;
    auxv[12].u.a_val = getgid();
    auxv[13].a_type = AT_NULL;
#else
    auxv[1].u.a_val = open("/proc/self/exe", O_RDONLY);
#endif

    /* make sure the rest are sane */
    for(i = new_entries; i < delta/sizeof(*auxv); i++) {
        auxv[i].a_type = AT_IGNORE;
        auxv[i].u.a_val = 0;
    }

    /* OK, go through and patch up the auxv entries to match the new
       executable */
    seen = 0;
    for(; auxv->a_type != AT_NULL; auxv++) {
        if (1)
            printf("doing auxv %p %5lld: %p \n",
                   auxv, (Long)auxv->a_type, (Long)auxv->u.a_val);
        /* 	   if(seen == 0xf) */
        /* 		   break; */
        switch(auxv->a_type) {
        case AT_PHDR:
            printf("seen 1\n");
            seen |= 1;
            auxv->u.a_val = info->phdr;
            break;

        case AT_PHNUM:
            printf("seen 2\n");
            seen |= 2;
            auxv->u.a_val = info->phnum;
            break;

        case AT_BASE:
            printf("seen 4\n");
            seen |= 4;
            auxv->u.a_val = info->interp_base;
            break;

        case AT_ENTRY:
            printf("seen 8\n");
            seen |= 8;
            auxv->u.a_val = info->entry;
            break;

        default:
            break;

        }
        if (1)
            printf("new auxv %p %5lld: %p \n",
                   auxv, (Long)auxv->a_type, (Long)auxv->u.a_val);

    }

    /* If we didn't see all the entries we need to fix up, then we
       can't make the new executable viable. */
    if (seen != 0xf) {
        fprintf(stderr, "valgrind: we didn't see enough auxv entries (seen=%x)\n", seen);
        exit(1);
    }

    return v_init_esp;
}
Exemplo n.º 6
0
int
fork_execvp0(const char *file, char *const argv[], u_int flags)
{
  if (strchr (file, '/') == NULL)
    {
      char *path, *p;
      struct stat st;
      size_t len;
      uid_t uid;
      gid_t gid;
      int ngroups;
      gid_t groups[NGROUPS_MAX];
      char *name;
 
      path = getenv ("PATH");
      if (path == NULL)
        {
          /* There is no `PATH' in the environment.
             The default search path is the current directory
             followed by the path `confstr' returns for `_CS_PATH'.  
	     We will just search current directory */
	  
	  path = ".";
        }
 
      len = strlen (file) + 1;
      name = alloca (strlen (path) + len);
      uid = geteuid ();
      gid = getegid ();
      ngroups = getgroups (sizeof (groups) / sizeof (groups[0]), groups);
      p = path;
      do
        {
          path = p;
          p = strchr (path, ':');
          if (p == NULL)
            p = strchr (path, '\0');
 
          if (p == path)
            /* Two adjacent colons, or a colon at the beginning or the end
               of `PATH' means to search the current directory.  */
            (void) memcpy (name, file, len);
          else
            {
              /* Construct the pathname to try.  */
              (void) memcpy (name, path, p - path);
              name[p - path] = '/';
              (void) memcpy (&name[(p - path) + 1], file, len);
            }
          if (stat (name, &st) == 0 && S_ISREG (st.st_mode))
            {
              int bit = S_IXOTH;
              if (st.st_uid == uid)
                bit = S_IXUSR;
              else if (st.st_gid == gid)
                bit = S_IXGRP;
              else
                {
                  register int i;
                  for (i = 0; i < ngroups; ++i)
                    if (st.st_gid == groups[i])
                      {
                        bit = S_IXGRP;
                        break;
                      }
                }
              if (st.st_mode & bit)
                {
                  file = name;
                  break;
                }
            }
        }
      while (*p++ != '\0');
    }
 
  return fork_execve0(file, argv, environ, -1, flags);
}
Exemplo n.º 7
0
int
main (int argc, char **argv)
{
	char *diskType = "auto";
	char *imagefilename = NULL;
	char *mountpoint = NULL;
	int debug = 0;
	int foreground = 0;
	char c;
	int i;
	char *differencing[DIFFERENCING_MAX];
	int differencingLen = 0;

	extern char *optarg;
	extern int optind;

//
// *** Parse the command line options ***
//
	processName = argv[0];

	while ((c = getopt (argc, argv, GETOPT_ARGS)) != -1)
	{
		switch (c)
		{
			case 'r':
				readonly = 1;
				break;
			case 'g':
				foreground = 1;
				break;
			case 'v':
				verbose = 1;
				break;
			case 'a':
				allowall = 1;
				break;
			case 'w':
				allowall = 1;
				allowallw = 1;
				break;
			case 't':
				diskType = (char *) optarg;
				break;									// ignored if OLDAPI
			case 's':
				if (differencingLen == DIFFERENCING_MAX)
					usageAndExit ("Too many differencing disks");
				differencing[differencingLen++] = (char *) optarg;
				break;
			case 'f':
				imagefilename = (char *) optarg;
				break;
			case 'd':
				foreground = 1;
				debug = 1;
				break;
			case 'h':
				usageAndExit (NULL);
			case '?':
				usageAndExit ("Unknown option");
		}
	}
//
// *** Validate the command line ***
//
	if (argc != optind + 1)
		usageAndExit ("a single mountpoint must be specified");
	mountpoint = argv[optind];
	if (!mountpoint)
		usageAndExit ("no mountpoint specified");
	if (!imagefilename)
		usageAndExit ("no image chosen");
	if (stat (imagefilename, &VDfile_stat) < 0)
		usageAndExit ("cannot access imagefile");
	if (access (imagefilename, F_OK | R_OK | ((!readonly) ? W_OK : 0)) < 0)
		usageAndExit ("cannot access imagefile");
	for (i = 0; i < differencingLen; i++)
		if (access (differencing[i], F_OK | R_OK | ((readonly) ? 0 : W_OK)) < 0)
			usageAndExit ("cannot access differencing imagefile %s",
										differencing[i]);

#define IS_TYPE(s) (strcmp (s, diskType) == 0)
	if (!
			(IS_TYPE ("auto") || IS_TYPE ("VDI") || IS_TYPE ("VMDK")
			 || IS_TYPE ("VHD") || IS_TYPE ("auto")))
		usageAndExit ("invalid disk type specified");
	if (strcmp ("auto", diskType) == 0
			&& detectDiskType (&diskType, imagefilename) < 0)
		return 1;

//
// *** Open the VDI, parse the MBR + EBRs and connect to the fuse service ***
//
	if (RT_FAILURE (VDInterfaceAdd (&vdError, "VD Error", VDINTERFACETYPE_ERROR,
																	&vdErrorCallbacks, NULL, &pVDifs)))
		usageAndExit ("invalid initialisation of VD interface");
	if (RT_FAILURE (VDCreate (&vdError, VDTYPE_HDD, &hdDisk)))
		usageAndExit ("invalid initialisation of VD interface");
	DISKopen (diskType, imagefilename);

	for (i = 0; i < differencingLen; i++)
	{
		char *diffType;
		char *diffFilename = differencing[i];
		detectDiskType (&diffType, diffFilename);
		DISKopen (diffType, diffFilename);
	}

	initialisePartitionTable ();

	myuid = geteuid ();
	mygid = getegid ();

	fuse_opt_add_arg (&fuseArgs, "vdfuse");

	{
		char fsname[strlen (imagefilename) + 12];
		strcpy (fsname, "-ofsname=\0");
		strcat (fsname, imagefilename);
		fuse_opt_add_arg (&fuseArgs, fsname);
	}

	fuse_opt_add_arg (&fuseArgs, "-osubtype=vdfuse");
	fuse_opt_add_arg (&fuseArgs, "-o");
	fuse_opt_add_arg (&fuseArgs, (allowall) ? "allow_other" : "allow_root");
	if (foreground)
		fuse_opt_add_arg (&fuseArgs, "-f");
	if (debug)
		fuse_opt_add_arg (&fuseArgs, "-d");
	fuse_opt_add_arg (&fuseArgs, mountpoint);

	return fuse_main (fuseArgs.argc, fuseArgs.argv, &fuseOperations
#if FUSE_USE_VERSION >= 26
										, NULL
#endif
		);
}
Exemplo n.º 8
0
CAMLprim value unix_getegid(value unit)
{
  return Val_int(getegid());
}
Exemplo n.º 9
0
END_TEST
#endif

START_TEST(test_become_the_user)
  {
  int rc;
  job *pjob;
  int uid;
  int gid;

  // must be root to run this test
  if (getuid() != 0)
    return;

  pjob = (job *)calloc(1, sizeof(job));
  fail_unless(pjob != NULL);

  pjob->ji_grpcache = (struct grpcache *)calloc(1, sizeof(struct grpcache));
  fail_unless(pjob->ji_grpcache != NULL);

  pjob->ji_qs.ji_un.ji_momt.ji_exuid = 500;
  pjob->ji_qs.ji_un.ji_momt.ji_exgid = 500;

  pjob->ji_grpcache->gc_ngroup = 1;
  pjob->ji_grpcache->gc_groups[0] = 500;

  // fork so we can test the setxid/setexid calls in the child
  rc = fork();
  fail_unless(rc != -1);

  if (rc > 0)
    {
    int status;

    // parent
    wait(&status);
    return;
    }

  // child
  
  rc = become_the_user(pjob, true);
  fail_unless(rc == PBSE_NONE);

  // check the group list, uid, gid
  uid = geteuid();
  gid = getegid();
  fail_unless(uid != 500);
  fail_unless(gid != 500);

  // put things back in place
  fail_unless(seteuid(0) == 0);
  fail_unless(setegid(0) == 0);

  rc = become_the_user(pjob, false);
  fail_unless(rc == PBSE_NONE);

  // check the uid, gid
  uid = getuid();
  gid = getgid();
  fail_unless(uid != 500);
  fail_unless(gid != 500);
  }
Exemplo n.º 10
0
FILE *
opencal(void)
{
	uid_t uid;
	size_t i;
	int fd, found, pdes[2];
	struct stat sbuf;

	/* open up calendar file as stdin */
	if (!freopen(calendarFile, "r", stdin)) {
		if (doall) {
			if (chdir(calendarHomes[0]) != 0)
				return (NULL);
			if (stat(calendarNoMail, &sbuf) == 0)
				return (NULL);
			if (!freopen(calendarFile, "r", stdin))
				return (NULL);
		} else {
			char *home = getenv("HOME");
			if (home == NULL || *home == '\0')
				errx(1, "cannot get home directory");
			if (chdir(home) != 0)
				errx(1, "cannot enter home directory");
			for (found = i = 0; i < sizeof(calendarHomes) /
			    sizeof(calendarHomes[0]); i++)
				if (chdir(calendarHomes[i]) == 0 &&
				    freopen(calendarFile, "r", stdin)) {
					found = 1;
					break;
				}
			if (!found)
				errx(1,
				    "can't open calendar file \"%s\": %s (%d)",
				    calendarFile, strerror(errno), errno);
		}
	}
	if (pipe(pdes) < 0)
		return (NULL);
	switch (fork()) {
	case -1:			/* error */
		(void)close(pdes[0]);
		(void)close(pdes[1]);
		return (NULL);
	case 0:
		/* child -- stdin already setup, set stdout to pipe input */
		if (pdes[1] != STDOUT_FILENO) {
			(void)dup2(pdes[1], STDOUT_FILENO);
			(void)close(pdes[1]);
		}
		(void)close(pdes[0]);
		uid = geteuid();
		if (setuid(getuid()) < 0) {
			warnx("first setuid failed");
			_exit(1);
		};
		if (setgid(getegid()) < 0) {
			warnx("setgid failed");
			_exit(1);
		}
		if (setuid(uid) < 0) {
			warnx("setuid failed");
			_exit(1);
		}
		execl(_PATH_CPP, "cpp", "-P",
		    "-traditional", "-nostdinc",	/* GCC specific opts */
		    "-I.", "-I", _PATH_INCLUDE, (char *)NULL);
		warn(_PATH_CPP);
		_exit(1);
	}
	/* parent -- set stdin to pipe output */
	(void)dup2(pdes[0], STDIN_FILENO);
	(void)close(pdes[0]);
	(void)close(pdes[1]);

	/* not reading all calendar files, just set output to stdout */
	if (!doall)
		return (stdout);

	/* set output to a temporary file, so if no output don't send mail */
	(void)snprintf(path, sizeof(path), "%s/_calXXXXXX", _PATH_TMP);
	if ((fd = mkstemp(path)) < 0)
		return (NULL);
	return (fdopen(fd, "w+"));
}
Exemplo n.º 11
0
void
closecal(FILE *fp)
{
	uid_t uid;
	struct stat sbuf;
	int nread, pdes[2], status;
	char buf[1024];

	if (!doall)
		return;

	rewind(fp);
	if (fstat(fileno(fp), &sbuf) || !sbuf.st_size)
		goto done;
	if (pipe(pdes) < 0)
		goto done;
	switch (fork()) {
	case -1:			/* error */
		(void)close(pdes[0]);
		(void)close(pdes[1]);
		goto done;
	case 0:
		/* child -- set stdin to pipe output */
		if (pdes[0] != STDIN_FILENO) {
			(void)dup2(pdes[0], STDIN_FILENO);
			(void)close(pdes[0]);
		}
		(void)close(pdes[1]);
		uid = geteuid();
		if (setuid(getuid()) < 0) {
			warnx("setuid failed");
			_exit(1);
		};
		if (setgid(getegid()) < 0) {
			warnx("setgid failed");
			_exit(1);
		}
		if (setuid(uid) < 0) {
			warnx("setuid failed");
			_exit(1);
		}
		execl(_PATH_SENDMAIL, "sendmail", "-i", "-t", "-F",
		    "\"Reminder Service\"", (char *)NULL);
		warn(_PATH_SENDMAIL);
		_exit(1);
	}
	/* parent -- write to pipe input */
	(void)close(pdes[0]);

	write(pdes[1], "From: \"Reminder Service\" <", 26);
	write(pdes[1], pw->pw_name, strlen(pw->pw_name));
	write(pdes[1], ">\nTo: <", 7);
	write(pdes[1], pw->pw_name, strlen(pw->pw_name));
	write(pdes[1], ">\nSubject: ", 11);
	write(pdes[1], dayname, strlen(dayname));
	write(pdes[1], "'s Calendar\nPrecedence: bulk\n\n", 30);

	while ((nread = read(fileno(fp), buf, sizeof(buf))) > 0)
		(void)write(pdes[1], buf, nread);
	(void)close(pdes[1]);
done:	(void)fclose(fp);
	(void)unlink(path);
	while (wait(&status) >= 0);
}
Exemplo n.º 12
0
/* drops privileges */
int drop_privileges(char *user, char *group){
	uid_t uid=-1;
	gid_t gid=-1;
	struct group *grp;
	struct passwd *pw;

	/* set effective group ID */
	if(group!=NULL){
		
		/* see if this is a group name */
		if(strspn(group,"0123456789")<strlen(group)){
			grp=(struct group *)getgrnam(group);
			if(grp!=NULL)
				gid=(gid_t)(grp->gr_gid);
			else
				syslog(LOG_ERR,"Warning: Could not get group entry for '%s'",group);
			endgrent();
		        }

		/* else we were passed the GID */
		else
			gid=(gid_t)atoi(group);

		/* set effective group ID if other than current EGID */
		if(gid!=getegid()){

			if(setgid(gid)==-1)
				syslog(LOG_ERR,"Warning: Could not set effective GID=%d",(int)gid);
		        }
	        }


	/* set effective user ID */
	if(user!=NULL){
		
		/* see if this is a user name */
		if(strspn(user,"0123456789")<strlen(user)){
			pw=(struct passwd *)getpwnam(user);
			if(pw!=NULL)
				uid=(uid_t)(pw->pw_uid);
			else
				syslog(LOG_ERR,"Warning: Could not get passwd entry for '%s'",user);
			endpwent();
		        }

		/* else we were passed the UID */
		else
			uid=(uid_t)atoi(user);
			
		/* set effective user ID if other than current EUID */
		if(uid!=geteuid()){

#ifdef HAVE_INITGROUPS
			/* initialize supplementary groups */
			if(initgroups(user,gid)==-1){
				if(errno==EPERM)
					syslog(LOG_ERR,"Warning: Unable to change supplementary groups using initgroups()");
				else{
					syslog(LOG_ERR,"Warning: Possibly root user failed dropping privileges with initgroups()");
					return ERROR;
			                }
	                        }
#endif

			if(setuid(uid)==-1)
				syslog(LOG_ERR,"Warning: Could not set effective UID=%d",(int)uid);
		        }
	        }

	return OK;
        }
Exemplo n.º 13
0
void _PR_InitLog(void)
{
    char *ev;

    _pr_logLock = PR_NewLock();

    ev = PR_GetEnv("NSPR_LOG_MODULES");
    if (ev && ev[0]) {
        char module[64];  /* Security-Critical: If you change this
                           * size, you must also change the sscanf
                           * format string to be size-1.
                           */
        PRBool isSync = PR_FALSE;
        PRIntn evlen = strlen(ev), pos = 0;
        PRInt32 bufSize = DEFAULT_BUF_SIZE;
        while (pos < evlen) {
            PRIntn level = 1, count = 0, delta = 0;
            count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-]%n:%d%n",
                           module, &delta, &level, &delta);
            pos += delta;
            if (count == 0) break;

            /*
            ** If count == 2, then we got module and level. If count
            ** == 1, then level defaults to 1 (module enabled).
            */
            if (strcasecmp(module, "sync") == 0) {
                isSync = PR_TRUE;
            } else if (strcasecmp(module, "bufsize") == 0) {
                if (level >= LINE_BUF_SIZE) {
                    bufSize = level;
                }
            } else {
                PRLogModuleInfo *lm = logModules;
                PRBool skip_modcheck =
                    (0 == strcasecmp (module, "all")) ? PR_TRUE : PR_FALSE;

                while (lm != NULL) {
                    if (skip_modcheck) lm -> level = (PRLogModuleLevel)level;
                    else if (strcasecmp(module, lm->name) == 0) {
                        lm->level = (PRLogModuleLevel)level;
                        break;
                    }
                    lm = lm->next;
                }
            }
            /*found:*/
            count = sscanf(&ev[pos], " , %n", &delta);
            pos += delta;
            if (count == EOF) break;
        }
        PR_SetLogBuffering(isSync ? bufSize : 0);

#ifdef XP_UNIX
        if ((getuid() != geteuid()) || (getgid() != getegid())) {
            return;
        }
#endif /* XP_UNIX */

        ev = PR_GetEnv("NSPR_LOG_FILE");
        if (ev && ev[0]) {
            if (!PR_SetLogFile(ev)) {
#ifdef XP_PC
                char* str = PR_smprintf("Unable to create nspr log file '%s'\n", ev);
                if (str) {
                    OutputDebugString(str);
                    PR_smprintf_free(str);
                }
#else
                fprintf(stderr, "Unable to create nspr log file '%s'\n", ev);
#endif
            }
        } else {
#ifdef _PR_USE_STDIO_FOR_LOGGING
            logFile = stderr;
#else
            logFile = _pr_stderr;
#endif
        }
    }
}
Exemplo n.º 14
0
static int l_issetugid(void) {
	return (geteuid() != getuid() || getegid() != getgid());
}
Exemplo n.º 15
0
/*
 * Check per accout or global hush-login setting.
 *
 * Hushed mode is enabled:
 *
 * a) if global (e.g. /etc/hushlogins) hush file exists:
 *     1) for ALL ACCOUNTS if the file is empty
 *     2) for the current user if the username or shell are found in the file
 *
 * b) if ~/.hushlogin file exists
 *
 * The ~/.hushlogin is ignored if the global hush file exists.
 *
 * The HUSHLOGIN_FILE login.def variable overwrites the default hush filename.
 *
 * Note that shadow-utils login(1) does not support "a1)". The "a1)" is
 * necessary if you want to use PAM for "Last login" message.
 *
 * -- Karel Zak <*****@*****.**> (26-Aug-2011)
 *
 *
 * Per-account check requires some explanation: As root we may not be able to
 * read the directory of the user if it is on an NFS mounted filesystem. We
 * temporarily set our effective uid to the user-uid making sure that we keep
 * root privs. in the real uid.
 *
 * A portable solution would require a fork(), but we rely on Linux having the
 * BSD setreuid()
 */
static int get_hushlogin_status(struct passwd *pwd)
{
	const char *files[] = { _PATH_HUSHLOGINS, _PATH_HUSHLOGIN, NULL };
	const char *file;
	char buf[BUFSIZ];
	int i;

	file = getlogindefs_str("HUSHLOGIN_FILE", NULL);
	if (file) {
		if (!*file)
			return 0;	/* empty HUSHLOGIN_FILE defined */

		files[0] = file;
		files[1] = NULL;
	}

	for (i = 0; files[i]; i++) {
		int ok = 0;

		file = files[i];

		/* Global hush-file*/
		if (*file == '/') {
			struct stat st;
			FILE *f;

			if (stat(file, &st) != 0)
				continue;	/* file does not exist */

			if (st.st_size == 0)
				return 1;	/* for all accounts */

			f = fopen(file, "r");
			if (!f)
				continue;	/* ignore errors... */

			while (ok == 0 && fgets(buf, sizeof(buf), f)) {
				buf[strlen(buf) - 1] = '\0';
				ok = !strcmp(buf, *buf == '/' ? pwd->pw_shell :
								pwd->pw_name);
			}
			fclose(f);
			if (ok)
				return 1;	/* found username/shell */

			return 0;		/* ignore per-account files */
		}

		/* Per-account setting */
		if (strlen(pwd->pw_dir) + sizeof(file) + 2 > sizeof(buf))
			continue;
		else {
			uid_t ruid = getuid();
			gid_t egid = getegid();

			sprintf(buf, "%s/%s", pwd->pw_dir, file);

			if (setregid(-1, pwd->pw_gid) == 0 &&
			    setreuid(0, pwd->pw_uid) == 0)
				ok = effective_access(buf, O_RDONLY) == 0;

			if (setuid(0) != 0 ||
			    setreuid(ruid, 0) != 0 ||
			    setregid(-1, egid) != 0) {
				syslog(LOG_ALERT, _("hush login status: restore original IDs failed"));
				exit(EXIT_FAILURE);
			}
			if (ok)
				return 1;	/* enabled by user */
		}
	}

	return 0;
}
Exemplo n.º 16
0
/*static*/ status_t
Inode::Create(Transaction& transaction, Inode* parent, const char* name,
	int32 mode, int openMode, uint8 type, bool* _created, ino_t* _id,
	Inode** _inode, fs_vnode_ops* vnodeOps, uint32 publishFlags)
{
	TRACE("Inode::Create()\n");
	Volume* volume = transaction.GetVolume();

	DirectoryIterator* entries = NULL;
	ObjectDeleter<DirectoryIterator> entriesDeleter;

	if (parent != NULL) {
		parent->WriteLockInTransaction(transaction);

		TRACE("Inode::Create(): Looking up entry destination\n");
		HTree htree(volume, parent);

		status_t status = htree.Lookup(name, &entries);
		if (status == B_ENTRY_NOT_FOUND) {
			panic("We need to add the first node.\n");
			return B_ERROR;
		}
		if (status != B_OK)
			return status;
		entriesDeleter.SetTo(entries);

		TRACE("Inode::Create(): Looking up to see if file already exists\n");
		ino_t entryID;

		status = entries->FindEntry(name, &entryID);
		if (status == B_OK) {
			// File already exists
			TRACE("Inode::Create(): File already exists\n");
			if (S_ISDIR(mode) || S_ISLNK(mode) || (openMode & O_EXCL) != 0)
				return B_FILE_EXISTS;

			Vnode vnode(volume, entryID);
			Inode* inode;

			status = vnode.Get(&inode);
			if (status != B_OK) {
				TRACE("Inode::Create() Failed to get the inode from the "
					"vnode\n");
				return B_ENTRY_NOT_FOUND;
			}

			if (inode->IsDirectory() && (openMode & O_RWMASK) != O_RDONLY)
				return B_IS_A_DIRECTORY;
			if ((openMode & O_DIRECTORY) != 0 && !inode->IsDirectory())
				return B_NOT_A_DIRECTORY;

			if (inode->CheckPermissions(open_mode_to_access(openMode)
					| ((openMode & O_TRUNC) != 0 ? W_OK : 0)) != B_OK)
				return B_NOT_ALLOWED;

			if ((openMode & O_TRUNC) != 0) {
				// Truncate requested
				TRACE("Inode::Create(): Truncating file\n");
				inode->WriteLockInTransaction(transaction);

				status = inode->Resize(transaction, 0);
				if (status != B_OK)
					return status;
			}

			if (_created != NULL)
				*_created = false;
			if (_id != NULL)
				*_id = inode->ID();
			if (_inode != NULL)
				*_inode = inode;

			if (_id != NULL || _inode != NULL)
				vnode.Keep();

			TRACE("Inode::Create(): Done opening file\n");
			return B_OK;
		/*} else if ((mode & S_ATTR_DIR) == 0) {
			TRACE("Inode::Create(): (mode & S_ATTR_DIR) == 0\n");
			return B_BAD_VALUE;*/
		} else if ((openMode & O_DIRECTORY) != 0) {
			TRACE("Inode::Create(): (openMode & O_DIRECTORY) != 0\n");
			return B_ENTRY_NOT_FOUND;
		}

		// Return to initial position
		TRACE("Inode::Create(): Restarting iterator\n");
		entries->Restart();
	}

	status_t status;
	if (parent != NULL) {
		status = parent->CheckPermissions(W_OK);
		if (status != B_OK)
			return status;
	}

	TRACE("Inode::Create(): Allocating inode\n");
	ino_t id;
	status = volume->AllocateInode(transaction, parent, mode, id);
	if (status != B_OK) {
		ERROR("Inode::Create(): AllocateInode() failed\n");
		return status;
	}

	if (entries != NULL) {
		size_t nameLength = strlen(name);
		status = entries->AddEntry(transaction, name, nameLength, id, type);
		if (status != B_OK) {
			ERROR("Inode::Create(): AddEntry() failed\n");
			return status;
		}
	}

	TRACE("Inode::Create(): Creating inode\n");
	Inode* inode = new(std::nothrow) Inode(volume);
	if (inode == NULL)
		return B_NO_MEMORY;

	TRACE("Inode::Create(): Getting node structure\n");
	ext2_inode& node = inode->Node();
	TRACE("Inode::Create(): Initializing inode data\n");
	memset(&node, 0, sizeof(ext2_inode));
	node.SetMode(mode);
	node.SetUserID(geteuid());
	node.SetGroupID(parent != NULL ? parent->Node().GroupID() : getegid());
	node.SetNumLinks(inode->IsDirectory() ? 2 : 1);
	TRACE("Inode::Create(): Updating time\n");
	struct timespec timespec;
	_BigtimeToTimespec(real_time_clock_usecs(), &timespec);
	inode->SetAccessTime(&timespec);
	inode->SetCreationTime(&timespec);
	inode->SetModificationTime(&timespec);
	if (parent != NULL)
		node.SetFlags(parent->Flags() & EXT2_INODE_INHERITED);
	if (volume->HasExtentsFeature()
		&& (inode->IsDirectory() || inode->IsFile())) {
		node.SetFlag(EXT2_INODE_EXTENTS);
		ExtentStream stream(volume, &node.extent_stream, 0);
		stream.Init();
		ASSERT(stream.Check());
	}

	if (sizeof(ext2_inode) < volume->InodeSize())
		node.SetExtraInodeSize(sizeof(ext2_inode) - EXT2_INODE_NORMAL_SIZE);

	TRACE("Inode::Create(): Updating ID\n");
	inode->fID = id;

	if (inode->IsDirectory()) {
		TRACE("Inode::Create(): Initializing directory\n");
		status = inode->InitDirectory(transaction, parent);
		if (status != B_OK) {
			ERROR("Inode::Create(): InitDirectory() failed\n");
			delete inode;
			return status;
		}
	}

	// TODO: Maybe it can be better
	/*if (volume->HasExtendedAttributes()) {
		TRACE("Inode::Create(): Initializing extended attributes\n");
		uint32 blockGroup = 0;
		uint32 pos = 0;
		uint32 allocated;

		status = volume->AllocateBlocks(transaction, 1, 1, blockGroup, pos,
			allocated);
		if (status != B_OK)
			return status;

		// Clear the new block
		uint32 blockNum = volume->FirstDataBlock() + pos +
			volume->BlocksPerGroup() * blockGroup;
		CachedBlock cached(volume);
		cached.SetToWritable(transaction, blockNum, true);

		node.SetExtendedAttributesBlock(blockNum);
	}*/

	TRACE("Inode::Create(): Saving inode\n");
	status = inode->WriteBack(transaction);
	if (status != B_OK) {
		delete inode;
		return status;
	}

	TRACE("Inode::Create(): Creating vnode\n");

	Vnode vnode;
	status = vnode.Publish(transaction, inode, vnodeOps, publishFlags);
	if (status != B_OK)
		return status;

	if (!inode->IsSymLink()) {
		// Vnode::Publish doesn't publish symlinks
		if (!inode->IsDirectory()) {
			status = inode->CreateFileCache();
			if (status != B_OK)
				return status;
		}

		inode->WriteLockInTransaction(transaction);
	}

	if (_created)
		*_created = true;
	if (_id != NULL)
		*_id = id;
	if (_inode != NULL)
		*_inode = inode;

	if (_id != NULL || _inode != NULL)
		vnode.Keep();

	TRACE("Inode::Create(): Deleting entries iterator\n");
	DirectoryIterator* iterator = entriesDeleter.Detach();
	TRACE("Inode::Create(): Entries iterator: %p\n", entries);
	delete iterator;
	TRACE("Inode::Create(): Done\n");

	return B_OK;
}
/* A binary wrapper is needed around python scripts if we want
 * to run them in sgid/suid mode.
 *
 * This is such a wrapper.
 */
int main(int argc, char **argv)
{
    /*
     * We disallow passing of arguments which point to writable dirs
     * and other files possibly not accessible to calling user.
     * This way, the script will always use default values for these arguments.
     */
    char **pp = argv;
    char *arg;
    while ((arg = *++pp) != NULL)
    {
        /* Allow taking ids from stdin */
        if (strcmp(arg, "--ids=-") == 0)
            continue;

        if (strncmp(arg, "--exact", 7) == 0)
            continue;

        if (strncmp(arg, "--cache", 7) == 0)
            error_msg_and_die("bad option %s", arg);
        if (strncmp(arg, "--tmpdir", 8) == 0)
            error_msg_and_die("bad option %s", arg);
        if (strncmp(arg, "--ids", 5) == 0)
            error_msg_and_die("bad option %s", arg);
    }

    /* Switch real user/group to effective ones.
     * Otherwise yum library gets confused - gets EPERM (why??).
     */
    gid_t g = getegid();
    /* do setregid only if we have to, to not upset selinux needlessly */
    if (g != getgid())
        IGNORE_RESULT(setregid(g, g));
    uid_t u = geteuid();
    if (u != getuid())
    {
        IGNORE_RESULT(setreuid(u, u));
        /* We are suid'ed! */
        /* Prevent malicious user from messing up with suid'ed process: */
#if 1
// We forgot to sanitize PYTHONPATH. And who knows what else we forgot
// (especially considering *future* new variables of this kind).
// We switched to clearing entire environment instead:

        // However since we communicate through environment variables
        // we have to keep a whitelist of variables to keep.
        static const char *whitelist[] = {
            "REPORT_CLIENT_SLAVE" //  Check if the app is being run as a slave
        };
        const size_t wlsize = sizeof(whitelist)/sizeof(char*);
        char *setlist[sizeof(whitelist)/sizeof(char*)] = { 0 };
        char *p = NULL;
        for (size_t i = 0; i < wlsize; i++)
            if ((p = getenv(whitelist[i])) != NULL)
                setlist[i] = xstrdup(p);

        // Now we can clear the environment
        clearenv();

        // And once again set whitelisted variables
        for (size_t i = 0; i < wlsize; i++)
            if (setlist[i] != NULL)
            {
                xsetenv(whitelist[i], setlist[i]);
                free(setlist[i]);
            }
#else
        /* Clear dangerous stuff from env */
        static const char forbid[] =
            "LD_LIBRARY_PATH" "\0"
            "LD_PRELOAD" "\0"
            "LD_TRACE_LOADED_OBJECTS" "\0"
            "LD_BIND_NOW" "\0"
            "LD_AOUT_LIBRARY_PATH" "\0"
            "LD_AOUT_PRELOAD" "\0"
            "LD_NOWARN" "\0"
            "LD_KEEPDIR" "\0"
        ;
        const char *p = forbid;
        do {
            unsetenv(p);
            p += strlen(p) + 1;
        } while (*p);
#endif
        /* Set safe PATH */
        // Adding configure --bindir and --sbindir to the PATH so that
        // abrt-action-install-debuginfo doesn't fail when spawning
        // abrt-action-trim-files
        char path_env[] = "PATH=/usr/sbin:/sbin:/usr/bin:/bin:"BIN_DIR":"SBIN_DIR;
        if (u != 0)
            strcpy(path_env, "PATH=/usr/bin:/bin:"BIN_DIR);
        putenv(path_env);
    }

    execvp(EXECUTABLE, argv);
    error_msg_and_die("Can't execute %s", EXECUTABLE);
}
Exemplo n.º 18
0
char *
makemsg(char *fname, size_t *mbufsize, int print_banner)
{
	register int ch, cnt;
	struct tm *lt;
	struct passwd *pw;
	struct stat sbuf;
	time_t now;
	FILE *fp;
	char *p, *whom, *where, *hostname, *lbuf, *tmpname, *mbuf;
	long line_max;

	hostname = xmalloc(sysconf(_SC_HOST_NAME_MAX) + 1);
	line_max = sysconf(_SC_LINE_MAX);
	lbuf = xmalloc(line_max);

	if ((fp = xfmkstemp(&tmpname, NULL)) == NULL)
		err(EXIT_FAILURE, _("can't open temporary file"));
	unlink(tmpname);
	free(tmpname);

	if (print_banner == TRUE) {
		if (!(whom = getlogin()) || !*whom)
			whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
		if (!whom) {
			whom = "someone";
			warn(_("cannot get passwd uid"));
		}
		where = ttyname(STDOUT_FILENO);
		if (!where) {
			where = "somewhere";
			warn(_("cannot get tty name"));
		}
		gethostname(hostname, sizeof(hostname));
		time(&now);
		lt = localtime(&now);

		/*
		 * all this stuff is to blank out a square for the message;
		 * we wrap message lines at column 79, not 80, because some
		 * terminals wrap after 79, some do not, and we can't tell.
		 * Which means that we may leave a non-blank character
		 * in column 80, but that can't be helped.
		 */
		/* snprintf is not always available, but the sprintf's here
		   will not overflow as long as %d takes at most 100 chars */
		fprintf(fp, "\r%79s\r\n", " ");
		sprintf(lbuf, _("Broadcast Message from %s@%s"),
			      whom, hostname);
		fprintf(fp, "%-79.79s\007\007\r\n", lbuf);
		sprintf(lbuf, "        (%s) at %d:%02d ...",
			      where, lt->tm_hour, lt->tm_min);
		fprintf(fp, "%-79.79s\r\n", lbuf);
	}
	fprintf(fp, "%79s\r\n", " ");

	free(hostname);

	if (fname) {
		/*
		 * When we are not root, but suid or sgid, refuse to read files
		 * (e.g. device files) that the user may not have access to.
		 * After all, our invoker can easily do "wall < file"
		 * instead of "wall file".
		 */
		uid_t uid = getuid();
		if (uid && (uid != geteuid() || getgid() != getegid()))
			errx(EXIT_FAILURE, _("will not read %s - use stdin."),
			     fname);

		if (!freopen(fname, "r", stdin))
			err(EXIT_FAILURE, _("cannot open file %s"), fname);
	}

	while (fgets(lbuf, line_max, stdin)) {
		for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) {
			if (cnt == 79 || ch == '\n') {
				for (; cnt < 79; ++cnt)
					putc(' ', fp);
				putc('\r', fp);
				putc('\n', fp);
				cnt = 0;
			}
			if (ch != '\n')
				carefulputc(ch, fp);
		}
	}
	fprintf(fp, "%79s\r\n", " ");

	free(lbuf);
	rewind(fp);

	if (fstat(fileno(fp), &sbuf))
		err(EXIT_FAILURE, _("fstat failed"));

	*mbufsize = (size_t) sbuf.st_size;
	mbuf = xmalloc(*mbufsize);

	if (fread(mbuf, 1, *mbufsize, fp) != *mbufsize)
		err(EXIT_FAILURE, _("fread failed"));

	if (close_stream(fp) != 0)
		errx(EXIT_FAILURE, _("write error"));
	return mbuf;
}
Exemplo n.º 19
0
int smbrun(const char *cmd, int *outfd)
{
	OutputDebugString("smbrun is not supported\n");
#ifndef _XBOX
	pid_t pid;
	uid_t uid = current_user.ut.uid;
	gid_t gid = current_user.ut.gid;
	
	/*
	 * Lose any elevated privileges.
	 */
	drop_effective_capability(KERNEL_OPLOCK_CAPABILITY);
	drop_effective_capability(DMAPI_ACCESS_CAPABILITY);

	/* point our stdout at the file we want output to go into */

	if (outfd && ((*outfd = setup_out_fd()) == -1)) {
		return -1;
	}

	/* in this method we will exec /bin/sh with the correct
	   arguments, after first setting stdout to point at the file */

	/*
	 * We need to temporarily stop CatchChild from eating
	 * SIGCLD signals as it also eats the exit status code. JRA.
	 */

	CatchChildLeaveStatus();
                                   	
	if ((pid=sys_fork()) < 0) {
		DEBUG(0,("smbrun: fork failed with error %s\n", strerror(errno) ));
		CatchChild(); 
		if (outfd) {
			close(*outfd);
			*outfd = -1;
		}
		return errno;
	}

	if (pid) {
		/*
		 * Parent.
		 */
		int status=0;
		pid_t wpid;

		
		/* the parent just waits for the child to exit */
		while((wpid = sys_waitpid(pid,&status,0)) < 0) {
			if(errno == EINTR) {
				errno = 0;
				continue;
			}
			break;
		}

		CatchChild(); 

		if (wpid != pid) {
			DEBUG(2,("waitpid(%d) : %s\n",(int)pid,strerror(errno)));
			if (outfd) {
				close(*outfd);
				*outfd = -1;
			}
			return -1;
		}

		/* Reset the seek pointer. */
		if (outfd) {
			sys_lseek(*outfd, 0, SEEK_SET);
		}

#if defined(WIFEXITED) && defined(WEXITSTATUS)
		if (WIFEXITED(status)) {
			return WEXITSTATUS(status);
		}
#endif

		return status;
	}
	
	CatchChild(); 
	
	/* we are in the child. we exec /bin/sh to do the work for us. we
	   don't directly exec the command we want because it may be a
	   pipeline or anything else the config file specifies */
	
	/* point our stdout at the file we want output to go into */
	if (outfd) {
		close(1);
		if (sys_dup2(*outfd,1) != 1) {
			DEBUG(2,("Failed to create stdout file descriptor\n"));
			close(*outfd);
			exit(80);
		}
	}

	/* now completely lose our privileges. This is a fairly paranoid
	   way of doing it, but it does work on all systems that I know of */

	become_user_permanently(uid, gid);

	if (getuid() != uid || geteuid() != uid ||
	    getgid() != gid || getegid() != gid) {
		/* we failed to lose our privileges - do not execute
                   the command */
		exit(81); /* we can't print stuff at this stage,
			     instead use exit codes for debugging */
	}
	
#ifndef __INSURE__
	/* close all other file descriptors, leaving only 0, 1 and 2. 0 and
	   2 point to /dev/null from the startup code */
	{
	int fd;
	for (fd=3;fd<256;fd++) close(fd);
	}
#endif

	execl("/bin/sh","sh","-c",cmd,NULL);  
	
	/* not reached */
	exit(82);
#endif //_XBOX
	return 1;
}
void printRealAndEffectiveId() {
	printf("user id = %d \n", getuid());
	printf("effective user id = %d\n", geteuid());
	printf("group id = %d \n", getpid());
	printf("effective group id = %d\n", getegid());
}
Exemplo n.º 21
0
int main(int ac, char **av)
{
	int lc;
	char *msg;
	struct stat buf;

	/*
	 * parse standard options
	 */
	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
	}

	/*
	 * perform global setup for test
	 */
	setup();

	/*
	 * check looping state if -i option given
	 */
	for (lc = 0; TEST_LOOPING(lc); lc++) {

		tst_count = 0;

		/*
		 * TEST mkdir() base functionality
		 */

		/* Initialize the test directory name */
		sprintf(tstdir1, "tstdir1.%d", getpid());

		/* Call mkdir(2) using the TEST macro */
		TEST(mkdir(tstdir1, PERMS));

		if (TEST_RETURN == -1) {
			tst_resm(TFAIL, "mkdir(%s, %#o) Failed",
				 tstdir1, PERMS);
			continue;
		}

		if (STD_FUNCTIONAL_TEST) {
			if (stat(tstdir1, &buf) == -1) {
				tst_brkm(TBROK, cleanup, "failed to stat the "
					 "new directory");
			}
			/* check the owner */
			if (buf.st_uid != geteuid()) {
				tst_resm(TFAIL, "mkdir() FAILED to set owner ID"
					 " as process's effective ID");
				continue;
			}
			/* check the group ID */
			if (buf.st_gid != getegid()) {
				tst_resm(TFAIL, "mkdir() failed to set group ID"
					 " as the process's group ID");
				continue;
			}
			tst_resm(TPASS, "mkdir() functionality is correct");
		} else {
			tst_resm(TPASS, "call succeeded");
		}

		/* clean up things in case we are looping */
		if (rmdir(tstdir1) == -1) {
			tst_brkm(TBROK, cleanup, "could not remove directory");
		}

	}

	/*
	 * cleanup and exit
	 */
	cleanup();
	tst_exit();

}
Exemplo n.º 22
0
void
_cupsSetDefaults(void)
{
  cups_file_t	*fp;			/* File */
  const char	*home;			/* Home directory of user */
  char		filename[1024];		/* Filename */
  _cups_client_conf_t cc;		/* client.conf values */
  _cups_globals_t *cg = _cupsGlobals();	/* Pointer to library globals */


  DEBUG_puts("_cupsSetDefaults()");

 /*
  * Load initial client.conf values...
  */

  cups_init_client_conf(&cc);

 /*
  * Read the /etc/cups/client.conf and ~/.cups/client.conf files, if
  * present.
  */

  snprintf(filename, sizeof(filename), "%s/client.conf", cg->cups_serverroot);
  if ((fp = cupsFileOpen(filename, "r")) != NULL)
  {
    cups_read_client_conf(fp, &cc);
    cupsFileClose(fp);
  }

#  ifdef HAVE_GETEUID
  if ((geteuid() == getuid() || !getuid()) && getegid() == getgid() && (home = getenv("HOME")) != NULL)
#  elif !defined(WIN32)
  if (getuid() && (home = getenv("HOME")) != NULL)
#  else
  if ((home = getenv("HOME")) != NULL)
#  endif /* HAVE_GETEUID */
  {
   /*
    * Look for ~/.cups/client.conf...
    */

    snprintf(filename, sizeof(filename), "%s/.cups/client.conf", home);
    if ((fp = cupsFileOpen(filename, "r")) != NULL)
    {
      cups_read_client_conf(fp, &cc);
      cupsFileClose(fp);
    }
  }

 /*
  * Finalize things so every client.conf value is set...
  */

  cups_finalize_client_conf(&cc);

  if (cg->encryption == (http_encryption_t)-1)
    cg->encryption = cc.encryption;

  if (!cg->server[0] || !cg->ipp_port)
    cupsSetServer(cc.server_name);

  if (!cg->ipp_port)
    cups_set_default_ipp_port(cg);

  if (!cg->user[0])
    strlcpy(cg->user, cc.user, sizeof(cg->user));

#ifdef HAVE_GSSAPI
  if (!cg->gss_service_name[0])
    strlcpy(cg->gss_service_name, cc.gss_service_name, sizeof(cg->gss_service_name));
#endif /* HAVE_GSSAPI */

  if (cg->trust_first < 0)
    cg->trust_first = cc.trust_first;

  if (cg->any_root < 0)
    cg->any_root = cc.any_root;

  if (cg->expired_certs < 0)
    cg->expired_certs = cc.expired_certs;

  if (cg->validate_certs < 0)
    cg->validate_certs = cc.validate_certs;

#ifdef HAVE_SSL
  _httpTLSSetOptions(cc.ssl_options | _HTTP_TLS_SET_DEFAULT, cc.ssl_min_version, cc.ssl_max_version);
#endif /* HAVE_SSL */
}
Exemplo n.º 23
0
int
main(int argc, char *argv[])
{
	char *system = NULL;
	int i;
	char *p;
	char sbuf[12];

	gid = getgid();
	egid = getegid();
	uid = getuid();
	euid = geteuid();

#if INCLUDE_CU_INTERFACE
	if (equal(sname(argv[0]), "cu")) {
		cumode = 1;
		cumain(argc, argv);
		goto cucommon;
	}
#endif /* INCLUDE_CU_INTERFACE */

	if (argc > 4)
		usage();
	if (!isatty(0))
		errx(1, "must be interactive");

	for (; argc > 1; argv++, argc--) {
		if (argv[1][0] != '-')
			system = argv[1];
		else switch (argv[1][1]) {

		case 'v':
			vflag++;
			break;

		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			BR = atoi(&argv[1][1]);
			break;

		default:
			warnx("%s, unknown option", argv[1]);
			break;
		}
	}

	if (system == NULL)
		goto notnumber;
	if (isalpha(*system))
		goto notnumber;
	/*
	 * System name is really a phone number...
	 * Copy the number then stomp on the original (in case the number
	 *	is private, we don't want 'ps' or 'w' to find it).
	 */
	if (strlen(system) > sizeof(PNbuf) - 1)
		errx(1, "phone number too long (max = %zd bytes)", sizeof PNbuf - 1);
	strncpy(PNbuf, system, sizeof(PNbuf) - 1);
	for (p = system; *p; p++)
		*p = '\0';
	PN = PNbuf;
	(void)snprintf(sbuf, sizeof(sbuf), "tip%ld", BR);
	system = sbuf;

notnumber:
	(void)signal(SIGINT, cleanup);
	(void)signal(SIGQUIT, cleanup);
	(void)signal(SIGHUP, cleanup);
	(void)signal(SIGTERM, cleanup);
	(void)signal(SIGUSR1, tipdone);

	if ((i = hunt(system)) == 0) {
		printf("all ports busy\n");
		exit(3);
	}
	if (i == -1) {
		printf("link down\n");
		(void)uu_unlock(uucplock);
		exit(3);
	}
	setbuf(stdout, NULL);
	loginit();

	/*
	 * Kludge, their's no easy way to get the initialization
	 *   in the right order, so force it here
	 */
	if ((PH = getenv("PHONES")) == NULL)
		PH = _PATH_PHONES;
	vinit();				/* init variables */
	setparity("even");			/* set the parity table */
	if ((i = speed(number(value(BAUDRATE)))) == 0) {
		printf("tip: bad baud rate %d\n", number(value(BAUDRATE)));
		(void)uu_unlock(uucplock);
		exit(3);
	}

	/*
	 * Now that we have the logfile and the ACU open
	 *  return to the real uid and gid.  These things will
	 *  be closed on exit.  Swap real and effective uid's
	 *  so we can get the original permissions back
	 *  for removing the uucp lock.
	 */
	user_uid();

	/*
	 * Hardwired connections require the
	 *  line speed set before they make any transmissions
	 *  (this is particularly true of things like a DF03-AC)
	 */
	if (HW)
		ttysetup(i);
	if ((p = connect())) {
		printf("\07%s\n[EOT]\n", p);
		daemon_uid();
		(void)uu_unlock(uucplock);
		exit(1);
	}
	if (!HW)
		ttysetup(i);
cucommon:
	/*
	 * From here down the code is shared with
	 * the "cu" version of tip.
	 */

#if HAVE_TERMIOS
	tcgetattr (0, &otermios);
	ctermios = otermios;
#ifndef _POSIX_SOURCE
	ctermios.c_iflag = (IMAXBEL|IXANY|ISTRIP|IXON|BRKINT);
	ctermios.c_lflag = (PENDIN|IEXTEN|ISIG|ECHOCTL|ECHOE|ECHOKE);
#else
	ctermios.c_iflag = (ISTRIP|IXON|BRKINT);
	ctermios.c_lflag = (PENDIN|IEXTEN|ISIG|ECHOE);
#endif
	ctermios.c_cflag = (CLOCAL|HUPCL|CREAD|CS8);
	ctermios.c_cc[VINTR] = 	ctermios.c_cc[VQUIT] = -1;
	ctermios.c_cc[VSUSP] = ctermios.c_cc[VDSUSP] = ctermios.c_cc[VDISCARD] =
		ctermios.c_cc[VLNEXT] = -1;
#else /* HAVE_TERMIOS */
	ioctl(0, TIOCGETP, (char *)&defarg);
	ioctl(0, TIOCGETC, (char *)&defchars);
	ioctl(0, TIOCGLTC, (char *)&deflchars);
	ioctl(0, TIOCGETD, (char *)&odisc);
	arg = defarg;
	arg.sg_flags = ANYP | CBREAK;
	tchars = defchars;
	tchars.t_intrc = tchars.t_quitc = -1;
	ltchars = deflchars;
	ltchars.t_suspc = ltchars.t_dsuspc = ltchars.t_flushc
		= ltchars.t_lnextc = -1;
#endif /* HAVE_TERMIOS */
	raw();

	pipe(fildes); pipe(repdes);
	(void)signal(SIGALRM, timeoutfunc);

	/*
	 * Everything's set up now:
	 *	connection established (hardwired or dialup)
	 *	line conditioned (baud rate, mode, etc.)
	 *	internal data structures (variables)
	 * so, fork one process for local side and one for remote.
	 */
	printf(cumode ? "Connected\r\n" : "\07connected\r\n");

	if (LI != NULL && tiplink (LI, 0) != 0) {
		tipabort ("login failed");
	}

	if ((pid = fork()))
		tipin();
	else
		tipout();
	/*NOTREACHED*/
}
Exemplo n.º 24
0
int DLL_DECL
Cns_lstat(const char *path, struct Cns_filestat *statbuf)
{
	char *actual_path;
	int c, n;
	char func[16];
	gid_t gid;
	int msglen;
	char *q;
	char *rbp;
	char repbuf[57];
	char *sbp;
	char sendbuf[REQBUFSZ];
	char server[CA_MAXHOSTNAMELEN+1];
	struct Cns_api_thread_info *thip;
	uid_t uid;
	u_signed64 zero = 0;
 
	strcpy (func, "Cns_lstat");
	if (Cns_apiinit (&thip))
		return (-1);
	uid = geteuid();
	gid = getegid();
#if defined(_WIN32)
	if (uid < 0 || gid < 0) {
		Cns_errmsg (func, NS053);
		serrno = SENOMAPFND;
		return (-1);
	}
#endif

	if (! path || ! statbuf) {
		serrno = EFAULT;
		return (-1);
	}

	if (strlen (path) > CA_MAXPATHLEN) {
		serrno = ENAMETOOLONG;
		return (-1);
	}

	if (Cns_selectsrvr (path, thip->server, server, &actual_path))
		return (-1);

	/* Build request header */

	sbp = sendbuf;
	marshall_LONG (sbp, CNS_MAGIC2);
	marshall_LONG (sbp, CNS_LSTAT);
	q = sbp;        /* save pointer. The next field will be updated */
	msglen = 3 * LONGSIZE;
	marshall_LONG (sbp, msglen);
 
	/* Build request body */

	marshall_LONG (sbp, uid);
	marshall_LONG (sbp, gid);
	marshall_HYPER (sbp, thip->cwd);
	marshall_HYPER (sbp, zero);
	marshall_STRING (sbp, actual_path);

	msglen = sbp - sendbuf;
	marshall_LONG (q, msglen);	/* update length field */

	c = send2nsd (NULL, server, sendbuf, msglen, repbuf, sizeof(repbuf));

	if (c == 0) {
		rbp = repbuf;
		unmarshall_HYPER (rbp, statbuf->fileid);
		unmarshall_WORD (rbp, statbuf->filemode);
		unmarshall_LONG (rbp, statbuf->nlink);
		unmarshall_LONG (rbp, statbuf->uid);
		unmarshall_LONG (rbp, statbuf->gid);
		unmarshall_HYPER (rbp, statbuf->filesize);
		unmarshall_TIME_T (rbp, statbuf->atime);
		unmarshall_TIME_T (rbp, statbuf->mtime);
		unmarshall_TIME_T (rbp, statbuf->ctime);
		unmarshall_WORD (rbp, statbuf->fileclass);
		unmarshall_BYTE (rbp, statbuf->status);
	}
	if (c && serrno == SENAMETOOLONG) serrno = ENAMETOOLONG;
	return (c);
}
Exemplo n.º 25
0
EXPORT_C int OPENSSL_issetugid(void)
{
    if (getuid() != geteuid()) return 1;
    if (getgid() != getegid()) return 1;
    return 0;
}
Exemplo n.º 26
0
int DLL_DECL
Cns_statr(const char *sfn, struct Cns_filestatg *statbuf)
{
	int c, n;
	char func[16];
	gid_t gid;
	int msglen;
	char *q;
	char *rbp;
	char repbuf[132];
	char *sbp;
	char sendbuf[REQBUFSZ];
	struct Cns_api_thread_info *thip;
	uid_t uid;
 
	strcpy (func, "Cns_statr");
	if (Cns_apiinit (&thip))
		return (-1);
	uid = geteuid();
	gid = getegid();
#if defined(_WIN32)
	if (uid < 0 || gid < 0) {
		Cns_errmsg (func, NS053);
		serrno = SENOMAPFND;
		return (-1);
	}
#endif

	if (! sfn || ! statbuf) {
		serrno = EFAULT;
		return (-1);
	}

	if (strlen (sfn) > CA_MAXSFNLEN) {
		serrno = ENAMETOOLONG;
		return (-1);
	}

	/* Build request header */

	sbp = sendbuf;
	marshall_LONG (sbp, CNS_MAGIC);
	marshall_LONG (sbp, CNS_STATR);
	q = sbp;        /* save pointer. The next field will be updated */
	msglen = 3 * LONGSIZE;
	marshall_LONG (sbp, msglen);
 
	/* Build request body */

	marshall_LONG (sbp, uid);
	marshall_LONG (sbp, gid);
	marshall_STRING (sbp, sfn);

	msglen = sbp - sendbuf;
	marshall_LONG (q, msglen);	/* update length field */

	c = send2nsd (NULL, NULL, sendbuf, msglen, repbuf, sizeof(repbuf));

	if (c == 0) {
		rbp = repbuf;
		unmarshall_HYPER (rbp, statbuf->fileid);
		unmarshall_STRING (rbp, statbuf->guid);
		unmarshall_WORD (rbp, statbuf->filemode);
		unmarshall_LONG (rbp, statbuf->nlink);
		unmarshall_LONG (rbp, statbuf->uid);
		unmarshall_LONG (rbp, statbuf->gid);
		unmarshall_HYPER (rbp, statbuf->filesize);
		unmarshall_TIME_T (rbp, statbuf->atime);
		unmarshall_TIME_T (rbp, statbuf->mtime);
		unmarshall_TIME_T (rbp, statbuf->ctime);
		unmarshall_WORD (rbp, statbuf->fileclass);
		unmarshall_BYTE (rbp, statbuf->status);
		unmarshall_STRING (rbp, statbuf->csumtype);
		unmarshall_STRING (rbp, statbuf->csumvalue);
	}
	if (c && serrno == SENAMETOOLONG) serrno = ENAMETOOLONG;
	return (c);
}
Exemplo n.º 27
0
int main(int argc, char **argv)
{
	struct stat statbuf;
	uid_t uid = getuid();
	uid_t gid = getgid();
	uid_t euid = geteuid();
	uid_t egid = getegid();

	struct passwd *pwd = getpwuid(uid);
	struct group *grp = getgrgid(gid);

	if (argc < 3)
		usage(argv[0]);

	options_init();

	openlog(PACKAGE, LOG_PID, LOG_DAEMON);

	memset(&statbuf, 0, sizeof(statbuf));

	if (!options_binload(argv[1])) {
		log_err(0, "invalid binary config file %s", argv[1]);
		usage(argv[0]);
	}

	if (uid != 0) {
		if (strcmp(pwd->pw_name, CHILLI_USER)) {
			log_err(0, "has to run as user %s or root",
				CHILLI_USER);
			usage(argv[0]);
		}

		if (strcmp(grp->gr_name, CHILLI_GROUP)) {
			log_err(0, "has to run as group %s or root",
				CHILLI_GROUP);
			usage(argv[0]);
		}
	}

	log_dbg("USER %s(%d/%d), GROUP %s(%d/%d) CHILLI[UID %d, GID %d]",
		pwd->pw_name, uid, euid, grp->gr_name, gid, egid,
		_options.uid, _options.gid);

	if (stat(argv[2], &statbuf)) {
		log_err(errno, "%s does not exist", argv[2]);
		usage(argv[0]);
	}

	if (_options.uid &&	/* chilli is running as non-root */
	    _options.uid == euid &&	/* current euid same as chilli uid */
	    _options.gid == egid &&	/* current egid same as chilli gid */
	    statbuf.st_uid == 0 &&	/* script owned by root */
	    statbuf.st_gid == _options.gid &&	/* script group same as chilli gid */
	    (statbuf.st_mode & 0400) == 0400) {

		if (setuid(0))
			log_err(errno, "setuid %s", argv[0]);
	}

	log_info("Running %s (%d/%d)", argv[2], getuid(), geteuid());

	if (execv(argv[2], &argv[2])) {
		log_err(errno, "exec %s", argv[2]);
		usage(argv[0]);
	}

	return 0;
}
Exemplo n.º 28
0
BOOL change_to_user(connection_struct *conn, uint16 vuid)
{
	user_struct *vuser = get_valid_user_struct(vuid);
	int snum;
	gid_t gid;
	uid_t uid;
	char group_c;
	BOOL must_free_token = False;
	NT_USER_TOKEN *token = NULL;

	if (!conn) {
		DEBUG(2,("change_to_user: Connection not open\n"));
		return(False);
	}

	/*
	 * We need a separate check in security=share mode due to vuid
	 * always being UID_FIELD_INVALID. If we don't do this then
	 * in share mode security we are *always* changing uid's between
	 * SMB's - this hurts performance - Badly.
	 */

	if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
	   (current_user.ut.uid == conn->uid)) {
		DEBUG(4,("change_to_user: Skipping user change - already "
			 "user\n"));
		return(True);
	} else if ((current_user.conn == conn) && 
		   (vuser != 0) && (current_user.vuid == vuid) && 
		   (current_user.ut.uid == vuser->uid)) {
		DEBUG(4,("change_to_user: Skipping user change - already "
			 "user\n"));
		return(True);
	}

	snum = SNUM(conn);

	if ((vuser) && !check_user_ok(conn, vuser, snum)) {
		DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
			 "not permitted access to share %s.\n",
			 vuser->user.smb_name, vuser->user.unix_name, vuid,
			 lp_servicename(snum)));
		return False;
	}

	if (conn->force_user) /* security = share sets this too */ {
		uid = conn->uid;
		gid = conn->gid;
		current_user.ut.groups = conn->groups;
		current_user.ut.ngroups = conn->ngroups;
		token = conn->nt_user_token;
	} else if (vuser) {
		uid = conn->admin_user ? 0 : vuser->uid;
		gid = vuser->gid;
		current_user.ut.ngroups = vuser->n_groups;
		current_user.ut.groups  = vuser->groups;
		token = vuser->nt_user_token;
	} else {
		DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
			 "share %s.\n",vuid, lp_servicename(snum) ));
		return False;
	}

	/*
	 * See if we should force group for this service.
	 * If so this overrides any group set in the force
	 * user code.
	 */

	if((group_c = *lp_force_group(snum))) {

		token = dup_nt_token(NULL, token);
		if (token == NULL) {
			DEBUG(0, ("dup_nt_token failed\n"));
			return False;
		}
		must_free_token = True;

		if(group_c == '+') {

			/*
			 * Only force group if the user is a member of
			 * the service group. Check the group memberships for
			 * this user (we already have this) to
			 * see if we should force the group.
			 */

			int i;
			for (i = 0; i < current_user.ut.ngroups; i++) {
				if (current_user.ut.groups[i] == conn->gid) {
					gid = conn->gid;
					gid_to_sid(&token->user_sids[1], gid);
					break;
				}
			}
		} else {
			gid = conn->gid;
			gid_to_sid(&token->user_sids[1], gid);
		}
	}
	
	set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
		    token);

	/*
	 * Free the new token (as set_sec_ctx copies it).
	 */

	if (must_free_token)
		TALLOC_FREE(token);

	current_user.conn = conn;
	current_user.vuid = vuid;

	DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n",
		 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
  
	return(True);
}
Exemplo n.º 29
0
static void
id_print(struct passwd *pw, int use_ggl, int p_euid, int p_egid)
{
	struct group *gr;
	gid_t gid, egid, lastgid;
	uid_t uid, euid;
	int cnt, ngroups;
	long ngroups_max;
	gid_t *groups;
	const char *fmt;

	if (pw != NULL) {
		uid = pw->pw_uid;
		gid = pw->pw_gid;
	}
	else {
		uid = getuid();
		gid = getgid();
	}

	ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
	if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
		err(1, "malloc");

	if (use_ggl && pw != NULL) {
		ngroups = ngroups_max;
		getgrouplist(pw->pw_name, gid, groups, &ngroups);
	}
	else {
		ngroups = getgroups(ngroups_max, groups);
	}

	if (pw != NULL)
		printf("uid=%u(%s)", uid, pw->pw_name);
	else 
		printf("uid=%u", getuid());
	printf(" gid=%u", gid);
	if ((gr = getgrgid(gid)))
		(void)printf("(%s)", gr->gr_name);
	if (p_euid && (euid = geteuid()) != uid) {
		(void)printf(" euid=%u", euid);
		if ((pw = getpwuid(euid)))
			(void)printf("(%s)", pw->pw_name);
	}
	if (p_egid && (egid = getegid()) != gid) {
		(void)printf(" egid=%u", egid);
		if ((gr = getgrgid(egid)))
			(void)printf("(%s)", gr->gr_name);
	}
	fmt = " groups=%u";
	for (lastgid = -1, cnt = 0; cnt < ngroups; ++cnt) {
		if (lastgid == (gid = groups[cnt]))
			continue;
		printf(fmt, gid);
		fmt = ",%u";
		if ((gr = getgrgid(gid)))
			printf("(%s)", gr->gr_name);
		lastgid = gid;
	}
	printf("\n");
	free(groups);
}
Exemplo n.º 30
0
int main(int argc, char** argv)
{
 int i;
 int err;
 struct stat buf;
 int uid,gid;

 /* Parse the command line options */

 for(i=1;i<argc;i++)
   {
    if(!strcmp(argv[i],"-h") || !strcmp(argv[i],"--help"))
       usage(1);

    if(!strcmp(argv[i],"--version"))
       usage(2);

    if(!strcmp(argv[i],"-d"))
      {
       detached=0;

       if(i<(argc-1) && isdigit(argv[i+1][0]))
         {
          StderrLevel=Fatal+1-atoi(argv[++i]);

          if(StderrLevel<0 || StderrLevel>Fatal)
            {fprintf(stderr,"wwwoffled: The '-d' option requires a number between 0 and %d.\n",Fatal+1); exit(1);}
         }

       continue;
      }

    if(!strcmp(argv[i],"-l"))
      {
       if(++i>=argc)
         {fprintf(stderr,"wwwoffled: The '-l' option requires a filename.\n"); exit(1);}
       if(argv[i][0]!='/')
         {fprintf(stderr,"wwwoffled: The '-l' option requires an absolute pathname.\n"); exit(1);}

       log_file=argv[i];
       continue;
      }

    if(!strcmp(argv[i],"-p"))
      {
       print_pid=1;
       continue;
      }

    if(!strcmp(argv[i],"-f"))
      {
       nofork=1;
       detached=0;
       continue;
      }

    if(!strcmp(argv[i],"-c"))
      {
       if(++i>=argc)
         {fprintf(stderr,"wwwoffled: The '-c' option requires a filename.\n"); exit(1);}

       config_file=argv[i];
       continue;
      }

    fprintf(stderr,"wwwoffled: Unknown option '%s'.\n",argv[i]); exit(1);
   }

 /* Combination options */

 if(log_file)
   {
    if(nofork)
       log_file=NULL;           /* -f overrides -l */
    else
       detached=1;              /* -l overrides -d */

    if(StderrLevel==-1)
       StderrLevel=Inform;      /* -l sets log level if no -d */
   }

 /* Initialise things. */

 for(i=0;i<MAX_FETCH_SERVERS;i++)
    fetch_pids[i]=0;

 for(i=0;i<MAX_SERVERS;i++)
    server_pids[i]=0;

 if(log_file)
    OpenErrorLog(log_file);

 InitErrorHandler("wwwoffled",0,1); /* use stderr and not syslog to start with. */

 /* Read the configuration file. */

 InitConfigurationFile(config_file);

 init_io(STDERR_FILENO);

 if(ReadConfigurationFile(STDERR_FILENO))
    PrintMessage(Fatal,"Error in configuration file '%s'.",ConfigurationFileName());

 finish_io(STDERR_FILENO);

 InitErrorHandler("wwwoffled",ConfigInteger(UseSyslog),1); /* enable syslog if requested. */

 /* Print a startup message. */

#if USE_IPV6
#define IPV6_STRING "with ipv6"
#else
#define IPV6_STRING "without ipv6"
#endif

#define ZLIB_STRING "with zlib"

#define GNUTLS_STRING "with gnutls"

 PrintMessage(Important,"WWWOFFLE Demon Version %s (%s,%s,%s) started.",WWWOFFLE_VERSION,IPV6_STRING,ZLIB_STRING,GNUTLS_STRING);
 PrintMessage(Inform,"WWWOFFLE Read Configuration File '%s'.",ConfigurationFileName());

 /* Change the user and group. */

 gid=ConfigInteger(WWWOFFLE_Gid);
 uid=ConfigInteger(WWWOFFLE_Uid);

 if(uid!=-1)
    seteuid(0);

 if(log_file && (uid!=-1 || gid!=-1))
    chown(log_file,(uid_t)uid,(gid_t)gid);

 if(gid!=-1)
   {
#if HAVE_SETGROUPS
    if(getuid()==0 || geteuid()==0)
       if(setgroups(0,NULL)<0)
          PrintMessage(Fatal,"Cannot clear supplementary group list [%!s].");
#endif

#if HAVE_SETRESGID
    if(setresgid((gid_t)gid,(gid_t)gid,(gid_t)gid)<0)
       PrintMessage(Fatal,"Cannot set real/effective/saved group id to %d [%!s].",gid);
#else
    if(geteuid()==0)
      {
       if(setgid((gid_t)gid)<0)
          PrintMessage(Fatal,"Cannot set group id to %d [%!s].",gid);
      }
    else
      {
#if HAVE_SETREGID
       if(setregid(getegid(),(gid_t)gid)<0)
          PrintMessage(Fatal,"Cannot set effective group id to %d [%!s].",gid);
       if(setregid((gid_t)gid,(gid_t)~1)<0)
          PrintMessage(Fatal,"Cannot set real group id to %d [%!s].",gid);
#else
       PrintMessage(Fatal,"Must be root to totally change group id.");
#endif
      }
#endif
   }

 if(uid!=-1)
   {
#if HAVE_SETRESUID
    if(setresuid((uid_t)uid,(uid_t)uid,(uid_t)uid)<0)
       PrintMessage(Fatal,"Cannot set real/effective/saved user id to %d [%!s].",uid);
#else
    if(geteuid()==0)
      {
       if(setuid((uid_t)uid)<0)
          PrintMessage(Fatal,"Cannot set user id to %d [%!s].",uid);
      }
    else
      {
#if HAVE_SETREUID
       if(setreuid(geteuid(),(uid_t)uid)<0)
          PrintMessage(Fatal,"Cannot set effective user id to %d [%!s].",uid);
       if(setreuid((uid_t)uid,(uid_t)~1)<0)
          PrintMessage(Fatal,"Cannot set real user id to %d [%!s].",uid);
#else
       PrintMessage(Fatal,"Must be root to totally change user id.");
#endif
      }
#endif
   }

 if(uid!=-1 || gid!=-1)
    PrintMessage(Inform,"Running with uid=%d, gid=%d.",geteuid(),getegid());

 if(geteuid()==0 || getegid()==0)
    PrintMessage(Warning,"Running with root user or group privileges is not recommended.");

 /* Create, Change to and open the spool directory. */

 umask(0);

 if(stat(ConfigString(SpoolDir),&buf))
   {
    err=mkdir(ConfigString(SpoolDir),(mode_t)ConfigInteger(DirPerm));
    if(err==-1 && errno!=EEXIST)
       PrintMessage(Fatal,"Cannot create spool directory %s [%!s].",ConfigString(SpoolDir));
    stat(ConfigString(SpoolDir),&buf);
   }

 if(!S_ISDIR(buf.st_mode))
    PrintMessage(Fatal,"The spool directory %s is not a directory.",SpoolDir);

 err=ChangeToSpoolDir(ConfigString(SpoolDir));
 if(err==-1)
    PrintMessage(Fatal,"Cannot change to spool directory %s [%!s].",ConfigString(SpoolDir));

 /* Bind the HTTP proxy socket(s). */

#if USE_IPV6
 if(ConfigString(Bind_IPv6))
   {
    http_fd[1]=OpenServerSocket(ConfigString(Bind_IPv6),ConfigInteger(HTTP_Port));
    if(http_fd[1]==-1)
       PrintMessage(Fatal,"Cannot create HTTP IPv6 server socket.");
   }
#endif

 if(ConfigString(Bind_IPv4))
   {
    http_fd[0]=OpenServerSocket(ConfigString(Bind_IPv4),ConfigInteger(HTTP_Port));
    if(http_fd[0]==-1)
      {
#if USE_IPV6
       if(http_fd[1]!=-1 && /* PS 2003-01-13 redundant? If IPv6 is listening to 0 then it doesn't matter what address IPv4 is listening to... (at least on linux?) */
                            /* ConfigString(Bind_IPv4) && !strcmp(ConfigString(Bind_IPv4),"0.0.0.0") && */
                            ConfigString(Bind_IPv6) && !strcmp(ConfigString(Bind_IPv6),"[0:0:0:0:0:0:0:0]"))
          PrintMessage(Warning,"Cannot create HTTP IPv4 server socket (but the IPv6 one might accept IPv4 connections).");
       else
          PrintMessage(Fatal,"Cannot create HTTP IPv4 server socket.");
#else
       PrintMessage(Fatal,"Cannot create HTTP server socket.");
#endif
      }
   }

 if(http_fd[0]==-1 && http_fd[1]==-1)
   {
#if USE_IPV6
    PrintMessage(Fatal,"The IPv4 and IPv6 HTTP sockets were not bound; are they disabled in the config file?");
#else
    PrintMessage(Fatal,"The HTTP socket was not bound; is it disabled in the config file?");
#endif
   }

 /* Bind the HTTPS socket(s). */

 if(LoadRootCredentials())
   {
    PrintMessage(Warning,"Failed to read (or create if needed) the WWWOFFLE root certificates.");
   }

 if(LoadTrustedCertificates())
   {
    PrintMessage(Warning,"Failed to read in any trusted certificates.");
   }

#if USE_IPV6
 if(ConfigString(Bind_IPv6))
   {
    https_fd[1]=OpenServerSocket(ConfigString(Bind_IPv6),ConfigInteger(HTTPS_Port));
    if(https_fd[1]==-1)
       PrintMessage(Fatal,"Cannot create HTTPS IPv6 server socket.");
   }
#endif

 if(ConfigString(Bind_IPv4))
   {
    https_fd[0]=OpenServerSocket(ConfigString(Bind_IPv4),ConfigInteger(HTTPS_Port));
    if(https_fd[0]==-1)
      {
#if USE_IPV6
       if(https_fd[1]!=-1 && ConfigString(Bind_IPv4) && !strcmp(ConfigString(Bind_IPv4),"0.0.0.0") &&
                             ConfigString(Bind_IPv6) && !strcmp(ConfigString(Bind_IPv6),"[0:0:0:0:0:0:0:0]"))
          PrintMessage(Warning,"Cannot create HTTPS IPv4 server socket (but the IPv6 one might accept IPv4 connections).");
       else
          PrintMessage(Fatal,"Cannot create HTTPS IPv4 server socket.");
#else
       PrintMessage(Fatal,"Cannot create HTTPS server socket.");
#endif
      }
   }

 if(https_fd[0]==-1 && https_fd[1]==-1)
   {
#if USE_IPV6
    PrintMessage(Fatal,"The IPv4 and IPv6 HTTPS sockets were not bound; are they disabled in the config file?");
#else
    PrintMessage(Fatal,"The HTTPS socket was not bound; is it disabled in the config file?");
#endif
   }

 /* Bind the WWWOFFLE control socket(s). */

#if USE_IPV6
 if(ConfigString(Bind_IPv6))
   {
    wwwoffle_fd[1]=OpenServerSocket(ConfigString(Bind_IPv6),ConfigInteger(WWWOFFLE_Port));
    if(wwwoffle_fd[1]==-1)
       PrintMessage(Fatal,"Cannot create WWWOFFLE IPv6 server socket.");
   }
#endif

 if(ConfigString(Bind_IPv4))
   {
    wwwoffle_fd[0]=OpenServerSocket(ConfigString(Bind_IPv4),ConfigInteger(WWWOFFLE_Port));
    if(wwwoffle_fd[0]==-1)
      {
#if USE_IPV6
       if(wwwoffle_fd[1]!=-1 && ConfigString(Bind_IPv4) && !strcmp(ConfigString(Bind_IPv4),"0.0.0.0") &&
                                ConfigString(Bind_IPv6) && !strcmp(ConfigString(Bind_IPv6),"[0:0:0:0:0:0:0:0]")) {
          PrintMessage(Warning,"Cannot create WWWOFFLE IPv4 server socket (but the IPv6 one might accept IPv4 connections).");
          PrintMessage(Warning,"Consider adding \"bind-ipv4 = none\" to wwwoffle.conf if using IPv6.");
       }
       else
          PrintMessage(Fatal,"Cannot create WWWOFFLE IPv4 server socket.");
#else
       PrintMessage(Fatal,"Cannot create WWWOFFLE server socket.");
#endif
      }
   }

 if(wwwoffle_fd[0]==-1 && wwwoffle_fd[1]==-1)
   {
#if USE_IPV6
    PrintMessage(Fatal,"The IPv4 and IPv6 WWWOFFLE sockets were not bound; are they disabled in the config file?");
#else
    PrintMessage(Fatal,"The WWWOFFLE socket was not bound; is it disabled in the config file?");
#endif
   }

 /* Detach from terminal */

 if(detached)
   {
    demoninit();

    PrintMessage(Important,"Detached from terminal and changed pid to %d.",getpid());

    if(log_file)
       InitErrorHandler("wwwoffled",-1,-1); /* pid changes after detaching, keep stderr as was. */
    else
       InitErrorHandler("wwwoffled",-1, 0); /* pid changes after detaching, disable stderr. */

    if(!log_file)
       close(STDERR_FILENO);
   }

 close(STDIN_FILENO);
 close(STDOUT_FILENO);

 install_sighandlers();

 max_servers=ConfigInteger(MaxServers);
 max_fetch_servers=ConfigInteger(MaxFetchServers);

 /* Loop around waiting for connections. */

 PrintMessage(Inform,"WWWOFFLE Ready to accept connections.");

 do
   {
    struct timeval tv;
    fd_set readfd;
    int nfds=0,nfd=0;

    FD_ZERO(&readfd);

#if USE_IPV6
       for(nfd=0;nfd<=1;nfd++)
         {
#endif
          if(http_fd[nfd]>=nfds)
             nfds=http_fd[nfd]+1;
          if(https_fd[nfd]>=nfds)
             nfds=https_fd[nfd]+1;
          if(wwwoffle_fd[nfd]>=nfds)
             nfds=wwwoffle_fd[nfd]+1;

          if(n_servers<max_servers)
            {
             if(http_fd[nfd]!=-1)
                FD_SET(http_fd[nfd],&readfd);
             if(https_fd[nfd]!=-1)
                FD_SET(https_fd[nfd],&readfd);
            }

          if(wwwoffle_fd[nfd]!=-1)
             FD_SET(wwwoffle_fd[nfd],&readfd);
#if USE_IPV6
         }
#endif

    tv.tv_sec=10;
    tv.tv_usec=0;

    if(select(nfds,&readfd,NULL,NULL,&tv)!=-1)
      {
#if USE_IPV6
       for(nfd=0;nfd<=1;nfd++)
         {
#endif
          if(wwwoffle_fd[nfd]!=-1 && FD_ISSET(wwwoffle_fd[nfd],&readfd))
            {
             char *host,*ip;
             int port,client;

             client=AcceptConnect(wwwoffle_fd[nfd]);

             if(client>=0)
               {
                init_io(client);
                configure_io_timeout(client,ConfigInteger(SocketTimeout),ConfigInteger(SocketTimeout));

                if(SocketRemoteName(client,&host,&ip,&port))
                  {
                   finish_io(client);
                   CloseSocket(client);
                  }
                else
                  {
                   char *canonical_ip=CanonicaliseHost(ip);

                   if(IsAllowedConnectHost(host) || IsAllowedConnectHost(canonical_ip))
                     {
                      PrintMessage(Important,"WWWOFFLE Connection from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */

                      CommandConnect(client);

                      if(fetch_fd!=client)
                        {
                         finish_io(client);
                         CloseSocket(client);
                        }
                     }
                   else
                     {
                      PrintMessage(Warning,"WWWOFFLE Connection rejected from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */
                      finish_io(client);
                      CloseSocket(client);
                     }

                   free(canonical_ip);
                  }
               }
            }

          if(http_fd[nfd]!=-1 && FD_ISSET(http_fd[nfd],&readfd))
            {
             char *host,*ip;
             int port,client;

             client=AcceptConnect(http_fd[nfd]);

             if(client>=0)
               {
                init_io(client);
                configure_io_timeout(client,ConfigInteger(SocketTimeout),ConfigInteger(SocketTimeout));

                if(!SocketRemoteName(client,&host,&ip,&port))
                  {
                   char *canonical_ip=CanonicaliseHost(ip);

                   if(IsAllowedConnectHost(host) || IsAllowedConnectHost(canonical_ip))
                     {
                      PrintMessage(Inform,"HTTP Proxy connection from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */
                      ForkServer(client);
                     }
                   else
                      PrintMessage(Warning,"HTTP Proxy connection rejected from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */

                   free(canonical_ip);
                  }

                if(nofork)
                   got_sigexit=1;

                if(!nofork)
                  {
                   finish_io(client);
                   CloseSocket(client);
                  }
               }
            }

          if(https_fd[nfd]!=-1 && FD_ISSET(https_fd[nfd],&readfd))
            {
             char *host,*ip;
             int port,client;

             client=AcceptConnect(https_fd[nfd]);

             if(client>=0)
               {
                init_io(client);
                configure_io_timeout(client,ConfigInteger(SocketTimeout),ConfigInteger(SocketTimeout));

                if(!SocketRemoteName(client,&host,&ip,&port))
                  {
                   char *canonical_ip=CanonicaliseHost(ip);

                   if(IsAllowedConnectHost(host) || IsAllowedConnectHost(canonical_ip))
                     {
                      PrintMessage(Inform,"HTTPS Proxy connection from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */
                      ForkServer(client);
                     }
                   else
                      PrintMessage(Warning,"HTTPS Proxy connection rejected from host %s (%s).",host,canonical_ip); /* Used in audit-usage.pl */

                   free(canonical_ip);
                  }

                if(nofork)
                   got_sigexit=1;

                if(!nofork)
                  {
                   finish_io(client);
                   CloseSocket(client);
                  }
               }
            }

#if USE_IPV6
         }
#endif
      }

    if(got_sighup)
      {
       got_sighup=0;

       PrintMessage(Important,"SIGHUP signalled.");

       if(log_file)
         {
          PrintMessage(Important,"Closing and opening log file.");

          OpenErrorLog(log_file);
         }

       PrintMessage(Important,"WWWOFFLE Re-reading Configuration File.");

       if(ReadConfigurationFile(-1))
          PrintMessage(Warning,"Error in configuration file; keeping old values.");

       PrintMessage(Important,"WWWOFFLE Finished Re-reading Configuration File.");
      }

    if(got_sigchld)
      {
       int pid, status;
       int isserver=0;

       /* To avoid race conditions, reset the flag before fetching the status */

       got_sigchld=0;

       while((pid=waitpid(-1,&status,WNOHANG))>0)
         {
          int i;
          int exitval=0;

          if(WIFEXITED(status))
             exitval=WEXITSTATUS(status);
          else if(WIFSIGNALED(status))
             exitval=-WTERMSIG(status);

          if(purging)
             if(purge_pid==pid)
               {
                if(exitval>=0)
                   PrintMessage(Inform,"Purge process exited with status %d (pid=%d).",exitval,pid);
                else
                   PrintMessage(Important,"Purge process terminated by signal %d (pid=%d).",-exitval,pid);

                purging=0;
               }

          for(i=0;i<max_servers;i++)
             if(server_pids[i]==pid)
               {
                n_servers--;
                server_pids[i]=0;
                isserver=1;

                if(exitval>=0)
                   PrintMessage(Inform,"Child wwwoffles exited with status %d (pid=%d).",exitval,pid);
                else
                   PrintMessage(Important,"Child wwwoffles terminated by signal %d (pid=%d).",-exitval,pid);

                break;
               }

          /* Check if the child that terminated is one of the fetching wwwoffles */

          for(i=0;i<max_fetch_servers;i++)
             if(fetch_pids[i]==pid)
               {
                n_fetch_servers--;
                fetch_pids[i]=0;
                break;
               }

          if(exitval==3)
             fetching=0;

          if(exitval==4 && online!=0)
             fetching=1;

          if(online==0)
             fetching=0;
         }

       if(isserver)
          PrintMessage(Debug,"Currently running: %d servers total, %d fetchers.",n_servers,n_fetch_servers);
      }

    /* The select timed out or we got a signal. If we are currently fetching,
       start fetch servers to look for jobs in the spool directory. */

    while(fetching && n_fetch_servers<max_fetch_servers && n_servers<max_servers)
       ForkServer(fetch_fd);

    if(fetch_fd!=-1 && !fetching && n_fetch_servers==0)
      {
       write_string(fetch_fd,"WWWOFFLE No more to fetch.\n");

       finish_io(fetch_fd);
       CloseSocket(fetch_fd);
       fetch_fd=-1;

       PrintMessage(Important,"WWWOFFLE Fetch finished.");

       ForkRunModeScript(ConfigString(RunFetch),"fetch","stop",-1);
      }
   }
 while(!got_sigexit);

 /* Close down and exit. */

 /* These four sockets don't need finish_io() calling because they never
    had init_io() called, they are just bound to a port listening. */

 if(http_fd[0]!=-1) CloseSocket(http_fd[0]);
 if(http_fd[1]!=-1) CloseSocket(http_fd[1]);
 if(wwwoffle_fd[0]!=-1) CloseSocket(wwwoffle_fd[0]);
 if(wwwoffle_fd[1]!=-1) CloseSocket(wwwoffle_fd[1]);

 if(!nofork)
   {
    if(n_servers)
       PrintMessage(Important,"Exit signalled - waiting for %d child wwwoffles servers.",n_servers);
    else
       PrintMessage(Important,"Exit signalled.");
   }

 while(n_servers)
   {
    int i;
    int pid,status,exitval=0;

    while((pid=waitpid(-1,&status,0))>0)
      {
       if(WIFEXITED(status))
          exitval=WEXITSTATUS(status);
       else if(WIFSIGNALED(status))
          exitval=-WTERMSIG(status);

       for(i=0;i<max_servers;i++)
          if(server_pids[i]==pid)
            {
             n_servers--;
             server_pids[i]=0;

             if(exitval>=0)
                PrintMessage(Inform,"Child wwwoffles exited with status %d (pid=%d).",exitval,pid);
             else
                PrintMessage(Important,"Child wwwoffles terminated by signal %d (pid=%d).",-exitval,pid);

             break;
            }

       if(purging)
          if(purge_pid==pid)
            {
             if(exitval>=0)
                PrintMessage(Inform,"Purge process exited with status %d (pid=%d).",exitval,pid);
             else
                PrintMessage(Important,"Purge process terminated by signal %d (pid=%d).",-exitval,pid);

             purging=0;
            }
      }
   }

 PrintMessage(Important,"Exiting.");

 FinishConfigurationFile();

 FreeLoadedCredentials();

 return(0);
}