Exemple #1
0
int main(int argc, char **argv)
{
	clearenv();

	init();

	printf("Initial: ");
	print();

	check_perms();

	printf("* TEMPORARY DROP \n");
	drop_temporarily();

	check_perms();

	printf("* RESTORE \n");
	restore();

	check_perms();

	printf("* PERNAMENT DROP \n");
	drop_pernamently();

	check_perms();


	printf("* RESTORE (we should fail now) \n");
	restore();

	check_perms();
		

	return 0;
}
Exemple #2
0
static void alarm_handler(int sig)
{
  axio_eolmode(NodeIo, EOLMODE_TEXT);
  axio_puts("\n",NodeIo);
  if (check_perms(PERM_ANSI, 0L) != -1) {
    axio_printf(NodeIo,"\e[05;31m");
  }
Exemple #3
0
/*
 * main - groupadd command
 */
int main (int argc, char **argv)
{
	/*
	 * Get my name so that I can use it to report errors.
	 */
	Prog = Basename (argv[0]);

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	process_root_flag ("-R", argc, argv);
	prefix = process_prefix_flag ("-P", argc, argv);

	OPENLOG ("groupadd");
#ifdef WITH_AUDIT
	audit_help_open ();
#endif

	if (atexit (do_cleanups) != 0) {
		fprintf (stderr,
		         _("%s: Cannot setup cleanup service.\n"),
		         Prog);
		exit (1);
	}

	/*
	 * Parse the command line options.
	 */
	process_flags (argc, argv);

	check_perms ();

#ifdef SHADOWGRP
	is_shadow_grp = sgr_file_present ();
#endif

	/*
	 * Do the hard stuff - open the files, create the group entries,
	 * then close and update the files.
	 */
	open_files ();

	if (!gflg) {
		if (find_new_gid (rflg, &group_id, NULL) < 0) {
			exit (E_GID_IN_USE);
		}
	}

	grp_update ();
	close_files ();

	nscd_flush_cache ("group");

	return E_SUCCESS;
}
Exemple #4
0
void handle_property_set_fd()
{
    prop_msg msg;
    int s;
    int r;
    int res;
    struct ucred cr;
    struct sockaddr_un addr;
    socklen_t addr_size = sizeof(addr);
    socklen_t cr_size = sizeof(cr);

    if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
        return;
    }

    /* Check socket options here */
    if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
        close(s);
        ERROR("Unable to recieve socket options\n");
        return;
    }

    r = recv(s, &msg, sizeof(msg), 0);
    close(s);
    if(r != sizeof(prop_msg)) {
        ERROR("sys_prop: mis-match msg size recieved: %d expected: %d\n",
              r, sizeof(prop_msg));
        return;
    }

    switch(msg.cmd) {
    case PROP_MSG_SETPROP:
        msg.name[PROP_NAME_MAX-1] = 0;
        msg.value[PROP_VALUE_MAX-1] = 0;

        if(memcmp(msg.name,"ctl.",4) == 0) {
            if (check_control_perms(msg.value, cr.uid, cr.gid)) {
                handle_control_message((char*) msg.name + 4, (char*) msg.value);
            } else {
                ERROR("sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n",
                        msg.name + 4, msg.value, cr.uid, cr.pid);
            }
        } else {
            if (check_perms(msg.name, cr.uid, cr.gid)) {
                property_set((char*) msg.name, (char*) msg.value);
            } else {
                ERROR("sys_prop: permission denied uid:%d  name:%s\n",
                      cr.uid, msg.name);
            }
        }
        break;

    default:
        break;
    }
}
Exemple #5
0
void load_upsdconf(int reloading)
{
    char	fn[SMALLBUF];
    PCONF_CTX_t	ctx;

    snprintf(fn, sizeof(fn), "%s/upsd.conf", confpath());

    check_perms(fn);

    pconf_init(&ctx, upsd_conf_err);

    if (!pconf_file_begin(&ctx, fn)) {
        pconf_finish(&ctx);

        if (!reloading)
            fatalx(EXIT_FAILURE, "%s", ctx.errmsg);

        upslogx(LOG_ERR, "Reload failed: %s", ctx.errmsg);
        return;
    }

    while (pconf_file_next(&ctx)) {
        if (pconf_parse_error(&ctx)) {
            upslogx(LOG_ERR, "Parse error: %s:%d: %s",
                    fn, ctx.linenum, ctx.errmsg);
            continue;
        }

        if (ctx.numargs < 1)
            continue;

        if (!parse_upsd_conf_args(ctx.numargs, ctx.arglist)) {
            unsigned int	i;
            char	errmsg[SMALLBUF];

            snprintf(errmsg, sizeof(errmsg),
                     "upsd.conf: invalid directive");

            for (i = 0; i < ctx.numargs; i++)
                snprintfcat(errmsg, sizeof(errmsg), " %s",
                            ctx.arglist[i]);

            upslogx(LOG_WARNING, "%s", errmsg);
        }

    }

    pconf_finish(&ctx);
}
Exemple #6
0
int do_sendto(message *dev_m_in, message *dev_m_out)
{
	int minor;
	int rc;
	struct sockaddr_un addr;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] do_sendto() call_count=%d\n", uds_minor(dev_m_in),
							++call_count);
#endif

	minor = uds_minor(dev_m_in);

	if (uds_fd_table[minor].type != SOCK_DGRAM) {
		/* This IOCTL is only for SOCK_DGRAM sockets */
		return EINVAL;
	}

	rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
		(vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un),
		D);

	if (rc != OK) {
		return EIO;
	}

	/* do some basic sanity checks on the address */
	if (addr.sun_family != AF_UNIX || addr.sun_path[0] == '\0') {
		/* bad address */
		return EINVAL;
	}

	rc = check_perms(minor, &addr);
	if (rc != OK) {
		return rc;
	}

	memcpy(&(uds_fd_table[minor].target), &addr,
					sizeof(struct sockaddr_un));

	return OK;
}
Exemple #7
0
int do_links(int argc, char **argv)
{
    struct ax_routes *axrt, *p;
    char digipath[AX25_MAX_DIGIS*10];
    char tipoconn[9];
    int i=0;

    axio_puts("",NodeIo);
    if (User.ul_type == AF_NETROM) {
        axio_printf(NodeIo,"%s} ", NodeId);
    }
    if ((axrt=read_ax_routes()) == NULL) {
        if (errno) node_perror("do_links: read_ax_routes", errno);
        else axio_printf(NodeIo,"No known links");
        if (User.ul_type == AF_NETROM) {
            node_msg("");
        }
        return 0;
    }

    /* "links" */
    if (check_perms(PERM_ANSI, 0L) != -1) {
        axio_printf(NodeIo, "\e[01;33m");
    }
Exemple #8
0
/*
 * Initiate a AX.25, NET/ROM, ROSE or TCP connection to the host
 * specified by `address'.
 */
static ax25io *connect_to(char **addr, int family, int escape, int compr)
{
  int fd;
  ax25io *riop;
  fd_set read_fdset;
  fd_set write_fdset;
  int salen;
  union {
    struct full_sockaddr_ax25 ax;
#ifdef HAVE_ROSE
    struct sockaddr_rose      rs;
#endif		
    struct sockaddr_in        in;
  } sa;
  char call[10], path[20], *cp, *eol;
  int ret, retlen = sizeof(int);
  int paclen;
  struct hostent *hp;
  struct servent *sp;
  struct user u;
#ifdef HAVE_NETROM
  struct proc_nr_nodes *np;
#endif

  strcpy(call, User.call);
  /*
   * Fill in protocol spesific stuff.
   */
  switch (family) {
#ifdef HAVE_ROSE	
  case AF_ROSE:
    if (aliascmd==0) {
      if (check_perms(PERM_ROSE, 0L) == -1) {
	axio_printf(NodeIo,"Permission denied");
	if (User.ul_type == AF_NETROM) {
	  node_msg("");
	}
	node_log(LOGLVL_GW, "Permission denied: rose");
	return NULL;
      }
    }
    if ((fd = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) {
      node_perror("connect_to: socket", errno);
      return NULL;
    }
    sa.rs.srose_family = AF_ROSE;
    sa.rs.srose_ndigis = 0;
    ax25_aton_entry(call, sa.rs.srose_call.ax25_call);
    rose_aton(rs_config_get_addr(NULL), sa.rs.srose_addr.rose_addr);
    salen = sizeof(struct sockaddr_rose);
    if (bind(fd, (struct sockaddr *)&sa, salen) == -1) {
      node_perror("connect_to: bind", errno);
      close(fd);
      return NULL;
    }
    memset(path, 0, 11);
    memcpy(path, rs_config_get_addr(NULL), 4);
    salen = strlen(addr[1]);
    if ((salen != 6) && (salen != 10))
      {
	axio_printf(NodeIo,"Invalid ROSE address");
	if (User.ul_type == AF_NETROM) {
	  node_msg("");
	}
	return(NULL);
      }
    memcpy(path + (10-salen), addr[1], salen);
    sprintf(User.dl_name, "%s @ %s", addr[0], path);
    sa.rs.srose_family = AF_ROSE;
    sa.rs.srose_ndigis = 0;
    if (ax25_aton_entry(addr[0], sa.rs.srose_call.ax25_call) < 0) {
      close(fd);
      return NULL;
    }
    if (rose_aton(path, sa.rs.srose_addr.rose_addr) < 0) {
      close(fd);
      return NULL;
    }
    if (addr[2] != NULL) {
      if (ax25_aton_entry(addr[2], sa.rs.srose_digi.ax25_call) < 0) {
	close(fd);
	return NULL;
      }
      sa.rs.srose_ndigis = 1;
    }
    salen = sizeof(struct sockaddr_rose);
    paclen = rs_config_get_paclen(NULL);
    eol = ROSE_EOL;
    /* Uncomment the below if you wish to have the node show a 'Trying' state */
    /*    node_msg("%s Trying %s... Type <RETURN> to abort", User.dl_name); */
    break;
#endif		
#ifdef HAVE_NETROM
  case AF_NETROM:
    if (aliascmd==0) {
      if (check_perms(PERM_NETROM, 0L) == -1) {
	axio_printf(NodeIo,"Permission denied");
	if (User.ul_type == AF_NETROM) {
	  node_msg("");
	}
	node_log(LOGLVL_GW, "Permission denied: netrom");
	return NULL;
      }
    }
    if ((fd = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) {
      node_perror("connect_to: socket", errno);
      return NULL;
    }
    /* Why on earth is this different from ax.25 ????? */
    sprintf(path, "%s %s", nr_config_get_addr(NrPort), call); 
    ax25_aton(path, &sa.ax);
    sa.ax.fsa_ax25.sax25_family = AF_NETROM;
    salen = sizeof(struct full_sockaddr_ax25);
    if (bind(fd, (struct sockaddr *)&sa, salen) == -1) {
      node_perror("connect_to: bind", errno);
      close(fd);
      return NULL;
    }
    if ((np = find_node(addr[0], NULL)) == NULL) {
      axio_printf(NodeIo,"No such node");
      if (User.ul_type == AF_NETROM) {
	node_msg("");
      }
      return NULL;
    }
    strcpy(User.dl_name, print_node(np->alias, np->call));
    if (ax25_aton(np->call, &sa.ax) == -1) {
      close(fd);
      return NULL;
    }
    sa.ax.fsa_ax25.sax25_family = AF_NETROM;
    salen = sizeof(struct sockaddr_ax25);
    paclen = nr_config_get_paclen(NrPort); 
    eol = NETROM_EOL;
    /* Uncomment the below if you wish the node to show a 'Trying' state */
    if (check_perms(PERM_ANSI, 0L) != -1) {
      if (User.ul_type == AF_NETROM) {
	break;
      }
      node_msg("\e[01;36mTrying %s... hit <Enter> to abort", User.dl_name);
    }
    break;
#endif
#ifdef HAVE_AX25
  case AF_FLEXNET:
  case AF_AX25:
    if (aliascmd==0) {    
      if (check_perms(PERM_AX25, 0L) == -1 || (is_hidden(addr[0]) && check_perms(PERM_HIDDEN, 0L) == -1)) {
	axio_printf(NodeIo,"Permission denied");
	if (User.ul_type == AF_NETROM) {
	  node_msg("");
	}
	node_log(LOGLVL_GW, "Permission denied: ax.25 port %s", addr[0]);
	return NULL;
      }
    }
    if (ax25_config_get_addr(addr[0]) == NULL) {
      if (User.ul_type == AF_NETROM) {
	axio_printf(NodeIo,"%s} ", NodeId);
      }
      axio_printf(NodeIo,"Invalid port");
      if (User.ul_type == AF_NETROM) {
      	node_msg("");
      }
      return NULL;
    }
    if ((fd = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
      node_perror("connect_to: socket", errno);
      return NULL;
    }
    /*
     * Invert the SSID only if user is coming in with AX.25
     * and going out on the same port he is coming in via.
     */
    if (User.ul_type == AF_AX25 && !strcasecmp(addr[0], User.ul_name))
      invert_ssid(call, User.call);
    sprintf(path, "%s %s", call, ax25_config_get_addr(addr[0]));
    ax25_aton(path, &sa.ax);
    sa.ax.fsa_ax25.sax25_family = AF_AX25;
    salen = sizeof(struct full_sockaddr_ax25);
    if (bind(fd, (struct sockaddr *)&sa, salen) < 0) {
      node_perror("connect_to: bind", errno);
      close(fd);
      return NULL;
    }
    if (ax25_aton_arglist((const char **)addr+1, &sa.ax) < 0) {
      close(fd);
      return NULL;
    }
    strcpy(User.dl_name, strupr(addr[1]));
    strcpy(User.dl_port, strlwr(addr[0]));
    sa.ax.fsa_ax25.sax25_family = AF_AX25;
    salen = sizeof(struct full_sockaddr_ax25);
    paclen = ax25_config_get_paclen(addr[0]);
    eol = AX25_EOL;
    /* Uncomment the below if you wish the node to show a 'Trying' state */
    /*    if (family==AF_FLEXNET) node_msg("Trying %s via FlexNet... Type <RETURN> to abort", User.dl_name); */
    if ((family==AF_FLEXNET) || (family == AF_AX25)) { 
      if (!strcmp(User.dl_port,User.ul_name)) {
        if (check_perms(PERM_ANSI, 0L) != -1) {
	  axio_printf(NodeIo, "\e[05;31m");
	}
        axio_printf(NodeIo,"\aLoop detected on ");
      }
      if (check_perms(PERM_ANSI, 0L) != -1) {
	axio_printf(NodeIo, "\e[0;m");
      }
      if (User.ul_type == AF_NETROM) {
	axio_printf(NodeIo, "%s} ", NodeId);
      }
      if (check_perms(PERM_ANSI, 0L) != -1) {
	axio_printf(NodeIo, "\e[01;33m");
      }
Exemple #9
0
/*
 * gpasswd - administer the /etc/group file
 */
int main (int argc, char **argv)
{
	struct group grent;
#ifdef SHADOWGRP
	struct sgrp sgent;
#endif
	struct passwd *pw = NULL;

#ifdef WITH_AUDIT
	audit_help_open ();
#endif

	sanitize_env ();
	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	/*
	 * Make a note of whether or not this command was invoked by root.
	 * This will be used to bypass certain checks later on. Also, set
	 * the real user ID to match the effective user ID. This will
	 * prevent the invoker from issuing signals which would interfere
	 * with this command.
	 */
	bywho = getuid ();
	Prog = Basename (argv[0]);

	OPENLOG ("gpasswd");
	setbuf (stdout, NULL);
	setbuf (stderr, NULL);

#ifdef SHADOWGRP
	is_shadowgrp = sgr_file_present ();
#endif

	/*
	 * Determine the name of the user that invoked this command. This
	 * is really hit or miss because there are so many ways that command
	 * can be executed and so many ways to trip up the routines that
	 * report the user name.
	 */
	pw = get_my_pwent ();
	if (NULL == pw) {
		fprintf (stderr, _("%s: Cannot determine your user name.\n"),
		         Prog);
		SYSLOG ((LOG_WARN,
		         "Cannot determine the user name of the caller (UID %lu)",
		         (unsigned long) getuid ()));
		exit (E_NOPERM);
	}
	myname = xstrdup (pw->pw_name);

	/*
	 * Register an exit function to warn for any inconsistency that we
	 * could create.
	 */
	if (atexit (do_cleanups) != 0) {
		fprintf(stderr, "%s: cannot set exit function\n", Prog);
		exit (1);
	}

	/* Parse the options */
	process_flags (argc, argv);

	/*
	 * Replicate the group so it can be modified later on.
	 */
#ifdef SHADOWGRP
	get_group (&grent, &sgent);
#else
	get_group (&grent);
#endif

	/*
	 * Check if the user is allowed to change the password of this group.
	 */
#ifdef SHADOWGRP
	check_perms (&grent, &sgent);
#else
	check_perms (&grent);
#endif

	/*
	 * Removing a password is straight forward. Just set the password
	 * field to a "".
	 */
	if (rflg) {
		grent.gr_passwd = "";	/* XXX warning: const */
#ifdef SHADOWGRP
		sgent.sg_passwd = "";	/* XXX warning: const */
#endif
		goto output;
	} else if (Rflg) {
		/*
		 * Same thing for restricting the group. Set the password
		 * field to "!".
		 */
		grent.gr_passwd = "!";	/* XXX warning: const */
#ifdef SHADOWGRP
		sgent.sg_passwd = "!";	/* XXX warning: const */
#endif
		goto output;
	}

	/*
	 * Adding a member to a member list is pretty straightforward as
	 * well. Call the appropriate routine and split.
	 */
	if (aflg) {
		printf (_("Adding user %s to group %s\n"), user, group);
		grent.gr_mem = add_list (grent.gr_mem, user);
#ifdef SHADOWGRP
		if (is_shadowgrp) {
			sgent.sg_mem = add_list (sgent.sg_mem, user);
		}
#endif
		goto output;
	}

	/*
	 * Removing a member from the member list is the same deal as adding
	 * one, except the routine is different.
	 */
	if (dflg) {
		bool removed = false;

		printf (_("Removing user %s from group %s\n"), user, group);

		if (is_on_list (grent.gr_mem, user)) {
			removed = true;
			grent.gr_mem = del_list (grent.gr_mem, user);
		}
#ifdef SHADOWGRP
		if (is_shadowgrp) {
			if (is_on_list (sgent.sg_mem, user)) {
				removed = true;
				sgent.sg_mem = del_list (sgent.sg_mem, user);
			}
		}
#endif
		if (!removed) {
			fprintf (stderr,
			         _("%s: user '%s' is not a member of '%s'\n"),
			         Prog, user, group);
			exit (E_BAD_ARG);
		}
		goto output;
	}
#ifdef SHADOWGRP
	/*
	 * Replacing the entire list of administrators is simple. Check the
	 * list to make sure everyone is a real user. Then slap the new list
	 * in place.
	 */
	if (Aflg) {
		sgent.sg_adm = comma_to_list (admins);
		if (!Mflg) {
			goto output;
		}
	}
#endif				/* SHADOWGRP */

	/*
	 * Replacing the entire list of members is simple. Check the list to
	 * make sure everyone is a real user. Then slap the new list in
	 * place.
	 */
	if (Mflg) {
#ifdef SHADOWGRP
		sgent.sg_mem = comma_to_list (members);
#endif
		grent.gr_mem = comma_to_list (members);
		goto output;
	}

	/*
	 * If the password is being changed, the input and output must both
	 * be a tty. The typical keyboard signals are caught so the termio
	 * modes can be restored.
	 */
	if ((isatty (0) == 0) || (isatty (1) == 0)) {
		fprintf (stderr, _("%s: Not a tty\n"), Prog);
		exit (E_NOPERM);
	}

	catch_signals (0);	/* save tty modes */

	(void) signal (SIGHUP, catch_signals);
	(void) signal (SIGINT, catch_signals);
	(void) signal (SIGQUIT, catch_signals);
	(void) signal (SIGTERM, catch_signals);
#ifdef SIGTSTP
	(void) signal (SIGTSTP, catch_signals);
#endif

	/* Prompt for the new password */
#ifdef SHADOWGRP
	change_passwd (&grent, &sgent);
#else
	change_passwd (&grent);
#endif

	/*
	 * This is the common arrival point to output the new group file.
	 * The freshly crafted entry is in allocated space. The group file
	 * will be locked and opened for writing. The new entry will be
	 * output, etc.
	 */
      output:
	if (setuid (0) != 0) {
		fputs (_("Cannot change ID to root.\n"), stderr);
		SYSLOG ((LOG_ERR, "can't setuid(0)"));
		closelog ();
		exit (E_NOPERM);
	}
	pwd_init ();

	open_files ();

#ifdef SHADOWGRP
	update_group (&grent, &sgent);
#else
	update_group (&grent);
#endif

	close_files ();

	nscd_flush_cache ("group");

	exit (E_SUCCESS);
}
Exemple #10
0
/*
 * chfn - change a user's password file information
 *
 *	This command controls the GECOS field information in the password
 *	file entry.
 *
 *	The valid options are
 *
 *	-f	full name
 *	-r	room number
 *	-w	work phone number
 *	-h	home phone number
 *	-o	other information (*)
 *
 *	(*) requires root permission to execute.
 */
int main (int argc, char **argv)
{
	const struct passwd *pw;	/* password file entry               */
	char new_gecos[BUFSIZ];	/* buffer for new GECOS fields       */
	char *user;

	/*
	 * Get the program name. The program name is used as a
	 * prefix to most error messages.
	 */
	Prog = Basename (argv[0]);

	sanitize_env ();
	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	process_root_flag ("-R", argc, argv);

	/*
	 * This command behaves different for root and non-root
	 * users.
	 */
	amroot = (getuid () == 0);

	OPENLOG ("chfn");

	/* parse the command line options */
	process_flags (argc, argv);

	/*
	 * Get the name of the user to check. It is either the command line
	 * name, or the name getlogin() returns.
	 */
	if (optind < argc) {
		user = argv[optind];
		pw = xgetpwnam (user);
		if (NULL == pw) {
			fprintf (stderr, _("%s: user '%s' does not exist\n"), Prog,
			         user);
			fail_exit (E_NOPERM);
		}
	} else {
		pw = get_my_pwent ();
		if (NULL == pw) {
			fprintf (stderr,
			         _("%s: Cannot determine your user name.\n"),
			         Prog);
			SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
			         (unsigned long) getuid ()));
			fail_exit (E_NOPERM);
		}
		user = xstrdup (pw->pw_name);
	}

#ifdef	USE_NIS
	/*
	 * Now we make sure this is a LOCAL password entry for this user ...
	 */
	if (__ispwNIS ()) {
		char *nis_domain;
		char *nis_master;

		fprintf (stderr,
		         _("%s: cannot change user '%s' on NIS client.\n"),
		         Prog, user);

		if (!yp_get_default_domain (&nis_domain) &&
		    !yp_master (nis_domain, "passwd.byname", &nis_master)) {
			fprintf (stderr,
			         _
			         ("%s: '%s' is the NIS master for this client.\n"),
			         Prog, nis_master);
		}
		fail_exit (E_NOPERM);
	}
#endif

	/* Check that the caller is allowed to change the gecos of the
	 * specified user */
	check_perms (pw);

	/* If some fields were not set on the command line, load the value from
	 * the old gecos fields. */
	get_old_fields (pw->pw_gecos);

	/*
	 * If none of the fields were changed from the command line, let the
	 * user interactively change them.
	 */
	if (!fflg && !rflg && !wflg && !hflg && !oflg) {
		printf (_("Changing the user information for %s\n"), user);
		new_fields ();
	}

	/*
	 * Check all of the fields for valid information
	 */
	check_fields ();

	/*
	 * Build the new GECOS field by plastering all the pieces together,
	 * if they will fit ...
	 */
	if ((strlen (fullnm) + strlen (roomno) + strlen (workph) +
	     strlen (homeph) + strlen (slop)) > (unsigned int) 80) {
		fprintf (stderr, _("%s: fields too long\n"), Prog);
		fail_exit (E_NOPERM);
	}
	snprintf (new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s",
	          fullnm, roomno, workph, homeph,
	          ('\0' != slop[0]) ? "," : "", slop);

	/* Rewrite the user's gecos in the passwd file */
	update_gecos (user, new_gecos);

	SYSLOG ((LOG_INFO, "changed user '%s' information", user));

	nscd_flush_cache ("passwd");

	closelog ();
	exit (E_SUCCESS);
}
Exemple #11
0
int do_bind(message *dev_m_in, message *dev_m_out)
{
	int minor;
	struct sockaddr_un addr;
	int rc, i;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] do_bind() call_count=%d\n", uds_minor(dev_m_in),
							++call_count);
#endif

	minor = uds_minor(dev_m_in);

	if ((uds_fd_table[minor].type == -1) ||
		(uds_fd_table[minor].addr.sun_family == AF_UNIX &&
		uds_fd_table[minor].type != SOCK_DGRAM)) {

		/* the type hasn't been set by do_socket() yet OR attempting
		 * to re-bind() a non-SOCK_DGRAM socket
		 */
		return EINVAL;
	}

	rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
		(vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un));

	if (rc != OK) {
		return EIO;
	}

	/* do some basic sanity checks on the address */
	if (addr.sun_family != AF_UNIX) {

		/* bad family */
		return EAFNOSUPPORT;
	}

	if (addr.sun_path[0] == '\0') {

		/* bad address */
		return ENOENT;
	}

	rc = check_perms(minor, &addr);
	if (rc != OK) {
		/* permission denied, socket file doesn't exist, etc. */
		return rc;
	}

	/* make sure the address isn't already in use by another socket. */
	for (i = 0; i < NR_FDS; i++) {
		if ((uds_fd_table[i].addr.sun_family == AF_UNIX) &&
			!strncmp(addr.sun_path,
			uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) {

			/* another socket is bound to this sun_path */
			return EADDRINUSE;
		}
	}

	/* looks good, perform the bind() */
	memcpy(&(uds_fd_table[minor].addr), &addr, sizeof(struct sockaddr_un));

	return OK;
}
Exemple #12
0
void handle_property_set_fd()
{
    prop_msg msg;
    int s;
    int r;
    int res;
    struct ucred cr;
    struct sockaddr_un addr;
    socklen_t addr_size = sizeof(addr);
    socklen_t cr_size = sizeof(cr);
    char * source_ctx = NULL;
    struct pollfd ufds[1];
    const int timeout_ms = 2 * 1000;  /* Default 2 sec timeout for caller to send property. */
    int nr;

    if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
        return;
    }

    /* Check socket options here */
    if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
        close(s);
        ERROR("Unable to receive socket options\n");
        return;
    }

    ufds[0].fd = s;
    ufds[0].events = POLLIN;
    ufds[0].revents = 0;
    nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms));
    if (nr == 0) {
        ERROR("sys_prop: timeout waiting for pid=%d uid=%d gid=%d to send property message.\n", cr.pid, cr.uid, cr.gid);
        close(s);
        return;
    } else if (nr < 0) {
        ERROR("sys_prop: error waiting for pid=%d uid=%d gid=%d to send property message. err=%d %s\n", cr.pid, cr.uid, cr.gid, errno, strerror(errno));
        close(s);
        return;
    }

    r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), MSG_DONTWAIT));
    if(r != sizeof(prop_msg)) {
        ERROR("sys_prop: mis-match msg size received: %d from pid=%d uid=%d gid=%d expected: %zu errno: %d\n",
              r, cr.pid, cr.uid, cr.gid, sizeof(prop_msg), errno);
        close(s);
        return;
    }

    switch(msg.cmd) {
    case PROP_MSG_SETPROP:
        msg.name[PROP_NAME_MAX-1] = 0;
        msg.value[PROP_VALUE_MAX-1] = 0;

        if (!is_legal_property_name(msg.name, strlen(msg.name))) {
            ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name);
            close(s);
            return;
        }

        getpeercon(s, &source_ctx);

        if(memcmp(msg.name,"ctl.",4) == 0) {
            // Keep the old close-socket-early behavior when handling
            // ctl.* properties.
            close(s);
            if (check_control_mac_perms(msg.value, source_ctx)) {
#ifdef MTK_INIT
				INFO("[PropSet]: pid:%u uid:%u gid:%u %s %s\n", cr.pid, cr.uid, cr.gid, msg.name, msg.value);
#endif
                handle_control_message((char*) msg.name + 4, (char*) msg.value);
            } else {
                ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",
                        msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);
            }
        } else {
            if (check_perms(msg.name, source_ctx)) {
#ifdef MTK_INIT
				INFO("[PropSet]: pid:%u uid:%u gid:%u set %s=%s\n", cr.pid, cr.uid, cr.gid, msg.name, msg.value);
				if(strcmp(msg.name, ANDROID_RB_PROPERTY) == 0)
				{
					INFO("pid %d set %s=%s\n", cr.pid, msg.name, msg.value);
					reboot_pid(cr.pid);
				}
#endif
                property_set((char*) msg.name, (char*) msg.value);
            } else {
                ERROR("sys_prop: permission denied uid:%d  name:%s\n",
                      cr.uid, msg.name);
            }

            // Note: bionic's property client code assumes that the
            // property server will not close the socket until *AFTER*
            // the property is written to memory.
            close(s);
        }
        freecon(source_ctx);
        break;

    default:
        close(s);
        break;
    }
}
Exemple #13
0
int main (int argc, char **argv)
{
	char buf[BUFSIZ];
	char *name;
	char *newpwd;
	char *cp;

#ifndef USE_PAM
	const struct spwd *sp;
	struct spwd newsp;

	const struct passwd *pw;
	struct passwd newpw;
#endif				/* !USE_PAM */

	int errors = 0;
	int line = 0;

	Prog = Basename (argv[0]);

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	process_flags (argc, argv);

	OPENLOG ("chpasswd");

	check_perms ();

#ifndef USE_PAM
	is_shadow_pwd = spw_file_present ();

	open_files ();
#endif

	/*
	 * Read each line, separating the user name from the password. The
	 * password entry for each user will be looked up in the appropriate
	 * file (shadow or passwd) and the password changed. For shadow
	 * files the last change date is set directly, for passwd files the
	 * last change date is set in the age only if aging information is
	 * present.
	 */
	while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) {
		line++;
		cp = strrchr (buf, '\n');
		if (NULL != cp) {
			*cp = '\0';
		} else {
			if (feof (stdin) == 0) {
				fprintf (stderr,
				         _("%s: line %d: line too long\n"),
				         Prog, line);
				errors++;
				continue;
			}
		}

		/*
		 * The username is the first field. It is separated from the
		 * password with a ":" character which is replaced with a
		 * NUL to give the new password. The new password will then
		 * be encrypted in the normal fashion with a new salt
		 * generated, unless the '-e' is given, in which case it is
		 * assumed to already be encrypted.
		 */

		name = buf;
		cp = strchr (name, ':');
		if (NULL != cp) {
			*cp = '\0';
			cp++;
		} else {
			fprintf (stderr,
			         _("%s: line %d: missing new password\n"),
			         Prog, line);
			errors++;
			continue;
		}
		newpwd = cp;

#ifdef USE_PAM
		if (do_pam_passwd_non_interractive ("chpasswd", name, newpwd) != 0) {
			fprintf (stderr,
			         _("%s: (line %d, user %s) password not changed\n"),
			         Prog, line, name);
			errors++;
		}
#else				/* !USE_PAM */
		if (   !eflg
		    && (   (NULL == crypt_method)
		        || (0 != strcmp (crypt_method, "NONE")))) {
			void *arg = NULL;
			if (md5flg) {
				crypt_method = "MD5";
			} else if (crypt_method != NULL) {
#ifdef USE_SHA_CRYPT
				if (sflg) {
					arg = &sha_rounds;
				}
#endif
			} else {
				crypt_method = NULL;
			}
			cp = pw_encrypt (newpwd,
			                 crypt_make_salt(crypt_method, arg));
		}

		/*
		 * Get the password file entry for this user. The user must
		 * already exist.
		 */
		pw = pw_locate (name);
		if (NULL == pw) {
			fprintf (stderr,
			         _("%s: line %d: user '%s' does not exist\n"), Prog,
			         line, name);
			errors++;
			continue;
		}
		if (is_shadow_pwd) {
			sp = spw_locate (name);
		} else {
			sp = NULL;
		}

		/*
		 * The freshly encrypted new password is merged into the
		 * user's password file entry and the last password change
		 * date is set to the current date.
		 */
		if (NULL != sp) {
			newsp = *sp;
			newsp.sp_pwdp = cp;
			newsp.sp_lstchg = (long) time ((time_t *)NULL) / SCALE;
			if (0 == newsp.sp_lstchg) {
				/* Better disable aging than requiring a
				 * password change */
				newsp.sp_lstchg = -1;
			}
		} else {
			newpw = *pw;
			newpw.pw_passwd = cp;
		}

		/* 
		 * The updated password file entry is then put back and will
		 * be written to the password file later, after all the
		 * other entries have been updated as well.
		 */
		if (NULL != sp) {
			if (spw_update (&newsp) == 0) {
				fprintf (stderr,
				         _("%s: line %d: failed to prepare the new %s entry '%s'\n"),
				         Prog, line, spw_dbname (), newsp.sp_namp);
				errors++;
				continue;
			}
		} else {
			if (pw_update (&newpw) == 0) {
				fprintf (stderr,
				         _("%s: line %d: failed to prepare the new %s entry '%s'\n"),
				         Prog, line, pw_dbname (), newpw.pw_name);
				errors++;
				continue;
			}
		}
#endif				/* !USE_PAM */
	}

	/*
	 * Any detected errors will cause the entire set of changes to be
	 * aborted. Unlocking the password file will cause all of the
	 * changes to be ignored. Otherwise the file is closed, causing the
	 * changes to be written out all at once, and then unlocked
	 * afterwards.
	 *
	 * With PAM, it is not possible to delay the update of the
	 * password database.
	 */
	if (0 != errors) {
#ifndef USE_PAM
		fprintf (stderr,
		         _("%s: error detected, changes ignored\n"), Prog);
#endif
		fail_exit (1);
	}

#ifndef USE_PAM
	/* Save the changes */
	close_files ();
#endif

	nscd_flush_cache ("passwd");

	return (0);
}
Exemple #14
0
int main (int argc, char **argv)
{
	char buf[BUFSIZ];
	char *fields[8];
	int nfields;
	char *cp;
	const struct passwd *pw;
	struct passwd newpw;
	int errors = 0;
	int line = 0;
	uid_t uid;
	gid_t gid;
#ifdef USE_PAM
	int *lines = NULL;
	char **usernames = NULL;
	char **passwords = NULL;
	unsigned int nusers = 0;
#endif				/* USE_PAM */

	Prog = Basename (argv[0]);

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	/* FIXME: will not work with an input file */
	process_root_flag ("-R", argc, argv);

	OPENLOG ("newusers");

	process_flags (argc, argv);

	check_perms ();

	is_shadow = spw_file_present ();

#ifdef SHADOWGRP
	is_shadow_grp = sgr_file_present ();
#endif
#ifdef ENABLE_SUBIDS
	is_sub_uid = sub_uid_file_present () && !rflg;
	is_sub_gid = sub_gid_file_present () && !rflg;
#endif				/* ENABLE_SUBIDS */

	open_files ();

	/*
	 * Read each line. The line has the same format as a password file
	 * entry, except that certain fields are not constrained to be
	 * numerical values. If a group ID is entered which does not already
	 * exist, an attempt is made to allocate the same group ID as the
	 * numerical user ID. Should that fail, the next available group ID
	 * over 100 is allocated. The pw_gid field will be updated with that
	 * value.
	 */
	while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) {
		line++;
		cp = strrchr (buf, '\n');
		if (NULL != cp) {
			*cp = '\0';
		} else {
			if (feof (stdin) == 0) {
				fprintf (stderr,
				         _("%s: line %d: line too long\n"),
				         Prog, line);
				errors++;
				continue;
			}
		}

		/*
		 * Break the string into fields and screw around with them.
		 * There MUST be 7 colon separated fields, although the
		 * values aren't that particular.
		 */
		for (cp = buf, nfields = 0; nfields < 7; nfields++) {
			fields[nfields] = cp;
			cp = strchr (cp, ':');
			if (NULL != cp) {
				*cp = '\0';
				cp++;
			} else {
				break;
			}
		}
		if (nfields != 6) {
			fprintf (stderr, _("%s: line %d: invalid line\n"),
			         Prog, line);
			errors++;
			continue;
		}

		/*
		 * First check if we have to create or update an user
		 */
		pw = pw_locate (fields[0]);
		/* local, no need for xgetpwnam */
		if (   (NULL == pw)
		    && (getpwnam (fields[0]) != NULL)) {
			fprintf (stderr, _("%s: cannot update the entry of user %s (not in the passwd database)\n"), Prog, fields[0]);
			errors++;
			continue;
		}

		if (   (NULL == pw)
		    && (get_user_id (fields[2], &uid) != 0)) {
			fprintf (stderr,
			         _("%s: line %d: can't create user\n"),
			         Prog, line);
			errors++;
			continue;
		}

		/*
		 * Processed is the group name. A new group will be
		 * created if the group name is non-numeric and does not
		 * already exist. If the group name is a number (which is not
		 * an existing GID), a group with the same name as the user
		 * will be created, with the given GID. The given or created
		 * group will be the primary group of the user. If
		 * there is no named group to be a member of, the UID will
		 * be figured out and that value will be a candidate for a
		 * new group, if that group ID exists, a whole new group ID
		 * will be made up.
		 */
		if (   (NULL == pw)
		    && (add_group (fields[0], fields[3], &gid, uid) != 0)) {
			fprintf (stderr,
			         _("%s: line %d: can't create group\n"),
			         Prog, line);
			errors++;
			continue;
		}

		/*
		 * Now we work on the user ID. It has to be specified either
		 * as a numerical value, or left blank. If it is a numerical
		 * value, that value will be used, otherwise the next
		 * available user ID is computed and used. After this there
		 * will at least be a (struct passwd) for the user.
		 */
		if (   (NULL == pw)
		    && (add_user (fields[0], uid, gid) != 0)) {
			fprintf (stderr,
			         _("%s: line %d: can't create user\n"),
			         Prog, line);
			errors++;
			continue;
		}

		/*
		 * The password, gecos field, directory, and shell fields
		 * all come next.
		 */
		pw = pw_locate (fields[0]);
		if (NULL == pw) {
			fprintf (stderr,
			         _("%s: line %d: user '%s' does not exist in %s\n"),
			         Prog, line, fields[0], pw_dbname ());
			errors++;
			continue;
		}
		newpw = *pw;

#ifdef USE_PAM
		/* keep the list of user/password for later update by PAM */
		nusers++;
		lines     = realloc (lines,     sizeof (lines[0])     * nusers);
		usernames = realloc (usernames, sizeof (usernames[0]) * nusers);
		passwords = realloc (passwords, sizeof (passwords[0]) * nusers);
		lines[nusers-1]     = line;
		usernames[nusers-1] = strdup (fields[0]);
		passwords[nusers-1] = strdup (fields[1]);
#endif				/* USE_PAM */
		if (add_passwd (&newpw, fields[1]) != 0) {
			fprintf (stderr,
			         _("%s: line %d: can't update password\n"),
			         Prog, line);
			errors++;
			continue;
		}
		if ('\0' != fields[4][0]) {
			newpw.pw_gecos = fields[4];
		}

		if ('\0' != fields[5][0]) {
			newpw.pw_dir = fields[5];
		}

		if ('\0' != fields[6][0]) {
			newpw.pw_shell = fields[6];
		}

		if (   ('\0' != fields[5][0])
		    && (access (newpw.pw_dir, F_OK) != 0)) {
/* FIXME: should check for directory */
			mode_t msk = 0777 & ~getdef_num ("UMASK",
			                                 GETDEF_DEFAULT_UMASK);
			if (mkdir (newpw.pw_dir, msk) != 0) {
				fprintf (stderr,
				         _("%s: line %d: mkdir %s failed: %s\n"),
				         Prog, line, newpw.pw_dir,
				         strerror (errno));
			} else if (chown (newpw.pw_dir,
			                  newpw.pw_uid,
			                  newpw.pw_gid) != 0) {
				fprintf (stderr,
				         _("%s: line %d: chown %s failed: %s\n"),
				         Prog, line, newpw.pw_dir,
				         strerror (errno));
			}
		}

		/*
		 * Update the password entry with the new changes made.
		 */
		if (pw_update (&newpw) == 0) {
			fprintf (stderr,
			         _("%s: line %d: can't update entry\n"),
			         Prog, line);
			errors++;
			continue;
		}

#ifdef ENABLE_SUBIDS
		/*
		 * Add subordinate uids if the user does not have them.
		 */
		if (is_sub_uid && !sub_uid_assigned(fields[0])) {
			uid_t sub_uid_start = 0;
			unsigned long sub_uid_count = 0;
			if (find_new_sub_uids(fields[0], &sub_uid_start, &sub_uid_count) == 0) {
				if (sub_uid_add(fields[0], sub_uid_start, sub_uid_count) == 0) {
					fprintf (stderr,
						_("%s: failed to prepare new %s entry\n"),
						Prog, sub_uid_dbname ());
				}
			} else {
				fprintf (stderr,
					_("%s: can't find subordinate user range\n"),
					Prog);
				errors++;
			}
		}

		/*
		 * Add subordinate gids if the user does not have them.
		 */
		if (is_sub_gid && !sub_gid_assigned(fields[0])) {
			gid_t sub_gid_start = 0;
			unsigned long sub_gid_count = 0;
			if (find_new_sub_gids(fields[0], &sub_gid_start, &sub_gid_count) == 0) {
				if (sub_gid_add(fields[0], sub_gid_start, sub_gid_count) == 0) {
					fprintf (stderr,
						_("%s: failed to prepare new %s entry\n"),
						Prog, sub_uid_dbname ());
				}
			} else {
				fprintf (stderr,
					_("%s: can't find subordinate group range\n"),
					Prog);
				errors++;
			}
		}
#endif				/* ENABLE_SUBIDS */
	}

	/*
	 * Any detected errors will cause the entire set of changes to be
	 * aborted. Unlocking the password file will cause all of the
	 * changes to be ignored. Otherwise the file is closed, causing the
	 * changes to be written out all at once, and then unlocked
	 * afterwards.
	 */
	if (0 != errors) {
		fprintf (stderr,
		         _("%s: error detected, changes ignored\n"), Prog);
		fail_exit (EXIT_FAILURE);
	}

	close_files ();

	nscd_flush_cache ("passwd");
	nscd_flush_cache ("group");
	sssd_flush_cache (SSSD_DB_PASSWD | SSSD_DB_GROUP);

#ifdef USE_PAM
	unsigned int i;
	/* Now update the passwords using PAM */
	for (i = 0; i < nusers; i++) {
		if (do_pam_passwd_non_interactive ("newusers", usernames[i], passwords[i]) != 0) {
			fprintf (stderr,
			         _("%s: (line %d, user %s) password not changed\n"),
			         Prog, lines[i], usernames[i]);
			errors++;
		}
	}
#endif				/* USE_PAM */

	return ((0 == errors) ? EXIT_SUCCESS : EXIT_FAILURE);
}
Exemple #15
0
int main (int argc, char **argv)
{
	const struct spwd *sp;
	uid_t ruid;
	gid_t rgid;
	const struct passwd *pw;

	/*
	 * Get the program name so that error messages can use it.
	 */
	Prog = Basename (argv[0]);

	sanitize_env ();
	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	process_root_flag ("-R", argc, argv);

#ifdef WITH_AUDIT
	audit_help_open ();
#endif
	OPENLOG ("chage");

	ruid = getuid ();
	rgid = getgid ();
	amroot = (ruid == 0);
#ifdef WITH_SELINUX
	if (amroot && (is_selinux_enabled () > 0)) {
		amroot = (selinux_check_passwd_access (PASSWD__ROOTOK) == 0);
	}
#endif

	process_flags (argc, argv);

	check_perms ();

	if (!spw_file_present ()) {
		fprintf (stderr,
		         _("%s: the shadow password file is not present\n"),
		         Prog);
		SYSLOG ((LOG_WARN, "can't find the shadow password file"));
		closelog ();
		exit (E_SHADOW_NOTFOUND);
	}

	open_files (lflg);
	/* Drop privileges */
	if (lflg && (   (setregid (rgid, rgid) != 0)
	             || (setreuid (ruid, ruid) != 0))) {
		fprintf (stderr, _("%s: failed to drop privileges (%s)\n"),
		         Prog, strerror (errno));
		fail_exit (E_NOPERM);
	}

	pw = pw_locate (argv[optind]);
	if (NULL == pw) {
		fprintf (stderr, _("%s: user '%s' does not exist in %s\n"),
		         Prog, argv[optind], pw_dbname ());
		closelog ();
		fail_exit (E_NOPERM);
	}

	STRFCPY (user_name, pw->pw_name);
#ifdef WITH_TCB
	if (shadowtcb_set_user (pw->pw_name) == SHADOWTCB_FAILURE) {
		fail_exit (E_NOPERM);
	}
#endif
	user_uid = pw->pw_uid;

	sp = spw_locate (argv[optind]);
	get_defaults (sp);

	/*
	 * Print out the expiration fields if the user has requested the
	 * list option.
	 */
	if (lflg) {
		if (!amroot && (ruid != user_uid)) {
			fprintf (stderr, _("%s: Permission denied.\n"), Prog);
			fail_exit (E_NOPERM);
		}
#ifdef WITH_AUDIT
		audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
		              "display aging info",
		              user_name, (unsigned int) user_uid, 1);
#endif
		list_fields ();
		fail_exit (E_SUCCESS);
	}

	/*
	 * If none of the fields were changed from the command line, let the
	 * user interactively change them.
	 */
	if (!mflg && !Mflg && !dflg && !Wflg && !Iflg && !Eflg) {
		printf (_("Changing the aging information for %s\n"),
		        user_name);
		if (new_fields () == 0) {
			fprintf (stderr, _("%s: error changing fields\n"),
			         Prog);
			fail_exit (E_NOPERM);
		}
#ifdef WITH_AUDIT
		else {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			              "change all aging information",
			              user_name, (unsigned int) user_uid, 1);
		}
#endif
	} else {
#ifdef WITH_AUDIT
		if (Mflg) {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			              "change max age",
			              user_name, (unsigned int) user_uid, 1);
		}
		if (mflg) {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			              "change min age",
			              user_name, (unsigned int) user_uid, 1);
		}
		if (dflg) {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			              "change last change date",
			              user_name, (unsigned int) user_uid, 1);
		}
		if (Wflg) {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			              "change passwd warning",
			              user_name, (unsigned int) user_uid, 1);
		}
		if (Iflg) {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			              "change inactive days",
			              user_name, (unsigned int) user_uid, 1);
		}
		if (Eflg) {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			              "change passwd expiration",
			              user_name, (unsigned int) user_uid, 1);
		}
#endif
	}

	update_age (sp, pw);

	close_files ();

	SYSLOG ((LOG_INFO, "changed password expiry for %s", user_name));

	closelog ();
	exit (E_SUCCESS);
}
Exemple #16
0
int main (int argc, char **argv)
{
	char buf[BUFSIZ];
	char *name;
	char *newpwd;
	char *cp;

#ifdef	SHADOWGRP
	const struct sgrp *sg;
	struct sgrp newsg;
#endif

	const struct group *gr;
	struct group newgr;
	int errors = 0;
	int line = 0;

	Prog = Basename (argv[0]);

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	process_root_flag ("-R", argc, argv);

	process_flags (argc, argv);

	OPENLOG ("chgpasswd");

	check_perms ();

#ifdef SHADOWGRP
	is_shadow_grp = sgr_file_present ();
#endif

	open_files ();

	/*
	 * Read each line, separating the group name from the password. The
	 * group entry for each group will be looked up in the appropriate
	 * file (gshadow or group) and the password changed.
	 */
	while (fgets (buf, (int) sizeof buf, stdin) != (char *) 0) {
		line++;
		cp = strrchr (buf, '\n');
		if (NULL != cp) {
			*cp = '\0';
		} else {
			fprintf (stderr, _("%s: line %d: line too long\n"),
			         Prog, line);
			errors++;
			continue;
		}

		/*
		 * The group's name is the first field. It is separated from
		 * the password with a ":" character which is replaced with a
		 * NUL to give the new password. The new password will then
		 * be encrypted in the normal fashion with a new salt
		 * generated, unless the '-e' is given, in which case it is
		 * assumed to already be encrypted.
		 */

		name = buf;
		cp = strchr (name, ':');
		if (NULL != cp) {
			*cp = '\0';
			cp++;
		} else {
			fprintf (stderr,
			         _("%s: line %d: missing new password\n"),
			         Prog, line);
			errors++;
			continue;
		}
		newpwd = cp;
		if (   (!eflg)
		    && (   (NULL == crypt_method)
		        || (0 != strcmp (crypt_method, "NONE")))) {
			void *arg = NULL;
			const char *salt;
			if (md5flg) {
				crypt_method = "MD5";
			}
#ifdef USE_SHA_CRYPT
			if (sflg) {
				arg = &sha_rounds;
			}
#endif
			salt = crypt_make_salt (crypt_method, arg);
			cp = pw_encrypt (newpwd, salt);
			if (NULL == cp) {
				fprintf (stderr,
				         _("%s: failed to crypt password with salt '%s': %s\n"),
				         Prog, salt, strerror (errno));
				fail_exit (1);
			}
		}

		/*
		 * Get the group file entry for this group. The group must
		 * already exist.
		 */
		gr = gr_locate (name);
		if (NULL == gr) {
			fprintf (stderr,
			         _("%s: line %d: group '%s' does not exist\n"), Prog,
			         line, name);
			errors++;
			continue;
		}
#ifdef SHADOWGRP
		if (is_shadow_grp) {
			/* The gshadow entry should be updated if the
			 * group entry has a password set to 'x'.
			 * But on the other hand, if there is already both
			 * a group and a gshadow password, it's preferable
			 * to update both.
			 */
			sg = sgr_locate (name);

			if (   (NULL == sg)
			    && (strcmp (gr->gr_passwd,
			                SHADOW_PASSWD_STRING) == 0)) {
				static char *empty = NULL;
				/* If the password is set to 'x' in
				 * group, but there are no entries in
				 * gshadow, create one.
				 */
				newsg.sg_name   = name;
				/* newsg.sg_passwd = NULL; will be set later */
				newsg.sg_adm    = &empty;
				newsg.sg_mem    = dup_list (gr->gr_mem);
				sg = &newsg;
			}
		} else {
			sg = NULL;
		}
#endif

		/*
		 * The freshly encrypted new password is merged into the
		 * group's entry.
		 */
#ifdef SHADOWGRP
		if (NULL != sg) {
			newsg = *sg;
			newsg.sg_passwd = cp;
		}
		if (   (NULL == sg)
		    || (strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) != 0))
#endif
		{
			newgr = *gr;
			newgr.gr_passwd = cp;
		}

		/* 
		 * The updated group file entry is then put back and will
		 * be written to the group file later, after all the
		 * other entries have been updated as well.
		 */
#ifdef SHADOWGRP
		if (NULL != sg) {
			if (sgr_update (&newsg) == 0) {
				fprintf (stderr,
				         _("%s: line %d: failed to prepare the new %s entry '%s'\n"),
				         Prog, line, sgr_dbname (), newsg.sg_name);
				errors++;
				continue;
			}
		}
		if (   (NULL == sg)
		    || (strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) != 0))
#endif
		{
			if (gr_update (&newgr) == 0) {
				fprintf (stderr,
				         _("%s: line %d: failed to prepare the new %s entry '%s'\n"),
				         Prog, line, gr_dbname (), newgr.gr_name);
				errors++;
				continue;
			}
		}
	}

	/*
	 * Any detected errors will cause the entire set of changes to be
	 * aborted. Unlocking the group file will cause all of the
	 * changes to be ignored. Otherwise the file is closed, causing the
	 * changes to be written out all at once, and then unlocked
	 * afterwards.
	 */
	if (0 != errors) {
		fprintf (stderr,
		         _("%s: error detected, changes ignored\n"), Prog);
		fail_exit (1);
	}

	close_files ();

	nscd_flush_cache ("group");

	return (0);
}
Exemple #17
0
int do_connect(message *dev_m_in, message *dev_m_out)
{
	int minor, child;
	struct sockaddr_un addr;
	int rc, i, j;

#if DEBUG == 1
	static int call_count = 0;
	printf("(uds) [%d] do_connect() call_count=%d\n", uds_minor(dev_m_in),
								++call_count);
#endif

	minor = uds_minor(dev_m_in);

	/* only connection oriented sockets can connect */
	if (uds_fd_table[minor].type != SOCK_STREAM &&
			uds_fd_table[minor].type != SOCK_SEQPACKET) {
		return EINVAL;
	}

	if (uds_fd_table[minor].peer != -1) {
		/* socket is already connected */
		return EISCONN;
	}

	rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
				(vir_bytes) 0, (vir_bytes) &addr,
				sizeof(struct sockaddr_un));

	if (rc != OK) {
		return EIO;
	}

	rc = check_perms(minor, &addr);
	if (rc != OK) {
		/* permission denied, socket file doesn't exist, etc. */
		return rc;
	}

	/* look for a socket of the same type that is listening on the
	 * address we want to connect to
	 */
	for (i = 0; i < NR_FDS; i++) {

		if (uds_fd_table[minor].type == uds_fd_table[i].type &&
			uds_fd_table[i].listening &&
			uds_fd_table[i].addr.sun_family == AF_UNIX &&
			!strncmp(addr.sun_path, uds_fd_table[i].addr.sun_path,
			UNIX_PATH_MAX)) {

			if ((child = uds_fd_table[i].child) != -1) {

				/* the server is blocked on accept(2) --
				 * perform connection to the child
				 */

				rc = perform_connection(dev_m_in, dev_m_out,
					&addr, minor, child);

				if (rc == OK) {

					uds_fd_table[i].child = -1;

#if DEBUG == 1
		printf("(uds) [%d] {do_connect} revive %d\n", minor, child);
#endif

					/* wake the parent (server) */
					uds_fd_table[child].ready_to_revive =
						1;
					uds_unsuspend(dev_m_in->m_source,
						child);
				}

				return rc;

			} else {

#if DEBUG == 1
				printf("(uds) [%d] adding to %d's backlog\n",
								minor, i);
#endif

				/* tell the server were waiting to be served */

				/* look for a free slot in the backlog */
				rc = -1; /* to trap error */
				for (j = 0; j < uds_fd_table[i].backlog_size;
					j++) {

					if (uds_fd_table[i].backlog[j] == -1) {

						uds_fd_table[i].backlog[j] =
							minor;

						rc = 0;
						break;
					}
				}

				if (rc == -1) {

					/* backlog is full */
					break;
				}

				/* see if the server is blocked on select() */
				if (uds_fd_table[i].selecting == 1) {

					/* if the server wants to know
					 * about data ready to read and
					 * it doesn't know about it
					 * already, then let the server
					 * know we have data for it.
					 */
					if ((uds_fd_table[i].sel_ops_in &
						SEL_RD) &&
						!(uds_fd_table[i].sel_ops_out &
						SEL_RD)) {

						uds_fd_table[i].sel_ops_out |=
							SEL_RD;
						uds_fd_table[i].status_updated
							= 1;

						uds_unsuspend(
						dev_m_in->m_source, i);
					}
				}

				/* we found our server */
				uds_fd_table[minor].peer = i;

				/* set the address */
				memcpy(&(uds_fd_table[minor].addr), &addr,
					sizeof(struct sockaddr_un));

				break;
			}
		}
	}

	if (uds_fd_table[minor].peer == -1) {
		/* could not find another open socket listening on the
		 * specified address with room in the backlog
		 */
		return ECONNREFUSED;
	}

#if DEBUG == 1
	printf("(uds) [%d] {do_connect} suspend\n", minor);
#endif

	/* suspend until the server side completes the connection with accept()
	 */

	uds_fd_table[minor].suspended = UDS_SUSPENDED_CONNECT;

	return SUSPEND;
}
void handle_property_set_fd()
{
    prop_msg msg;
    int s;
    int r;
    int res;
    struct ucred cr;
    struct sockaddr_un addr;
    socklen_t addr_size = sizeof(addr);
    socklen_t cr_size = sizeof(cr);
    char * source_ctx = NULL;

    if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
        return;
    }

    /* Check socket options here */
    if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
        close(s);
        ERROR("Unable to receive socket options\n");
        return;
    }

    r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), 0));
    if(r != sizeof(prop_msg)) {
        ERROR("sys_prop: mis-match msg size received: %d expected: %zu errno: %d\n",
              r, sizeof(prop_msg), errno);
        close(s);
        return;
    }

    switch(msg.cmd) {
    case PROP_MSG_SETPROP:
        msg.name[PROP_NAME_MAX-1] = 0;
        msg.value[PROP_VALUE_MAX-1] = 0;

        if (!is_legal_property_name(msg.name, strlen(msg.name))) {
            ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name);
            close(s);
            return;
        }

        getpeercon(s, &source_ctx);

        if(memcmp(msg.name,"ctl.",4) == 0) {
            // Keep the old close-socket-early behavior when handling
            // ctl.* properties.
            close(s);
            if (check_control_perms(msg.value, cr.uid, cr.gid, source_ctx)) {
                handle_control_message((char*) msg.name + 4, (char*) msg.value);
            } else {
                ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",
                        msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);
            }
        } else {
            if (check_perms(msg.name, cr.uid, cr.gid, source_ctx)) {
                property_set((char*) msg.name, (char*) msg.value);
            } else {
                ERROR("sys_prop: permission denied uid:%d  name:%s\n",
                      cr.uid, msg.name);
            }

            // Note: bionic's property client code assumes that the
            // property server will not close the socket until *AFTER*
            // the property is written to memory.
            close(s);
        }
        freecon(source_ctx);
        break;

    default:
        close(s);
        break;
    }
}
Exemple #19
0
/*
 * Note, an intention with return values is so that this is compatible with
 * ipa-getkeytab. This is so based on the return value you can distinguish
 * between errors common between the two (no kerbeors ccache) and those
 * unique (host already added).
 */
int
main(int argc, const char **argv) {
    static const char *hostname = NULL;
    static const char *server = NULL;
    static const char *keytab = NULL;
    static const char *bindpw = NULL;
    static const char *basedn = NULL;
    int quiet = 0;
    int unenroll = 0;
    int force = 0;
    struct poptOption options[] = {
        { "debug", 'd', POPT_ARG_NONE, &debug, 0,
          _("Print the raw XML-RPC output in GSSAPI mode"), NULL },
        { "quiet", 'q', POPT_ARG_NONE, &quiet, 0,
          _("Quiet mode. Only errors are displayed."), NULL },
        { "unenroll", 'u', POPT_ARG_NONE, &unenroll, 0,
          _("Unenroll this host from IPA server"), NULL },
        { "hostname", 'h', POPT_ARG_STRING, &hostname, 0,
          _("Hostname of this server"), _("hostname") },
        { "server", 's', POPT_ARG_STRING, &server, 0,
          _("IPA Server to use"), _("hostname") },
        { "keytab", 'k', POPT_ARG_STRING, &keytab, 0,
          _("Specifies where to store keytab information."), _("filename") },
        { "force", 'f', POPT_ARG_NONE, &force, 0,
          _("Force the host join. Rejoin even if already joined."), NULL },
        { "bindpw", 'w', POPT_ARG_STRING, &bindpw, 0,
          _("LDAP password (if not using Kerberos)"), _("password") },
        { "basedn", 'b', POPT_ARG_STRING, &basedn, 0,
          _("LDAP basedn"), _("basedn") },
        POPT_AUTOHELP
        POPT_TABLEEND
    };
    poptContext pc;
    int ret;

    ret = init_gettext();
    if (ret) {
        exit(2);
    }

    pc = poptGetContext("ipa-join", argc, (const char **)argv, options, 0);
    ret = poptGetNextOpt(pc);
    if (ret != -1) {
        if (!quiet) {
            poptPrintUsage(pc, stderr, 0);
        }
        exit(2);
    }
    poptFreeContext(pc);
    if (debug)
        setenv("XMLRPC_TRACE_XML", "1", 1);


    if (!keytab)
        keytab = "/etc/krb5.keytab";

    if (unenroll) {
        ret = unenroll_host(server, hostname, keytab, quiet);
    } else {
        ret = check_perms(keytab);
        if (ret == 0)
            ret = join(server, hostname, bindpw, basedn, keytab, force, quiet);
    }

    exit(ret);
}