示例#1
0
int		what_to_print(const char *format, va_list *arg)
{
	char					*text;
	int						size;
	t_mod					data;
	char					*choped;
	unsigned long int		i;
	
	text = NULL;
	init_var(&i, &size);
	while (++i < ft_strlen(format))
	{
		if (format[i] == '%')
		{
			choped = ft_strdup(chop_format(format, &i));
			process_flags(choped, &data);
			start_engine(text, &size, &data, arg);
			i = i + ft_strlen(choped);
		}
		else
		{
			ft_putchar(format[i]);
			size++;
		}
	}
	return (size);
}
示例#2
0
/*
 * grpck - verify group file integrity
 */
int main (int argc, char **argv)
{
	int errors = 0;
	bool changed = false;

	/*
	 * 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);

	OPENLOG ("grpck");

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

	open_files ();

	if (sort_mode) {
		gr_sort ();
#ifdef	SHADOWGRP
		if (is_shadow) {
			sgr_sort ();
		}
		changed = true;
#endif
	} else {
		check_grp_file (&errors, &changed);
#ifdef	SHADOWGRP
		if (is_shadow) {
			check_sgr_file (&errors, &changed);
		}
#endif
	}

	/* Commit the change in the database if needed */
	close_files (changed);

	nscd_flush_cache ("group");

	/*
	 * Tell the user what we did and exit.
	 */
	if (0 != errors) {
		if (changed) {
			printf (_("%s: the files have been updated\n"), Prog);
		} else {
			printf (_("%s: no changes\n"), Prog);
		}
	}

	return ((0 != errors) ? E_BAD_ENTRY : E_OKAY);
}
示例#3
0
文件: print_arg.c 项目: LeGuit/libft
int					print_arg(t_mod *m, va_list ap)
{
	int				cnt;

	process_flags(m);
	process_modifier(m);
	cnt = g_convtab[(int)m->convers](m, ap);
	return (cnt);
}
示例#4
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;
}
示例#5
0
bool create_sphere(MeshInstance& mesh_instance, const Context& context, int subdivision, uint32_t flags)
{
    std::vector<DebugLayout::Vertex> vertices;
    std::vector<uint32_t> indices;

    vertices.reserve(8 * 3 * (1 << (2 * subdivision)));
    indices.reserve(8 * 3 * (1 << (2 * subdivision)));

    vec3 l(-1, 0, 0);
    vec3 r(1, 0, 0);
    vec3 b(0, 0, -1);
    vec3 f(0, 0, 1);
    vec3 d(0, -1, 0);
    vec3 u(0, 1, 0);

    subdivide(vertices, indices, b, l, u, subdivision);
    subdivide(vertices, indices, r, b, u, subdivision);
    subdivide(vertices, indices, f, r, u, subdivision);
    subdivide(vertices, indices, l, f, u, subdivision);
    subdivide(vertices, indices, l, b, d, subdivision);
    subdivide(vertices, indices, b, r, d, subdivision);
    subdivide(vertices, indices, r, f, d, subdivision);
    subdivide(vertices, indices, f, l, d, subdivision);

    caculate_normals(&vertices[0], &indices[0], indices.size());

    mesh_instance.mesh.aabb.extents.set(1.0f, 1.0f, 1.0f);

    process_flags(mesh_instance, context, vertices, vertices.size(), indices, indices.size(), flags);

    MeshPart& part = mesh_instance.mesh.parts[0];

    part.render_data.vbuffer = context.vertex_buffer_pool.create();
    part.render_data.ibuffer = context.index_buffer_pool.create();
    part.render_data.layout = DebugLayout::handle;
    part.render_data.elements_number = indices.size() / 3;
    part.render_data.indexes_number = indices.size();

    mesh_instance.mesh.ibuffer = part.render_data.ibuffer;
    mesh_instance.mesh.vbuffer = part.render_data.vbuffer;

    VertexBuffer& vbuffer = context.vertex_buffer_pool.get(part.render_data.vbuffer);
    if (!vbuffer.init(buffer_update_type_static,
                      reinterpret_cast<const uint8_t*>(&vertices[0]), vertices.size() * sizeof(DebugLayout::Vertex), sizeof(DebugLayout::Vertex)))
        return false;
    IndexBuffer& ibuffer = context.index_buffer_pool.get(part.render_data.ibuffer);
    return ibuffer.init(vbuffer, &indices[0], indices.size());
}
示例#6
0
bool create_cube(MeshInstance& mesh_instance, const Context& context, uint32_t flags)
{
    StandartGeometryLayout::Vertex vertices[8];
    vertices[0].pos.set(-0.5f, -0.5f, -0.5f);
    vertices[1].pos.set(-0.5f, 0.5f, -0.5f);
    vertices[2].pos.set(0.5f, 0.5f, -0.5f);
    vertices[3].pos.set(0.5f, -0.5f, -0.5f);
    vertices[4].pos.set(-0.5f, -0.5f, 0.5f);
    vertices[5].pos.set(-0.5f, 0.5f, 0.5f);
    vertices[6].pos.set(0.5f, 0.5f, 0.5f);
    vertices[7].pos.set(0.5f, -0.5f, 0.5f);

    array<uint32_t, 36> indices;
    uint32_t i[36] = {0, 1, 2, 0, 2, 3,
        7, 2, 6, 7, 3, 2,
        4, 7, 6, 4, 6, 5,
        4, 1, 5, 4, 0, 1,
        2, 5, 6, 2, 1, 5,
        3, 7, 4, 3, 4, 0};
    memcpy(&indices[0], i, sizeof(i));

    Mesh& mesh = mesh_instance.mesh;

    mesh.aabb.center = vec3(0.5f, 0.5f, 0.5f);
    mesh.aabb.extents = vec3(0.5f, 0.5f, 0.5f);

    process_flags(mesh_instance, context, vertices, 8, indices, 36, flags);

    mesh.parts[0].render_data.vbuffer = context.vertex_buffer_pool.create();
    mesh.parts[0].render_data.ibuffer = context.index_buffer_pool.create();

    mesh.parts[0].render_data.elements_number = 12;

    VertexBuffer& vbuffer = context.vertex_buffer_pool.get(mesh.parts[0].render_data.vbuffer);
    if (!vbuffer.init(buffer_update_type_static,
        reinterpret_cast<const uint8_t*>(&vertices[0]), 8 * sizeof(StandartGeometryLayout::Vertex), sizeof(StandartGeometryLayout::Vertex)))
        return false;
    IndexBuffer& ibuffer = context.index_buffer_pool.get(mesh.parts[0].render_data.ibuffer);
    return ibuffer.init(vbuffer, &indices[0], indices.size());
}
示例#7
0
bool create_plane(MeshInstance& mesh_instance, const Context& context, uint32_t flags)
{
    StandartGeometryLayout::Vertex vertexes[4];
    vertexes[0].pos.set(-0.5f, -0.5f, 0.0);
    vertexes[1].pos.set(-0.5f, 0.5f, 0.0);
    vertexes[2].pos.set(0.5f, 0.5f, 0.0);
    vertexes[3].pos.set(0.5f, -0.5f, 0.0);

    vertexes[0].nrm.set(0.0f, 0.0f, 1.0f);
    vertexes[1].nrm.set(0.0f, 0.0f, 1.0f);
    vertexes[2].nrm.set(0.0f, 0.0f, 1.0f);
    vertexes[3].nrm.set(0.0f, 0.0f, 1.0f);

    vertexes[0].tex.set(0.0f, 0.0f);
    vertexes[1].tex.set(0.0f, 1.0f);
    vertexes[2].tex.set(1.0f, 1.0f);
    vertexes[3].tex.set(1.0f, 0.0f);

    uint32_t indexes[6] = {0, 2, 1, 0, 3, 2};

    mesh_instance.mesh.aabb.extents.set(0.5f, 0.5f, 0.01f);

    process_flags(mesh_instance, context, vertexes, 4, indexes, 6, flags);

    Mesh& mesh = mesh_instance.mesh;

    mesh.parts[0].render_data.vbuffer = context.vertex_buffer_pool.create();
    mesh.parts[0].render_data.ibuffer = context.index_buffer_pool.create();

    mesh.parts[0].render_data.elements_number = 2;

    VertexBuffer& vbuffer = context.vertex_buffer_pool.get(mesh.parts[0].render_data.vbuffer);
    if (!vbuffer.init(buffer_update_type_static,
                      reinterpret_cast<const uint8_t*>(&vertexes[0]), 4 * sizeof(StandartGeometryLayout::Vertex), sizeof(StandartGeometryLayout::Vertex)))
        return false;
    IndexBuffer& ibuffer = context.index_buffer_pool.get(mesh.parts[0].render_data.ibuffer);
    return ibuffer.init(vbuffer, indexes, 6);
}
示例#8
0
int main(int argc, char** argv) {

    test_env("LD_PRELOAD");
    test_env("DYLD_INSERT_LIBRARIES");

    if (!process_flags(argc, argv)) {
        usage(argv[0]);
        return 1;
    }

    if (initial_sleep > 0) {
        printf("Sleeping %d sec...\n", initial_sleep);
        sleep(initial_sleep);
        printf("Awoke\n");
    }
    
    if (test_sync) {
        test_sync_init();
    }

    int i;
    for (i = 0; i < cycles; i++) {
        if (i > 0 && step_sleep > 0) {
            printf("\tsleeping %d sec...\n", step_sleep);
            sleep(4);
        }
        printf("cycle %d\n", i);
        test(i);
    }

    if (test_sync) {
        test_wait_shutdown();
    }

    return 0;
}
示例#9
0
int main (int argc, char **argv)
{
	const struct passwd *pw;
	struct passwd pwent;
	const struct spwd *sp;
	struct spwd spent;

	Prog = Basename (argv[0]);

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

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

	OPENLOG ("pwconv");

	process_flags (argc, argv);

#ifdef WITH_TCB
	if (getdef_bool("USE_TCB")) {
		fprintf (stderr, _("%s: can't work with tcb enabled\n"), Prog);
		exit (E_FAILURE);
	}
#endif				/* WITH_TCB */

	if (pw_lock () == 0) {
		fprintf (stderr,
		         _("%s: cannot lock %s; try again later.\n"),
		         Prog, pw_dbname ());
		fail_exit (E_PWDBUSY);
	}
	pw_locked = true;
	if (pw_open (O_RDWR) == 0) {
		fprintf (stderr,
		         _("%s: cannot open %s\n"), Prog, pw_dbname ());
		fail_exit (E_MISSING);
	}

	if (spw_lock () == 0) {
		fprintf (stderr,
		         _("%s: cannot lock %s; try again later.\n"),
		         Prog, spw_dbname ());
		fail_exit (E_PWDBUSY);
	}
	spw_locked = true;
	if (spw_open (O_CREAT | O_RDWR) == 0) {
		fprintf (stderr,
		         _("%s: cannot open %s\n"), Prog, spw_dbname ());
		fail_exit (E_FAILURE);
	}

	/*
	 * Remove /etc/shadow entries for users not in /etc/passwd.
	 */
	(void) spw_rewind ();
	while ((sp = spw_next ()) != NULL) {
		if (pw_locate (sp->sp_namp) != NULL) {
			continue;
		}

		if (spw_remove (sp->sp_namp) == 0) {
			/*
			 * This shouldn't happen (the entry exists) but...
			 */
			fprintf (stderr,
			         _("%s: cannot remove entry '%s' from %s\n"),
			         Prog, sp->sp_namp, spw_dbname ());
			fail_exit (E_FAILURE);
		}
	}

	/*
	 * Update shadow entries which don't have "x" as pw_passwd. Add any
	 * missing shadow entries.
	 */
	(void) pw_rewind ();
	while ((pw = pw_next ()) != NULL) {
		sp = spw_locate (pw->pw_name);
		if (NULL != sp) {
			/* do we need to update this entry? */
			if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) {
				continue;
			}
			/* update existing shadow entry */
			spent = *sp;
		} else {
			/* add new shadow entry */
			memset (&spent, 0, sizeof spent);
			spent.sp_namp   = pw->pw_name;
			spent.sp_min    = getdef_num ("PASS_MIN_DAYS", -1);
			spent.sp_max    = getdef_num ("PASS_MAX_DAYS", -1);
			spent.sp_warn   = getdef_num ("PASS_WARN_AGE", -1);
			spent.sp_inact  = -1;
			spent.sp_expire = -1;
			spent.sp_flag   = SHADOW_SP_FLAG_UNSET;
		}
		spent.sp_pwdp = pw->pw_passwd;
		spent.sp_lstchg = (long) time ((time_t *) 0) / SCALE;
		if (0 == spent.sp_lstchg) {
			/* Better disable aging than requiring a password
			 * change */
			spent.sp_lstchg = -1;
		}
		if (spw_update (&spent) == 0) {
			fprintf (stderr,
			         _("%s: failed to prepare the new %s entry '%s'\n"),
			         Prog, spw_dbname (), spent.sp_namp);
			fail_exit (E_FAILURE);
		}

		/* remove password from /etc/passwd */
		pwent = *pw;
		pwent.pw_passwd = SHADOW_PASSWD_STRING;	/* XXX warning: const */
		if (pw_update (&pwent) == 0) {
			fprintf (stderr,
			         _("%s: failed to prepare the new %s entry '%s'\n"),
			         Prog, pw_dbname (), pwent.pw_name);
			fail_exit (E_FAILURE);
		}
	}

	if (spw_close () == 0) {
		fprintf (stderr,
		         _("%s: failure while writing changes to %s\n"),
		         Prog, spw_dbname ());
		SYSLOG ((LOG_ERR, "failure while writing changes to %s", spw_dbname ()));
		fail_exit (E_FAILURE);
	}
	if (pw_close () == 0) {
		fprintf (stderr,
		         _("%s: failure while writing changes to %s\n"),
		         Prog, pw_dbname ());
		SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
		fail_exit (E_FAILURE);
	}

	/* /etc/passwd- (backup file) */
	if (chmod (PASSWD_FILE "-", 0600) != 0) {
		fprintf (stderr,
		         _("%s: failed to change the mode of %s to 0600\n"),
		         Prog, PASSWD_FILE "-");
		SYSLOG ((LOG_ERR, "failed to change the mode of %s to 0600", PASSWD_FILE "-"));
		/* continue */
	}

	if (pw_unlock () == 0) {
		fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
		SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
		/* continue */
	}

	if (spw_unlock () == 0) {
		fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
		SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
		/* continue */
	}

	nscd_flush_cache ("passwd");

	return E_SUCCESS;
}
示例#10
0
文件: chgpasswd.c 项目: bfeeny/shadow
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);
}
示例#11
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);
}
示例#12
0
文件: newusers.c 项目: brauner/shadow
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);
}
示例#13
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);
}
示例#14
0
文件: grpconv.c 项目: bfeeny/shadow
int main (int argc, char **argv)
{
	const struct group *gr;
	struct group grent;
	const struct sgrp *sg;
	struct sgrp sgent;

	Prog = Basename (argv[0]);

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

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

	OPENLOG ("grpconv");

	process_flags (argc, argv);

	if (gr_lock () == 0) {
		fprintf (stderr,
		         _("%s: cannot lock %s; try again later.\n"),
		         Prog, gr_dbname ());
		fail_exit (5);
	}
	gr_locked = true;
	if (gr_open (O_CREAT | O_RDWR) == 0) {
		fprintf (stderr, _("%s: cannot open %s\n"), Prog, gr_dbname ());
		fail_exit (1);
	}

	if (sgr_lock () == 0) {
		fprintf (stderr,
		         _("%s: cannot lock %s; try again later.\n"),
		         Prog, sgr_dbname ());
		fail_exit (5);
	}
	sgr_locked = true;
	if (sgr_open (O_CREAT | O_RDWR) == 0) {
		fprintf (stderr, _("%s: cannot open %s\n"), Prog, sgr_dbname ());
		fail_exit (1);
	}

	/*
	 * Remove /etc/gshadow entries for groups not in /etc/group.
	 */
	(void) sgr_rewind ();
	while ((sg = sgr_next ()) != NULL) {
		if (gr_locate (sg->sg_name) != NULL) {
			continue;
		}

		if (sgr_remove (sg->sg_name) == 0) {
			/*
			 * This shouldn't happen (the entry exists) but...
			 */
			fprintf (stderr,
			         _("%s: cannot remove entry '%s' from %s\n"),
			         Prog, sg->sg_name, sgr_dbname ());
			fail_exit (3);
		}
	}

	/*
	 * Update shadow group passwords if non-shadow password is not "x".
	 * Add any missing shadow group entries.
	 */
	(void) gr_rewind ();
	while ((gr = gr_next ()) != NULL) {
		sg = sgr_locate (gr->gr_name);
		if (NULL != sg) {
			/* update existing shadow group entry */
			sgent = *sg;
			if (strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) != 0)
				sgent.sg_passwd = gr->gr_passwd;
		} else {
			static char *empty = 0;

			/* add new shadow group entry */
			memset (&sgent, 0, sizeof sgent);
			sgent.sg_name = gr->gr_name;
			sgent.sg_passwd = gr->gr_passwd;
			sgent.sg_adm = &empty;
		}
		/*
		 * XXX - sg_mem is redundant, it is currently always a copy
		 * of gr_mem. Very few programs actually use sg_mem, and all
		 * of them are in the shadow suite. Maybe this field could
		 * be used for something else? Any suggestions?
		 */
		sgent.sg_mem = gr->gr_mem;

		if (sgr_update (&sgent) == 0) {
			fprintf (stderr,
			         _("%s: failed to prepare the new %s entry '%s'\n"),
			         Prog, sgr_dbname (), sgent.sg_name);
			fail_exit (3);
		}
		/* remove password from /etc/group */
		grent = *gr;
		grent.gr_passwd = SHADOW_PASSWD_STRING;	/* XXX warning: const */
		if (gr_update (&grent) == 0) {
			fprintf (stderr,
			         _("%s: failed to prepare the new %s entry '%s'\n"),
			         Prog, gr_dbname (), grent.gr_name);
			fail_exit (3);
		}
	}

	if (sgr_close () == 0) {
		fprintf (stderr,
		         _("%s: failure while writing changes to %s\n"),
		         Prog, sgr_dbname ());
		SYSLOG ((LOG_ERR, "failure while writing changes to %s", sgr_dbname ()));
		fail_exit (3);
	}
	if (gr_close () == 0) {
		fprintf (stderr,
		         _("%s: failure while writing changes to %s\n"),
		         Prog, gr_dbname ());
		SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
		fail_exit (3);
	}
	if (sgr_unlock () == 0) {
		fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
		SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
		/* continue */
	}
	if (gr_unlock () == 0) {
		fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
		SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
		/* continue */
	}

	nscd_flush_cache ("group");

	return 0;
}
示例#15
0
void
dissect_sss_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, ncp_req_hash_value *request_value)
{
    guint8              /*func,*/ subfunc = 0;
    guint32             subverb=0;
    guint32             msg_length=0;
    guint32             foffset= 0;
    proto_tree          *atree;
    proto_item          *aitem;


    if (tvb_length_remaining(tvb, foffset)<4) {
        return;
    }
    foffset = 6;
    /*func = tvb_get_guint8(tvb, foffset);*/
    foffset += 1;
    subfunc = tvb_get_guint8(tvb, foffset);
    foffset += 1;

    /* Fill in the PROTOCOL & INFO  columns. */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "NSSS");
    col_add_fstr(pinfo->cinfo, COL_INFO, "C SecretStore - %s", val_to_str(subfunc, sss_func_enum, "Unknown (%d)"));

    switch (subfunc) {
    case 1:
        aitem = proto_tree_add_text(ncp_tree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Packet Type: %s", val_to_str(subfunc, sss_func_enum, "Unknown (%d)"));
        atree = proto_item_add_subtree(aitem, ett_sss);
        proto_tree_add_item(atree, hf_ping_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        foffset += 4;
        proto_tree_add_item(atree, hf_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        /*foffset += 4;*/
        break;
    case 2:
        proto_tree_add_item(ncp_tree, hf_frag_handle, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        if (tvb_get_letohl(tvb, foffset)==0xffffffff) { /* Fragment handle of -1 means no fragment. So process packet */
            foffset += 4;
            proto_tree_add_item(ncp_tree, hf_buffer_size, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
            foffset += 4;
            proto_tree_add_item(ncp_tree, hf_length, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
            foffset += 4;
            foffset += 12; /* Blank Context */
            subverb = tvb_get_letohl(tvb, foffset);
            col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str(subverb, sss_verb_enum, "Unknown (%d)"));

            aitem = proto_tree_add_item(ncp_tree, hf_verb, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
            atree = proto_item_add_subtree(aitem, ett_sss);
            if (request_value) {
                request_value->req_nds_flags=subverb;
            }
            foffset += 4;
            process_flags(atree, tvb, foffset);
            foffset += 4;
            proto_tree_add_item(atree, hf_context, tvb, foffset, 4, ENC_BIG_ENDIAN);
            foffset += 4;
            switch (subverb) {
            case 0:
                foffset += 4;
                /*foffset =*/ sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
                break;
            case 1:
                foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
                msg_length = tvb_get_letohl(tvb, foffset);
                foffset += (msg_length+4);   /* Unsure of what this length and parameter are */
                /* A bad secret of length greater then 256 characters will cause frag
                   packets and then we will see these as malformed packets.
                   So check to make sure we still have data in the packet anytime
                   we read a secret. */
                if (tvb_length_remaining(tvb, foffset) > 4) {
                    /*foffset =*/ sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
                }
                break;
            case 2:
                foffset += 4;
                foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
                if (tvb_length_remaining(tvb, foffset) > 4) {
                    msg_length = tvb_get_letohl(tvb, foffset);
                    foffset += 4;
                    if (tvb_length_remaining(tvb, foffset) < (gint) msg_length) {
                        proto_tree_add_item(atree, hf_enc_data, tvb, foffset, -1, ENC_NA);
                    } else {
                        proto_tree_add_item(atree, hf_enc_data, tvb, foffset, msg_length, ENC_NA);
                    }
                }
                break;
            case 3:
            case 4:
                foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
                if (tvb_length_remaining(tvb, foffset) > 4) {
                    /*foffset =*/ sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
                }
                break;
            case 5:
                break;
            case 6:
                foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
                if (tvb_length_remaining(tvb, foffset) > 4) {
                    /*foffset =*/ sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
                }
                break;
            case 7:
                msg_length = tvb_get_letohl(tvb, foffset);
                foffset += 4;
                proto_tree_add_item(atree, hf_enc_cred, tvb, foffset, msg_length, ENC_NA);
                break;
            case 8:
            case 9:
            default:
                break;
            }
        } else {
            col_set_str(pinfo->cinfo, COL_INFO, "C SecretStore - fragment");
            proto_tree_add_text(ncp_tree, tvb, foffset, 4, "Fragment");

            /* Fragments don't really carry a subverb so store 0xff as the subverb number */
            if (request_value) {
                request_value->req_nds_flags=255;
            }
            if (tvb_length_remaining(tvb, foffset) > 8) {
                foffset += 4;
                proto_tree_add_item(ncp_tree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), ENC_NA);
            }
        }
        break;
    case 3:
        /* No Op */
        break;
    default:
        break;
    }
}
示例#16
0
int
main(int argc, char * argv[])
{
    int64_t skip = 0;
    int64_t seek = 0;
    int ibs = 0;
    int obs = 0;
    int bpt = DEF_BLOCKS_PER_TRANSFER;
    int bpt_given = 0;
    char str[STR_SZ];
    char * key;
    char * buf;
    char inf[INOUTF_SZ];
    int in_type = FT_OTHER;
    char outf[INOUTF_SZ];
    int out_type = FT_OTHER;
    int res, k, t;
    int infd, outfd, blocks;
    unsigned char * wrkPos;
    unsigned char * wrkBuff = NULL;
    unsigned char * wrkMmap = NULL;
    int64_t in_num_sect = -1;
    int in_res_sz = 0;
    int64_t out_num_sect = -1;
    int out_res_sz = 0;
    int scsi_cdbsz_in = DEF_SCSI_CDBSZ;
    int scsi_cdbsz_out = DEF_SCSI_CDBSZ;
    int cdbsz_given = 0;
    int do_coe = 0;     /* dummy, just accept + ignore */
    int do_sync = 0;
    int num_dio_not_done = 0;
    int in_sect_sz, out_sect_sz;
    int n, flags;
    char ebuff[EBUFF_SZ];
    char b[80];
    int blocks_per;
    size_t psz;
    struct flags_t in_flags;
    struct flags_t out_flags;
    int ret = 0;

#if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
    psz = sysconf(_SC_PAGESIZE); /* POSIX.1 (was getpagesize()) */
#else
    psz = 4096;     /* give up, pick likely figure */
#endif
    inf[0] = '\0';
    outf[0] = '\0';
    memset(&in_flags, 0, sizeof(in_flags));
    memset(&out_flags, 0, sizeof(out_flags));

    for (k = 1; k < argc; k++) {
        if (argv[k])
            strncpy(str, argv[k], STR_SZ);
        else
            continue;
        for (key = str, buf = key; *buf && *buf != '=';)
            buf++;
        if (*buf)
            *buf++ = '\0';
        if (0 == strcmp(key,"bpt")) {
            bpt = sg_get_num(buf);
            if (-1 == bpt) {
                pr2serr(ME "bad argument to 'bpt'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
            bpt_given = 1;
        } else if (0 == strcmp(key,"bs")) {
            blk_sz = sg_get_num(buf);
            if (-1 == blk_sz) {
                pr2serr(ME "bad argument to 'bs'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strcmp(key,"cdbsz")) {
            scsi_cdbsz_in = sg_get_num(buf);
            scsi_cdbsz_out = scsi_cdbsz_in;
            cdbsz_given = 1;
        } else if (0 == strcmp(key,"coe")) {
            do_coe = sg_get_num(buf);   /* dummy, just accept + ignore */
            if (do_coe) {
                ;    /* unused, dummy to suppress warning */
            }
        } else if (0 == strcmp(key,"count")) {
            if (0 != strcmp("-1", buf)) {
                dd_count = sg_get_llnum(buf);
                if (-1LL == dd_count) {
                    pr2serr(ME "bad argument to 'count'\n");
                    return SG_LIB_SYNTAX_ERROR;
                }
            }   /* treat 'count=-1' as calculate count (same as not given) */
        } else if (0 == strcmp(key,"dio"))
            out_flags.dio = sg_get_num(buf);
        else if (0 == strcmp(key,"fua")) {
            n = sg_get_num(buf);
            if (n & 1)
                out_flags.fua = 1;
            if (n & 2)
                in_flags.fua = 1;
        } else if (0 == strcmp(key,"ibs")) {
            ibs = sg_get_num(buf);
            if (-1 == ibs) {
                pr2serr(ME "bad argument to 'ibs'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (strcmp(key,"if") == 0) {
            if ('\0' != inf[0]) {
                pr2serr("Second 'if=' argument??\n");
                return SG_LIB_SYNTAX_ERROR;
            } else
                strncpy(inf, buf, INOUTF_SZ);
        } else if (0 == strcmp(key, "iflag")) {
            if (process_flags(buf, &in_flags)) {
                pr2serr(ME "bad argument to 'iflag'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (strcmp(key,"of") == 0) {
            if ('\0' != outf[0]) {
                pr2serr("Second 'of=' argument??\n");
                return SG_LIB_SYNTAX_ERROR;
            } else
                strncpy(outf, buf, INOUTF_SZ);
        } else if (0 == strcmp(key, "oflag")) {
            if (process_flags(buf, &out_flags)) {
                pr2serr(ME "bad argument to 'oflag'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strcmp(key,"obs")) {
            obs = sg_get_num(buf);
            if (-1 == obs) {
                pr2serr(ME "bad argument to 'obs'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strcmp(key,"seek")) {
            seek = sg_get_llnum(buf);
            if (-1LL == seek) {
                pr2serr(ME "bad argument to 'seek'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strcmp(key,"skip")) {
            skip = sg_get_llnum(buf);
            if (-1LL == skip) {
                pr2serr(ME "bad argument to 'skip'\n");
                return SG_LIB_SYNTAX_ERROR;
            }
        } else if (0 == strcmp(key,"sync"))
            do_sync = sg_get_num(buf);
        else if (0 == strcmp(key,"time"))
            do_time = sg_get_num(buf);
        else if (0 == strncmp(key, "verb", 4))
            verbose = sg_get_num(buf);
        else if ((0 == strncmp(key, "--help", 7)) ||
                 (0 == strcmp(key, "-h")) || (0 == strcmp(key, "-?"))) {
            usage();
            return 0;
        } else if ((0 == strncmp(key, "--vers", 6)) ||
                   (0 == strcmp(key, "-V"))) {
            pr2serr(ME ": %s\n", version_str);
            return 0;
        }
        else {
            pr2serr("Unrecognized option '%s'\n", key);
            pr2serr("For more information use '--help'\n");
            return SG_LIB_SYNTAX_ERROR;
        }
    }
    if (blk_sz <= 0) {
        blk_sz = DEF_BLOCK_SIZE;
        pr2serr("Assume default 'bs' (block size) of %d bytes\n", blk_sz);
    }
    if ((ibs && (ibs != blk_sz)) || (obs && (obs != blk_sz))) {
        pr2serr("If 'ibs' or 'obs' given must be same as 'bs'\n");
        usage();
        return SG_LIB_SYNTAX_ERROR;
    }
    if ((skip < 0) || (seek < 0)) {
        pr2serr("skip and seek cannot be negative\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    if ((out_flags.append > 0) && (seek > 0)) {
        pr2serr("Can't use both append and seek switches\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    if (bpt < 1) {
        pr2serr("bpt must be greater than 0\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    /* defaulting transfer size to 128*2048 for CD/DVDs is too large
       for the block layer in lk 2.6 and results in an EIO on the
       SG_IO ioctl. So reduce it in that case. */
    if ((blk_sz >= 2048) && (0 == bpt_given))
        bpt = DEF_BLOCKS_PER_2048TRANSFER;

#ifdef SG_DEBUG
    pr2serr(ME "if=%s skip=%" PRId64 " of=%s seek=%" PRId64 " count=%" PRId64
            "\n", inf, skip, outf, seek, dd_count);
#endif
    install_handler (SIGINT, interrupt_handler);
    install_handler (SIGQUIT, interrupt_handler);
    install_handler (SIGPIPE, interrupt_handler);
    install_handler (SIGUSR1, siginfo_handler);

    infd = STDIN_FILENO;
    outfd = STDOUT_FILENO;
    if (inf[0] && ('-' != inf[0])) {
        in_type = dd_filetype(inf);
        if (verbose)
            pr2serr(" >> Input file type: %s\n",
                    dd_filetype_str(in_type, ebuff));

        if (FT_ERROR == in_type) {
            pr2serr(ME "unable to access %s\n", inf);
            return SG_LIB_FILE_ERROR;
        } else if (FT_ST == in_type) {
            pr2serr(ME "unable to use scsi tape device %s\n", inf);
            return SG_LIB_FILE_ERROR;
        } else if (FT_SG == in_type) {
            flags = O_RDWR | O_NONBLOCK;
            if (in_flags.direct)
                flags |= O_DIRECT;
            if (in_flags.excl)
                flags |= O_EXCL;
            if (in_flags.dsync)
                flags |= O_SYNC;
            if ((infd = open(inf, flags)) < 0) {
                snprintf(ebuff, EBUFF_SZ,
                         ME "could not open %s for sg reading", inf);
                perror(ebuff);
                return SG_LIB_FILE_ERROR;
            }
            res = ioctl(infd, SG_GET_VERSION_NUM, &t);
            if ((res < 0) || (t < 30122)) {
                pr2serr(ME "sg driver prior to 3.1.22\n");
                return SG_LIB_FILE_ERROR;
            }
            in_res_sz = blk_sz * bpt;
            if (0 != (in_res_sz % psz)) /* round up to next page */
                in_res_sz = ((in_res_sz / psz) + 1) * psz;
            if (ioctl(infd, SG_GET_RESERVED_SIZE, &t) < 0) {
                perror(ME "SG_GET_RESERVED_SIZE error");
                return SG_LIB_FILE_ERROR;
            }
            if (t < MIN_RESERVED_SIZE)
                t = MIN_RESERVED_SIZE;
            if (in_res_sz > t) {
                if (ioctl(infd, SG_SET_RESERVED_SIZE, &in_res_sz) < 0) {
                    perror(ME "SG_SET_RESERVED_SIZE error");
                    return SG_LIB_FILE_ERROR;
                }
            }
            wrkMmap = (unsigned char *)mmap(NULL, in_res_sz,
                                            PROT_READ | PROT_WRITE, MAP_SHARED, infd, 0);
            if (MAP_FAILED == wrkMmap) {
                snprintf(ebuff, EBUFF_SZ,
                         ME "error using mmap() on file: %s", inf);
                perror(ebuff);
                return SG_LIB_FILE_ERROR;
            }
        } else {
            flags = O_RDONLY;
            if (in_flags.direct)
                flags |= O_DIRECT;
            if (in_flags.excl)
                flags |= O_EXCL;
            if (in_flags.dsync)
                flags |= O_SYNC;
            if ((infd = open(inf, flags)) < 0) {
                snprintf(ebuff, EBUFF_SZ,
                         ME "could not open %s for reading", inf);
                perror(ebuff);
                return SG_LIB_FILE_ERROR;
            }
            else if (skip > 0) {
                off64_t offset = skip;

                offset *= blk_sz;       /* could exceed 32 bits here! */
                if (lseek64(infd, offset, SEEK_SET) < 0) {
                    snprintf(ebuff, EBUFF_SZ, ME "couldn't skip to "
                             "required position on %s", inf);
                    perror(ebuff);
                    return SG_LIB_FILE_ERROR;
                }
                if (verbose)
                    pr2serr("  >> skip: lseek64 SEEK_SET, byte offset=0x%"
                            PRIx64 "\n", (uint64_t)offset);
            }
        }
    }

    if (outf[0] && ('-' != outf[0])) {
        out_type = dd_filetype(outf);
        if (verbose)
            pr2serr(" >> Output file type: %s\n",
                    dd_filetype_str(out_type, ebuff));

        if (FT_ST == out_type) {
            pr2serr(ME "unable to use scsi tape device %s\n", outf);
            return SG_LIB_FILE_ERROR;
        }
        else if (FT_SG == out_type) {
            flags = O_RDWR | O_NONBLOCK;
            if (out_flags.direct)
                flags |= O_DIRECT;
            if (out_flags.excl)
                flags |= O_EXCL;
            if (out_flags.dsync)
                flags |= O_SYNC;
            if ((outfd = open(outf, flags)) < 0) {
                snprintf(ebuff, EBUFF_SZ, ME "could not open %s for "
                         "sg writing", outf);
                perror(ebuff);
                return SG_LIB_FILE_ERROR;
            }
            res = ioctl(outfd, SG_GET_VERSION_NUM, &t);
            if ((res < 0) || (t < 30122)) {
                pr2serr(ME "sg driver prior to 3.1.22\n");
                return SG_LIB_FILE_ERROR;
            }
            if (ioctl(outfd, SG_GET_RESERVED_SIZE, &t) < 0) {
                perror(ME "SG_GET_RESERVED_SIZE error");
                return SG_LIB_FILE_ERROR;
            }
            if (t < MIN_RESERVED_SIZE)
                t = MIN_RESERVED_SIZE;
            out_res_sz = blk_sz * bpt;
            if (out_res_sz > t) {
                if (ioctl(outfd, SG_SET_RESERVED_SIZE, &out_res_sz) < 0) {
                    perror(ME "SG_SET_RESERVED_SIZE error");
                    return SG_LIB_FILE_ERROR;
                }
            }
            if (NULL == wrkMmap) {
                wrkMmap = (unsigned char *)mmap(NULL, out_res_sz,
                                                PROT_READ | PROT_WRITE, MAP_SHARED, outfd, 0);
                if (MAP_FAILED == wrkMmap) {
                    snprintf(ebuff, EBUFF_SZ,
                             ME "error using mmap() on file: %s", outf);
                    perror(ebuff);
                    return SG_LIB_FILE_ERROR;
                }
            }
        }
        else if (FT_DEV_NULL == out_type)
            outfd = -1; /* don't bother opening */
        else {
            if (FT_RAW != out_type) {
                flags = O_WRONLY | O_CREAT;
                if (out_flags.direct)
                    flags |= O_DIRECT;
                if (out_flags.excl)
                    flags |= O_EXCL;
                if (out_flags.dsync)
                    flags |= O_SYNC;
                if (out_flags.append)
                    flags |= O_APPEND;
                if ((outfd = open(outf, flags, 0666)) < 0) {
                    snprintf(ebuff, EBUFF_SZ,
                             ME "could not open %s for writing", outf);
                    perror(ebuff);
                    return SG_LIB_FILE_ERROR;
                }
            }
            else {
                if ((outfd = open(outf, O_WRONLY)) < 0) {
                    snprintf(ebuff, EBUFF_SZ, ME "could not open %s "
                             "for raw writing", outf);
                    perror(ebuff);
                    return SG_LIB_FILE_ERROR;
                }
            }
            if (seek > 0) {
                off64_t offset = seek;

                offset *= blk_sz;       /* could exceed 32 bits here! */
                if (lseek64(outfd, offset, SEEK_SET) < 0) {
                    snprintf(ebuff, EBUFF_SZ, ME "couldn't seek to "
                             "required position on %s", outf);
                    perror(ebuff);
                    return SG_LIB_FILE_ERROR;
                }
                if (verbose)
                    pr2serr("   >> seek: lseek64 SEEK_SET, byte offset=0x%"
                            PRIx64 "\n", (uint64_t)offset);
            }
        }
    }
    if ((STDIN_FILENO == infd) && (STDOUT_FILENO == outfd)) {
        pr2serr("Won't default both IFILE to stdin _and_ OFILE to as "
                "stdout\n");
        pr2serr("For more information use '--help'\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    if (dd_count < 0) {
        in_num_sect = -1;
        if (FT_SG == in_type) {
            res = scsi_read_capacity(infd, &in_num_sect, &in_sect_sz);
            if (SG_LIB_CAT_UNIT_ATTENTION == res) {
                pr2serr("Unit attention(in), continuing\n");
                res = scsi_read_capacity(infd, &in_num_sect, &in_sect_sz);
            } else if (SG_LIB_CAT_ABORTED_COMMAND == res) {
                pr2serr("Aborted command(in), continuing\n");
                res = scsi_read_capacity(infd, &in_num_sect, &in_sect_sz);
            }
            if (0 != res) {
                sg_get_category_sense_str(res, sizeof(b), b, verbose);
                pr2serr("Read capacity (if=%s): %s\n", inf, b);
                in_num_sect = -1;
            }
        } else if (FT_BLOCK == in_type) {
            if (0 != read_blkdev_capacity(infd, &in_num_sect, &in_sect_sz)) {
                pr2serr("Unable to read block capacity on %s\n", inf);
                in_num_sect = -1;
            }
            if (blk_sz != in_sect_sz) {
                pr2serr("block size on %s confusion; bs=%d, from device=%d\n",
                        inf, blk_sz, in_sect_sz);
                in_num_sect = -1;
            }
        }
        if (in_num_sect > skip)
            in_num_sect -= skip;

        out_num_sect = -1;
        if (FT_SG == out_type) {
            res = scsi_read_capacity(outfd, &out_num_sect, &out_sect_sz);
            if (SG_LIB_CAT_UNIT_ATTENTION == res) {
                pr2serr("Unit attention(out), continuing\n");
                res = scsi_read_capacity(outfd, &out_num_sect, &out_sect_sz);
            } else if (SG_LIB_CAT_ABORTED_COMMAND == res) {
                pr2serr("Aborted command(out), continuing\n");
                res = scsi_read_capacity(outfd, &out_num_sect, &out_sect_sz);
            }
            if (0 != res) {
                sg_get_category_sense_str(res, sizeof(b), b, verbose);
                pr2serr("Read capacity (of=%s): %s\n", inf, b);
                out_num_sect = -1;
            }
        } else if (FT_BLOCK == out_type) {
            if (0 != read_blkdev_capacity(outfd, &out_num_sect,
                                          &out_sect_sz)) {
                pr2serr("Unable to read block capacity on %s\n", outf);
                out_num_sect = -1;
            }
            if (blk_sz != out_sect_sz) {
                pr2serr("block size on %s confusion: bs=%d, from device=%d\n",
                        outf, blk_sz, out_sect_sz);
                out_num_sect = -1;
            }
        }
        if (out_num_sect > seek)
            out_num_sect -= seek;
#ifdef SG_DEBUG
        pr2serr("Start of loop, count=%" PRId64 ", in_num_sect=%" PRId64 ", "
                "out_num_sect=%" PRId64 "\n", dd_count, in_num_sect,
                out_num_sect);
#endif
        if (in_num_sect > 0) {
            if (out_num_sect > 0)
                dd_count = (in_num_sect > out_num_sect) ? out_num_sect :
                           in_num_sect;
            else
                dd_count = in_num_sect;
        }
        else
            dd_count = out_num_sect;
    }

    if (dd_count < 0) {
        pr2serr("Couldn't calculate count, please give one\n");
        return SG_LIB_SYNTAX_ERROR;
    }
    if (! cdbsz_given) {
        if ((FT_SG == in_type) && (MAX_SCSI_CDBSZ != scsi_cdbsz_in) &&
                (((dd_count + skip) > UINT_MAX) || (bpt > USHRT_MAX))) {
            pr2serr("Note: SCSI command size increased to 16 bytes (for "
                    "'if')\n");
            scsi_cdbsz_in = MAX_SCSI_CDBSZ;
        }
        if ((FT_SG == out_type) && (MAX_SCSI_CDBSZ != scsi_cdbsz_out) &&
                (((dd_count + seek) > UINT_MAX) || (bpt > USHRT_MAX))) {
            pr2serr("Note: SCSI command size increased to 16 bytes (for "
                    "'of')\n");
            scsi_cdbsz_out = MAX_SCSI_CDBSZ;
        }
    }

    if (out_flags.dio && (FT_SG != in_type)) {
        out_flags.dio = 0;
        pr2serr(">>> dio only performed on 'of' side when 'if' is an sg "
                "device\n");
    }
    if (out_flags.dio) {
        int fd;
        char c;

        if ((fd = open(proc_allow_dio, O_RDONLY)) >= 0) {
            if (1 == read(fd, &c, 1)) {
                if ('0' == c)
                    pr2serr(">>> %s set to '0' but should be set to '1' for "
                            "direct IO\n", proc_allow_dio);
            }
            close(fd);
        }
    }

    if (wrkMmap) {
        wrkPos = wrkMmap;
    } else {
        if ((FT_RAW == in_type) || (FT_RAW == out_type)) {
            wrkBuff = (unsigned char *)malloc(blk_sz * bpt + psz);
            if (0 == wrkBuff) {
                pr2serr("Not enough user memory for raw\n");
                return SG_LIB_FILE_ERROR;
            }
            /* perhaps use posix_memalign() instead */
            wrkPos = (unsigned char *)(((uintptr_t)wrkBuff + psz - 1) &
                                       (~(psz - 1)));
        }
        else {
            wrkBuff = (unsigned char *)malloc(blk_sz * bpt);
            if (0 == wrkBuff) {
                pr2serr("Not enough user memory\n");
                return SG_LIB_FILE_ERROR;
            }
            wrkPos = wrkBuff;
        }
    }

    blocks_per = bpt;
#ifdef SG_DEBUG
    pr2serr("Start of loop, count=%" PRId64 ", blocks_per=%d\n", dd_count,
            blocks_per);
#endif
    if (do_time) {
        start_tm.tv_sec = 0;
        start_tm.tv_usec = 0;
        gettimeofday(&start_tm, NULL);
        start_tm_valid = 1;
    }
    req_count = dd_count;

    if (verbose && (dd_count > 0) && (0 == out_flags.dio) &&
            (FT_SG == in_type) && (FT_SG == out_type))
        pr2serr("Since both 'if' and 'of' are sg devices, only do mmap-ed "
                "transfers on 'if'\n");

    while (dd_count > 0) {
        blocks = (dd_count > blocks_per) ? blocks_per : dd_count;
        if (FT_SG == in_type) {
            ret = sg_read(infd, wrkPos, blocks, skip, blk_sz, scsi_cdbsz_in,
                          in_flags.fua, in_flags.dpo, 1);
            if ((SG_LIB_CAT_UNIT_ATTENTION == ret) ||
                    (SG_LIB_CAT_ABORTED_COMMAND == ret)) {
                pr2serr("Unit attention or aborted command, continuing "
                        "(r)\n");
                ret = sg_read(infd, wrkPos, blocks, skip, blk_sz,
                              scsi_cdbsz_in, in_flags.fua, in_flags.dpo, 1);
            }
            if (0 != ret) {
                pr2serr("sg_read failed, skip=%" PRId64 "\n", skip);
                break;
            }
            else
                in_full += blocks;
        }
        else {
            while (((res = read(infd, wrkPos, blocks * blk_sz)) < 0) &&
                    ((EINTR == errno) || (EAGAIN == errno)))
                ;
            if (verbose > 2)
                pr2serr("read(unix): count=%d, res=%d\n", blocks * blk_sz,
                        res);
            if (ret < 0) {
                snprintf(ebuff, EBUFF_SZ, ME "reading, skip=%" PRId64 " ",
                         skip);
                perror(ebuff);
                ret = -1;
                break;
            }
            else if (res < blocks * blk_sz) {
                dd_count = 0;
                blocks = res / blk_sz;
                if ((res % blk_sz) > 0) {
                    blocks++;
                    in_partial++;
                }
            }
            in_full += blocks;
        }

        if (0 == blocks)
            break;      /* read nothing so leave loop */

        if (FT_SG == out_type) {
            int do_mmap = (FT_SG == in_type) ? 0 : 1;
            int dio_res = out_flags.dio;

            ret = sg_write(outfd, wrkPos, blocks, seek, blk_sz, scsi_cdbsz_out,
                           out_flags.fua, out_flags.dpo, do_mmap, &dio_res);
            if ((SG_LIB_CAT_UNIT_ATTENTION == ret) ||
                    (SG_LIB_CAT_ABORTED_COMMAND == ret)) {
                pr2serr("Unit attention or aborted command, continuing (w)\n");
                dio_res = out_flags.dio;
                ret = sg_write(outfd, wrkPos, blocks, seek, blk_sz,
                               scsi_cdbsz_out, out_flags.fua, out_flags.dpo,
                               do_mmap, &dio_res);
            }
            if (0 != ret) {
                pr2serr("sg_write failed, seek=%" PRId64 "\n", seek);
                break;
            }
            else {
                out_full += blocks;
                if (out_flags.dio && (0 == dio_res))
                    num_dio_not_done++;
            }
        }
        else if (FT_DEV_NULL == out_type)
            out_full += blocks; /* act as if written out without error */
        else {
            while (((res = write(outfd, wrkPos, blocks * blk_sz)) < 0) &&
                    ((EINTR == errno) || (EAGAIN == errno)))
                ;
            if (verbose > 2)
                pr2serr("write(unix): count=%d, res=%d\n", blocks * blk_sz,
                        res);
            if (res < 0) {
                snprintf(ebuff, EBUFF_SZ, ME "writing, seek=%" PRId64 " ",
                         seek);
                perror(ebuff);
                break;
            }
            else if (res < blocks * blk_sz) {
                pr2serr("output file probably full, seek=%" PRId64 " ", seek);
                blocks = res / blk_sz;
                out_full += blocks;
                if ((res % blk_sz) > 0)
                    out_partial++;
                break;
            }
            else
                out_full += blocks;
        }
        if (dd_count > 0)
            dd_count -= blocks;
        skip += blocks;
        seek += blocks;
    }

    if (do_time)
        calc_duration_throughput(0);
    if (do_sync) {
        if (FT_SG == out_type) {
            pr2serr(">> Synchronizing cache on %s\n", outf);
            res = sg_ll_sync_cache_10(outfd, 0, 0, 0, 0, 0, 0, 0);
            if (SG_LIB_CAT_UNIT_ATTENTION == res) {
                pr2serr("Unit attention(out), continuing\n");
                res = sg_ll_sync_cache_10(outfd, 0, 0, 0, 0, 0, 0, 0);
            }
            if (0 != res) {
                sg_get_category_sense_str(res, sizeof(b), b, verbose);
                pr2serr("Synchronize cache(out): %s\n", b);
            }
        }
    }

    if (wrkBuff) free(wrkBuff);
    if (STDIN_FILENO != infd)
        close(infd);
    if ((STDOUT_FILENO != outfd) && (FT_DEV_NULL != out_type))
        close(outfd);
    if (0 != dd_count) {
        pr2serr("Some error occurred,");
        if (0 == ret)
            ret = SG_LIB_CAT_OTHER;
    }
    print_stats();
    if (sum_of_resids)
        pr2serr(">> Non-zero sum of residual counts=%d\n", sum_of_resids);
    if (num_dio_not_done)
        pr2serr(">> dio requested but _not_ done %d times\n",
                num_dio_not_done);
    return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
}
示例#17
0
/*
 * pwck - verify password file integrity
 */
int main (int argc, char **argv)
{
	int errors = 0;
	bool changed = false;

	/*
	 * 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);

	OPENLOG ("pwck");

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

	open_files ();

	if (sort_mode) {
		if (pw_sort () != 0) {
			fprintf (stderr,
			         _("%s: cannot sort entries in %s\n"),
			         Prog, pw_dbname ());
			fail_exit (E_CANTSORT);
		}
		if (is_shadow) {
			if (spw_sort () != 0) {
				fprintf (stderr,
				         _("%s: cannot sort entries in %s\n"),
				         Prog, spw_dbname ());
				fail_exit (E_CANTSORT);
			}
		}
		changed = true;
	} else {
		check_pw_file (&errors, &changed);

		if (is_shadow) {
			check_spw_file (&errors, &changed);
		}
	}

	close_files (changed);

	nscd_flush_cache ("passwd");

	/*
	 * Tell the user what we did and exit.
	 */
	if (0 != errors) {
		printf (changed ?
		        _("%s: the files have been updated\n") :
		        _("%s: no changes\n"), Prog);
	}

	closelog ();
	return ((0 != errors) ? E_BADENTRY : E_OKAY);
}
示例#18
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);
}
示例#19
0
文件: expiry.c 项目: brauner/shadow
/* 
 * expiry - check and enforce password expiration policy
 *
 *	expiry checks (-c) the current password expiration and forces (-f)
 *	changes when required. It is callable as a normal user command.
 */
int main (int argc, char **argv)
{
	struct passwd *pwd;
	struct spwd *spwd;

	Prog = Basename (argv[0]);

	sanitize_env ();

	/* 
	 * Start by disabling all of the keyboard signals.
	 */
	(void) signal (SIGHUP, catch_signals);
	(void) signal (SIGINT, catch_signals);
	(void) signal (SIGQUIT, catch_signals);
#ifdef	SIGTSTP
	(void) signal (SIGTSTP, catch_signals);
#endif

	/*
	 * expiry takes one of two arguments. The default action is to give
	 * the usage message.
	 */
	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	OPENLOG ("expiry");

	process_flags (argc, argv);

	/*
	 * Get user entries for /etc/passwd and /etc/shadow
	 */
	pwd = get_my_pwent ();
	if (NULL == pwd) {
		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 (10);
	}
	spwd = getspnam (pwd->pw_name); /* !USE_PAM, No need for xgetspnam */

	/*
	 * If checking accounts, use agecheck() function.
	 */
	if (cflg) {
		/*
		 * Print out number of days until expiration.
		 */
		agecheck (spwd);

		/*
		 * Exit with status indicating state of account.
		 */
		exit (isexpired (pwd, spwd));
	}

	/*
	 * Otherwise, force a password change with the expire() function.
	 * It will force the change or give a message indicating what to
	 * do.
	 * It won't return unless the account is unexpired.
	 */
	(void) expire (pwd, spwd);

	return E_SUCCESS;
}
示例#20
0
/* 
 * ===  FUNCTION  ======================================================================
 *         Name:  main
 *  Description:  main is called with number of runs to simulate TODO: other params
 *
 * =====================================================================================
 */
int main(int argc, char* argv[])
{
    int32_t seed = (int32_t)time(0);
	StochasticLib1 s(seed);
	CRandomMersenne r((int)seed);
	process_flags(argc, argv);
	list<person> infected, removed;	
    list<person> susceptible;
    list<prevalence_data> pr_data;	
    list<birth_data> br_data;
    list<death_data> death_data;
    list<float> birth_rate_data;
    ofstream prev_out("outputs/prevalence.txt", ios::out), out("outputs/population.txt", ios::out);
    //set up data
    import_prevalence_data(pr_data);
    import_birth_rates(birth_rate_data);
    import_death_data(death_data);
	initialize_population(susceptible, infected, pr_data, s, r);

    float b_rate;
    list<float>::iterator birthrate_itr = birth_rate_data.begin();
    //print prleminary (day 0) stats
    //
    cout << "time 0: ";
    print_prevalence(susceptible, infected, prev_out);

    int year = 0;
    // run simulation
    

    int total = 0, prev_total = susceptible.size() + infected.size();

    for(int i = 0; i < NUM_ITERATIONS; ++i) // 3 month intervals
    {
        update_births(susceptible, infected, b_rate, s);
        shuffle_population(susceptible);
        compute_infected(susceptible, infected, s, r);
        update_cd4_count(infected, r);
        update_age(susceptible, infected); // quarterly update
        output_population_statistics(susceptible, infected, removed, out);
        
        //update_cd4_count(
        if(i % 20 == 0) // every 5 years
        {
            if(birthrate_itr != birth_rate_data.end())
            {
                b_rate = *birthrate_itr;
                ++birthrate_itr;
            }
        }

        if(i  % 4 == 0) // every year
        {
            compute_deaths(susceptible, infected, removed, death_data, s); // life tables assume annual
            map<string, int> S, I, R;
            ++year;
            cout << "Year: " << year << "  \t";
            total = susceptible.size() + infected.size();
            float d_p = 100.0 * (total - prev_total) / prev_total;
            prev_total = total;
            cout << "change (TOTAL population): " << d_p <<  "% (" << total << ")" << "\t";
            // TODO: this outputs/couts
            print_prevalence(susceptible, infected, prev_out);
            //cout << "susceptibles: " << susceptible.size() << " infected: " 
             //   << infected.size() << " removed: " << removed.size() << endl << endl;
            print_population_changes(susceptible, infected, removed, S, I, R);
        }
	}


    out.close();
    prev_out.close();
    return 0;
}
示例#21
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);
}
示例#22
0
/*
 * main - groupmod command
 *
 */
int main (int argc, char **argv)
{
#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM
	pam_handle_t *pamh = NULL;
	int retval;
#endif				/* USE_PAM */
#endif				/* ACCT_TOOLS_SETUID */

#ifdef WITH_AUDIT
	audit_help_open ();
#endif
	atexit (do_cleanups);

	/*
	 * 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_flags (argc, argv);

	OPENLOG ("groupmod");

#ifdef ACCT_TOOLS_SETUID
#ifdef USE_PAM
	{
		struct passwd *pampw;
		pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */
		if (NULL == pampw) {
			fprintf (stderr,
			         _("%s: Cannot determine your user name.\n"),
			         Prog);
			exit (1);
		}

		retval = pam_start ("groupmod", pampw->pw_name, &conv, &pamh);
	}

	if (PAM_SUCCESS == retval) {
		retval = pam_authenticate (pamh, 0);
	}

	if (PAM_SUCCESS == retval) {
		retval = pam_acct_mgmt (pamh, 0);
	}

	if (NULL != pamh) {
		(void) pam_end (pamh, retval);
	}
	if (PAM_SUCCESS != retval) {
		fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
		exit (1);
	}
#endif				/* USE_PAM */
#endif				/* ACCT_TOOLS_SETUID */

#ifdef SHADOWGRP
	is_shadow_grp = sgr_file_present ();
#endif
	{
		struct group *grp;
		/*
		 * Start with a quick check to see if the group exists.
		 */
		grp = getgrnam (group_name); /* local, no need for xgetgrnam */
		if (NULL == grp) {
			fprintf (stderr,
			         _("%s: group '%s' does not exist\n"),
			         Prog, group_name);
			exit (E_NOTFOUND);
		} else {
			group_id = grp->gr_gid;
		}
	}

#ifdef	USE_NIS
	/*
	 * Now make sure it isn't an NIS group.
	 */
	if (__isgrNIS ()) {
		char *nis_domain;
		char *nis_master;

		fprintf (stderr,
		         _("%s: group %s is a NIS group\n"),
		         Prog, group_name);

		if (!yp_get_default_domain (&nis_domain) &&
		    !yp_master (nis_domain, "group.byname", &nis_master)) {
			fprintf (stderr,
			         _("%s: %s is the NIS master\n"),
			         Prog, nis_master);
		}
		exit (E_NOTFOUND);
	}
#endif

	if (gflg) {
		check_new_gid ();
	}

	if (nflg) {
		check_new_name ();
	}

	lock_files ();

	/*
	 * Now if the group is not changed, it's our fault.
	 * Make sure failures will be reported.
	 */
	prepare_failure_reports ();

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

	grp_update ();

	close_files ();

	nscd_flush_cache ("group");

	return E_SUCCESS;
}
示例#23
0
int main (int argc, char **argv)
{
#ifdef USE_PAM
    pam_handle_t *pamh = NULL;
    struct passwd *pampw;
    int retval;
#endif

    /*
     * Get my name so that I can use it to report errors.
     */

    Prog = Basename (argv[0]);

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

#ifdef USE_PAM
    retval = PAM_SUCCESS;

    pampw = getpwuid (getuid ());
    if (pampw == NULL) {
        retval = PAM_USER_UNKNOWN;
    }

    if (retval == PAM_SUCCESS) {
        retval =
            pam_start ("shadow", pampw->pw_name, &conv, &pamh);
    }

    if (retval == PAM_SUCCESS) {
        retval = pam_authenticate (pamh, 0);
        if (retval != PAM_SUCCESS) {
            pam_end (pamh, retval);
        }
    }

    if (retval == PAM_SUCCESS) {
        retval = pam_acct_mgmt (pamh, 0);
        if (retval != PAM_SUCCESS) {
            pam_end (pamh, retval);
        }
    }

    if (retval != PAM_SUCCESS) {
        fprintf (stderr, _("%s: PAM authentication failed\n"),
                 Prog);
        exit (1);
    }
#endif				/* USE_PAM */

    OPENLOG (Prog);

#ifdef SHADOWGRP
    is_shadow_grp = sgr_file_present ();
#endif

    /*
     * The open routines for the DBM files don't use read-write as the
     * mode, so we have to clue them in.
     */

#ifdef	NDBM
    gr_dbm_mode = O_RDWR;
#ifdef	SHADOWGRP
    sg_dbm_mode = O_RDWR;
#endif				/* SHADOWGRP */
#endif				/* NDBM */
    process_flags (argc, argv);

    /*
     * Start with a quick check to see if the group exists.
     */

    if (getgrnam (group_name)) {
        if (fflg) {
            exit (E_SUCCESS);
        }
        fprintf (stderr, _("%s: group %s exists\n"), Prog,
                 group_name);
        exit (E_NAME_IN_USE);
    }

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

    open_files ();

    if (!gflg || !oflg)
        find_new_gid ();

    grp_update ();

    close_files ();

#ifdef USE_PAM
    if (retval == PAM_SUCCESS) {
        retval = pam_chauthtok (pamh, 0);
        if (retval != PAM_SUCCESS) {
            pam_end (pamh, retval);
        }
    }

    if (retval != PAM_SUCCESS) {
        fprintf (stderr, _("%s: PAM chauthtok failed\n"), Prog);
        exit (1);
    }

    if (retval == PAM_SUCCESS)
        pam_end (pamh, PAM_SUCCESS);
#endif				/* USE_PAM */
    exit (E_SUCCESS);
    /*NOTREACHED*/
}
示例#24
0
文件: pwunconv.c 项目: brauner/shadow
int main (int argc, char **argv)
{
	const struct passwd *pw;
	struct passwd pwent;
	const struct spwd *spwd;

	Prog = Basename (argv[0]);

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

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

	OPENLOG ("pwunconv");

	process_flags (argc, argv);

#ifdef WITH_TCB
	if (getdef_bool("USE_TCB")) {
		fprintf (stderr, _("%s: can't work with tcb enabled\n"), Prog);
		exit (1);
	}
#endif				/* WITH_TCB */

	if (!spw_file_present ()) {
		/* shadow not installed, do nothing */
		exit (0);
	}

	if (pw_lock () == 0) {
		fprintf (stderr,
		         _("%s: cannot lock %s; try again later.\n"),
		         Prog, pw_dbname ());
		fail_exit (5);
	}
	pw_locked = true;
	if (pw_open (O_CREAT | O_RDWR) == 0) {
		fprintf (stderr,
		         _("%s: cannot open %s\n"),
		         Prog, pw_dbname ());
		fail_exit (1);
	}

	if (spw_lock () == 0) {
		fprintf (stderr,
		         _("%s: cannot lock %s; try again later.\n"),
		         Prog, spw_dbname ());
		fail_exit (5);
	}
	spw_locked = true;
	if (spw_open (O_RDONLY) == 0) {
		fprintf (stderr,
		         _("%s: cannot open %s\n"),
		         Prog, spw_dbname ());
		fail_exit (1);
	}

	(void) pw_rewind ();
	while ((pw = pw_next ()) != NULL) {
		spwd = spw_locate (pw->pw_name);
		if (NULL == spwd) {
			continue;
		}

		pwent = *pw;

		/*
		 * Update password if non-shadow is "x".
		 */
		if (strcmp (pw->pw_passwd, SHADOW_PASSWD_STRING) == 0) {
			pwent.pw_passwd = spwd->sp_pwdp;
		}

		/*
		 * Password aging works differently in the two different
		 * systems. With shadow password files you apparently must
		 * have some aging information. The maxweeks or minweeks
		 * may not map exactly. In pwconv we set max == 10000,
		 * which is about 30 years. Here we have to undo that
		 * kludge. So, if maxdays == 10000, no aging information is
		 * put into the new file. Otherwise, the days are converted
		 * to weeks and so on.
		 */
		if (pw_update (&pwent) == 0) {
			fprintf (stderr,
			         _("%s: failed to prepare the new %s entry '%s'\n"),
			         Prog, pw_dbname (), pwent.pw_name);
			fail_exit (3);
		}
	}

	(void) spw_close (); /* was only open O_RDONLY */

	if (pw_close () == 0) {
		fprintf (stderr,
		         _("%s: failure while writing changes to %s\n"),
		         Prog, pw_dbname ());
		SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
		fail_exit (3);
	}

	if (unlink (SHADOW) != 0) {
		fprintf (stderr,
			 _("%s: cannot delete %s\n"), Prog, SHADOW);
		SYSLOG ((LOG_ERR, "cannot delete %s", SHADOW));
		fail_exit (3);
	}

	if (spw_unlock () == 0) {
		fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, spw_dbname ());
		SYSLOG ((LOG_ERR, "failed to unlock %s", spw_dbname ()));
		/* continue */
	}
	if (pw_unlock () == 0) {
		fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
		SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
		/* continue */
	}

	nscd_flush_cache ("passwd");
	sssd_flush_cache (SSSD_DB_PASSWD);

	return 0;
}
示例#25
0
/*
 * login - create a new login session for a user
 *
 *	login is typically called by getty as the second step of a
 *	new user session. getty is responsible for setting the line
 *	characteristics to a reasonable set of values and getting
 *	the name of the user to be logged in. login may also be
 *	called to create a new user session on a pty for a variety
 *	of reasons, such as X servers or network logins.
 *
 *	the flags which login supports are
 *	
 *	-p - preserve the environment
 *	-r - perform autologin protocol for rlogin
 *	-f - do not perform authentication, user is preauthenticated
 *	-h - the name of the remote host
 */
int main (int argc, char **argv)
{
	const char *tmptty;
	char tty[BUFSIZ];

#ifdef RLOGIN
	char term[128] = "";
#endif				/* RLOGIN */
#if defined(HAVE_STRFTIME) && !defined(USE_PAM)
	char ptime[80];
#endif
	unsigned int delay;
	unsigned int retries;
	bool failed;
	bool subroot = false;
#ifndef USE_PAM
	bool is_console;
#endif
	int err;
	const char *cp;
	char *tmp;
	char fromhost[512];
	struct passwd *pwd = NULL;
	char **envp = environ;
	const char *failent_user;
	/*@null@*/struct utmp *utent;

#ifdef USE_PAM
	int retcode;
	pid_t child;
	char *pam_user = NULL;
#else
	struct spwd *spwd = NULL;
#endif
	/*
	 * Some quick initialization.
	 */

	sanitize_env ();

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

	initenv ();

	amroot = (getuid () == 0);
	Prog = Basename (argv[0]);

	if (geteuid() != 0) {
		fprintf (stderr, _("%s: Cannot possibly work without effective root\n"), Prog);
		exit (1);
	}

	process_flags (argc, argv);

	if ((isatty (0) == 0) || (isatty (1) == 0) || (isatty (2) == 0)) {
		exit (1);	/* must be a terminal */
	}

	utent = get_current_utmp ();
	/*
	 * Be picky if run by normal users (possible if installed setuid
	 * root), but not if run by root. This way it still allows logins
	 * even if your getty is broken, or if something corrupts utmp,
	 * but users must "exec login" which will use the existing utmp
	 * entry (will not overwrite remote hostname).  --marekm
	 */
	if (!amroot && (NULL == utent)) {
		(void) puts (_("No utmp entry.  You must exec \"login\" from the lowest level \"sh\""));
		exit (1);
	}
	/* NOTE: utent might be NULL afterwards */

	tmptty = ttyname (0);
	if (NULL == tmptty) {
		tmptty = "UNKNOWN";
	}
	STRFCPY (tty, tmptty);

#ifndef USE_PAM
	is_console = console (tty);
#endif

	if (rflg || hflg) {
		/*
		 * Add remote hostname to the environment. I think
		 * (not sure) I saw it once on Irix.  --marekm
		 */
		addenv ("REMOTEHOST", hostname);
	}
	if (fflg) {
		preauth_flag = true;
	}
	if (hflg) {
		reason = PW_RLOGIN;
	}
#ifdef RLOGIN
	if (rflg) {
		assert (NULL == username);
		username = xmalloc (USER_NAME_MAX_LENGTH + 1);
		username[USER_NAME_MAX_LENGTH] = '\0';
		if (do_rlogin (hostname, username, USER_NAME_MAX_LENGTH, term, sizeof term)) {
			preauth_flag = true;
		} else {
			free (username);
			username = NULL;
		}
	}
#endif				/* RLOGIN */

	OPENLOG ("login");

	setup_tty ();

#ifndef USE_PAM
	(void) umask (getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));

	{
		/* 
		 * Use the ULIMIT in the login.defs file, and if
		 * there isn't one, use the default value. The
		 * user may have one for themselves, but otherwise,
		 * just take what you get.
		 */
		long limit = getdef_long ("ULIMIT", -1L);

		if (limit != -1) {
			set_filesize_limit (limit);
		}
	}

#endif
	/*
	 * The entire environment will be preserved if the -p flag
	 * is used.
	 */
	if (pflg) {
		while (NULL != *envp) {	/* add inherited environment, */
			addenv (*envp, NULL); /* some variables change later */
			envp++;
		}
	}

#ifdef RLOGIN
	if (term[0] != '\0') {
		addenv ("TERM", term);
	} else
#endif				/* RLOGIN */
	{
		/* preserve TERM from getty */
		if (!pflg) {
			tmp = getenv ("TERM");
			if (NULL != tmp) {
				addenv ("TERM", tmp);
			}
		}
	}

	init_env ();

	if (optind < argc) {	/* now set command line variables */
		set_env (argc - optind, &argv[optind]);
	}

	if (rflg || hflg) {
		cp = hostname;
#ifdef	HAVE_STRUCT_UTMP_UT_HOST
	} else if ((NULL != utent) && ('\0' != utent->ut_host[0])) {
		cp = utent->ut_host;
#endif				/* HAVE_STRUCT_UTMP_UT_HOST */
	} else {
		cp = "";
	}

	if ('\0' != *cp) {
		snprintf (fromhost, sizeof fromhost,
		          " on '%.100s' from '%.200s'", tty, cp);
	} else {
		snprintf (fromhost, sizeof fromhost,
		          " on '%.100s'", tty);
	}

      top:
	/* only allow ALARM sec. for login */
	(void) signal (SIGALRM, alarm_handler);
	timeout = getdef_unum ("LOGIN_TIMEOUT", ALARM);
	if (timeout > 0) {
		(void) alarm (timeout);
	}

	environ = newenvp;	/* make new environment active */
	delay   = getdef_unum ("FAIL_DELAY", 1);
	retries = getdef_unum ("LOGIN_RETRIES", RETRIES);

#ifdef USE_PAM
	retcode = pam_start ("login", username, &conv, &pamh);
	if (retcode != PAM_SUCCESS) {
		fprintf (stderr,
		         _("login: PAM Failure, aborting: %s\n"),
		         pam_strerror (pamh, retcode));
		SYSLOG ((LOG_ERR, "Couldn't initialize PAM: %s",
		         pam_strerror (pamh, retcode)));
		exit (99);
	}

	/*
	 * hostname & tty are either set to NULL or their correct values,
	 * depending on how much we know. We also set PAM's fail delay to
	 * ours.
	 *
	 * PAM_RHOST and PAM_TTY are used for authentication, only use
	 * information coming from login or from the caller (e.g. no utmp)
	 */
	retcode = pam_set_item (pamh, PAM_RHOST, hostname);
	PAM_FAIL_CHECK;
	retcode = pam_set_item (pamh, PAM_TTY, tty);
	PAM_FAIL_CHECK;
#ifdef HAS_PAM_FAIL_DELAY
	retcode = pam_fail_delay (pamh, 1000000 * delay);
	PAM_FAIL_CHECK;
#endif
	/* if fflg, then the user has already been authenticated */
	if (!fflg) {
		unsigned int failcount = 0;
		char hostn[256];
		char loginprompt[256];	/* That's one hell of a prompt :) */

		/* Make the login prompt look like we want it */
		if (gethostname (hostn, sizeof (hostn)) == 0) {
			snprintf (loginprompt,
			          sizeof (loginprompt),
			          _("%s login: "******"login: "******"TOO MANY LOGIN TRIES (%u)%s FOR '%s'",
				         failcount, fromhost, failent_user));
				fprintf(stderr,
				        _("Maximum number of tries exceeded (%u)\n"),
				        failcount);
				PAM_END;
				exit(0);
			} else if (retcode == PAM_ABORT) {
				/* Serious problems, quit now */
				(void) fputs (_("login: abort requested by PAM\n"), stderr);
				SYSLOG ((LOG_ERR,"PAM_ABORT returned from pam_authenticate()"));
				PAM_END;
				exit(99);
			} else if (retcode != PAM_SUCCESS) {
				SYSLOG ((LOG_NOTICE,"FAILED LOGIN (%u)%s FOR '%s', %s",
				         failcount, fromhost, failent_user,
				         pam_strerror (pamh, retcode)));
				failed = true;
			}

			if (!failed) {
				break;
			}

#ifdef WITH_AUDIT
			audit_fd = audit_open ();
			audit_log_acct_message (audit_fd,
			                        AUDIT_USER_LOGIN,
			                        NULL,    /* Prog. name */
			                        "login",
			                        failent_user,
			                        AUDIT_NO_ID,
			                        hostname,
			                        NULL,    /* addr */
			                        tty,
			                        0);      /* result */
			close (audit_fd);
#endif				/* WITH_AUDIT */

			(void) puts ("");
			(void) puts (_("Login incorrect"));

			if (failcount >= retries) {
				SYSLOG ((LOG_NOTICE,
				         "TOO MANY LOGIN TRIES (%u)%s FOR '%s'",
				         failcount, fromhost, failent_user));
				fprintf(stderr,
				        _("Maximum number of tries exceeded (%u)\n"),
				        failcount);
				PAM_END;
				exit(0);
			}

			/*
			 * Let's give it another go around.
			 * Even if a username was given on the command
			 * line, prompt again for the username.
			 */
			retcode = pam_set_item (pamh, PAM_USER, NULL);
			PAM_FAIL_CHECK;
		}

		/* We don't get here unless they were authenticated above */
		(void) alarm (0);
	}

	/* Check the account validity */
	retcode = pam_acct_mgmt (pamh, 0);
	if (retcode == PAM_NEW_AUTHTOK_REQD) {
		retcode = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
	}
	PAM_FAIL_CHECK;

	/* Open the PAM session */
	get_pam_user (&pam_user);
	retcode = pam_open_session (pamh, hushed (pam_user) ? PAM_SILENT : 0);
	PAM_FAIL_CHECK;

	/* Grab the user information out of the password file for future usage
	 * First get the username that we are actually using, though.
	 *
	 * From now on, we will discard changes of the user (PAM_USER) by
	 * PAM APIs.
	 */
	get_pam_user (&pam_user);
	if (NULL != username) {
		free (username);
	}
	username = pam_user;
	failent_user = get_failent_user (username);

	pwd = xgetpwnam (username);
	if (NULL == pwd) {
		SYSLOG ((LOG_ERR, "cannot find user %s", failent_user));
		exit (1);
	}

	/* This set up the process credential (group) and initialize the
	 * supplementary group access list.
	 * This has to be done before pam_setcred
	 */
	if (setup_groups (pwd) != 0) {
		exit (1);
	}

	retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED);
	PAM_FAIL_CHECK;
	/* NOTE: If pam_setcred changes PAM_USER, this will not be taken
	 * into account.
	 */

#else				/* ! USE_PAM */
	while (true) {	/* repeatedly get login/password pairs */
		/* user_passwd is always a pointer to this constant string
		 * or a passwd or shadow password that will be memzero by
		 * pw_free / spw_free.
		 * Do not free() user_passwd. */
		const char *user_passwd = "!";

		/* Do some cleanup to avoid keeping entries we do not need
		 * anymore. */
		if (NULL != pwd) {
			pw_free (pwd);
			pwd = NULL;
		}
		if (NULL != spwd) {
			spw_free (spwd);
			spwd = NULL;
		}

		failed = false;	/* haven't failed authentication yet */
		if (NULL == username) {	/* need to get a login id */
			if (subroot) {
				closelog ();
				exit (1);
			}
			preauth_flag = false;
			username = xmalloc (USER_NAME_MAX_LENGTH + 1);
			username[USER_NAME_MAX_LENGTH] = '\0';
			login_prompt (_("\n%s login: "******"!",
			 * the account is locked and the user cannot
			 * login, even if they have been
			 * "pre-authenticated."
			 */
			if (   ('!' == user_passwd[0])
			    || ('*' == user_passwd[0])) {
				failed = true;
			}
		}

		if (strcmp (user_passwd, SHADOW_PASSWD_STRING) == 0) {
			spwd = xgetspnam (username);
			if (NULL != spwd) {
				user_passwd = spwd->sp_pwdp;
			} else {
				/* The user exists in passwd, but not in
				 * shadow. SHADOW_PASSWD_STRING indicates
				 * that the password shall be in shadow.
				 */
				SYSLOG ((LOG_WARN,
				         "no shadow password for '%s'%s",
				         username, fromhost));
			}
		}

		/*
		 * The -r and -f flags provide a name which has already
		 * been authenticated by some server.
		 */
		if (preauth_flag) {
			goto auth_ok;
		}

		if (pw_auth (user_passwd, username, reason, (char *) 0) == 0) {
			goto auth_ok;
		}

		SYSLOG ((LOG_WARN, "invalid password for '%s' %s",
		         failent_user, fromhost));
		failed = true;

	      auth_ok:
		/*
		 * This is the point where all authenticated users wind up.
		 * If you reach this far, your password has been
		 * authenticated and so on.
		 */
		if (   !failed
		    && (NULL != pwd)
		    && (0 == pwd->pw_uid)
		    && !is_console) {
			SYSLOG ((LOG_CRIT, "ILLEGAL ROOT LOGIN %s", fromhost));
			failed = true;
		}
		if (   !failed
		    && !login_access (username, ('\0' != *hostname) ? hostname : tty)) {
			SYSLOG ((LOG_WARN, "LOGIN '%s' REFUSED %s",
			         username, fromhost));
			failed = true;
		}
		if (   (NULL != pwd)
		    && getdef_bool ("FAILLOG_ENAB")
		    && !failcheck (pwd->pw_uid, &faillog, failed)) {
			SYSLOG ((LOG_CRIT,
			         "exceeded failure limit for '%s' %s",
			         username, fromhost));
			failed = true;
		}
		if (!failed) {
			break;
		}

		/* don't log non-existent users */
		if ((NULL != pwd) && getdef_bool ("FAILLOG_ENAB")) {
			failure (pwd->pw_uid, tty, &faillog);
		}
		if (getdef_str ("FTMP_FILE") != NULL) {
#ifdef USE_UTMPX
			struct utmpx *failent =
				prepare_utmpx (failent_user,
				               tty,
			/* FIXME: or fromhost? */hostname,
				               utent);
#else				/* !USE_UTMPX */
			struct utmp *failent =
				prepare_utmp (failent_user,
				              tty,
				              hostname,
				              utent);
#endif				/* !USE_UTMPX */
			failtmp (failent_user, failent);
			free (failent);
		}

		retries--;
		if (retries <= 0) {
			SYSLOG ((LOG_CRIT, "REPEATED login failures%s",
			         fromhost));
		}

		/*
		 * If this was a passwordless account and we get here, login
		 * was denied (securetty, faillog, etc.). There was no
		 * password prompt, so do it now (will always fail - the bad
		 * guys won't see that the passwordless account exists at
		 * all).  --marekm
		 */
		if (user_passwd[0] == '\0') {
			pw_auth ("!", username, reason, (char *) 0);
		}

		/*
		 * Authentication of this user failed.
		 * The username must be confirmed in the next try.
		 */
		free (username);
		username = NULL;

		/*
		 * Wait a while (a la SVR4 /usr/bin/login) before attempting
		 * to login the user again. If the earlier alarm occurs
		 * before the sleep() below completes, login will exit.
		 */
		if (delay > 0) {
			(void) sleep (delay);
		}

		(void) puts (_("Login incorrect"));

		/* allow only one attempt with -r or -f */
		if (rflg || fflg || (retries <= 0)) {
			closelog ();
			exit (1);
		}
	}			/* while (true) */
#endif				/* ! USE_PAM */
	assert (NULL != username);
	assert (NULL != pwd);

	(void) alarm (0);		/* turn off alarm clock */

#ifndef USE_PAM			/* PAM does this */
	/*
	 * porttime checks moved here, after the user has been
	 * authenticated. now prints a message, as suggested
	 * by Ivan Nejgebauer <*****@*****.**>.  --marekm
	 */
	if (   getdef_bool ("PORTTIME_CHECKS_ENAB")
	    && !isttytime (username, tty, time ((time_t *) 0))) {
		SYSLOG ((LOG_WARN, "invalid login time for '%s'%s",
		         username, fromhost));
		closelog ();
		bad_time_notify ();
		exit (1);
	}

	check_nologin (pwd->pw_uid == 0);
#endif

	if (getenv ("IFS")) {	/* don't export user IFS ... */
		addenv ("IFS= \t\n", NULL);	/* ... instead, set a safe IFS */
	}

	if (pwd->pw_shell[0] == '*') {	/* subsystem root */
		pwd->pw_shell++;	/* skip the '*' */
		subsystem (pwd);	/* figure out what to execute */
		subroot = true;	/* say I was here again */
		endpwent ();	/* close all of the file which were */
		endgrent ();	/* open in the original rooted file */
		endspent ();	/* system. they will be re-opened */
#ifdef	SHADOWGRP
		endsgent ();	/* in the new rooted file system */
#endif
		goto top;	/* go do all this all over again */
	}

#ifdef WITH_AUDIT
	audit_fd = audit_open ();
	audit_log_acct_message (audit_fd,
	                        AUDIT_USER_LOGIN,
	                        NULL,    /* Prog. name */
	                        "login",
	                        username,
	                        AUDIT_NO_ID,
	                        hostname,
	                        NULL,    /* addr */
	                        tty,
	                        1);      /* result */
	close (audit_fd);
#endif				/* WITH_AUDIT */

#ifndef USE_PAM			/* pam_lastlog handles this */
	if (getdef_bool ("LASTLOG_ENAB")) {	/* give last login and log this one */
		dolastlog (&ll, pwd, tty, hostname);
	}
#endif

#ifndef USE_PAM			/* PAM handles this as well */
	/*
	 * Have to do this while we still have root privileges, otherwise we
	 * don't have access to /etc/shadow.
	 */
	if (NULL != spwd) {		/* check for age of password */
		if (expire (pwd, spwd)) {
			/* The user updated her password, get the new
			 * entries.
			 * Use the x variants because we need to keep the
			 * entry for a long time, and there might be other
			 * getxxyy in between.
			 */
			pw_free (pwd);
			pwd = xgetpwnam (username);
			if (NULL == pwd) {
				SYSLOG ((LOG_ERR,
				         "cannot find user %s after update of expired password",
				         username));
				exit (1);
			}
			spw_free (spwd);
			spwd = xgetspnam (username);
		}
	}
	setup_limits (pwd);	/* nice, ulimit etc. */
#endif				/* ! USE_PAM */
	chown_tty (pwd);

#ifdef USE_PAM
	/*
	 * We must fork before setuid() because we need to call
	 * pam_close_session() as root.
	 */
	(void) signal (SIGINT, SIG_IGN);
	child = fork ();
	if (child < 0) {
		/* error in fork() */
		fprintf (stderr, _("%s: failure forking: %s"),
		         Prog, strerror (errno));
		PAM_END;
		exit (0);
	} else if (child != 0) {
		/*
		 * parent - wait for child to finish, then cleanup
		 * session
		 */
		wait (NULL);
		PAM_END;
		exit (0);
	}
	/* child */
#endif

	/* If we were init, we need to start a new session */
	if (getppid() == 1) {
		setsid();
		if (ioctl(0, TIOCSCTTY, 1) != 0) {
			fprintf (stderr, _("TIOCSCTTY failed on %s"), tty);
		}
	}

	/*
	 * The utmp entry needs to be updated to indicate the new status
	 * of the session, the new PID and SID.
	 */
	update_utmp (username, tty, hostname, utent);

	/* The pwd and spwd entries for the user have been copied.
	 *
	 * Close all the files so that unauthorized access won't occur.
	 */
	endpwent ();		/* stop access to password file */
	endgrent ();		/* stop access to group file */
	endspent ();		/* stop access to shadow passwd file */
#ifdef	SHADOWGRP
	endsgent ();		/* stop access to shadow group file */
#endif

	/* Drop root privileges */
#ifndef USE_PAM
	if (setup_uid_gid (pwd, is_console))
#else
	/* The group privileges were already dropped.
	 * See setup_groups() above.
	 */
	if (change_uid (pwd))
#endif
	{
		exit (1);
	}

	setup_env (pwd);	/* set env vars, cd to the home dir */

#ifdef USE_PAM
	{
		const char *const *env;

		env = (const char *const *) pam_getenvlist (pamh);
		while ((NULL != env) && (NULL != *env)) {
			addenv (*env, NULL);
			env++;
		}
	}
#endif

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

	if (!hushed (username)) {
		addenv ("HUSHLOGIN=FALSE", NULL);
		/*
		 * pam_unix, pam_mail and pam_lastlog should take care of
		 * this
		 */
#ifndef USE_PAM
		motd ();	/* print the message of the day */
		if (   getdef_bool ("FAILLOG_ENAB")
		    && (0 != faillog.fail_cnt)) {
			failprint (&faillog);
			/* Reset the lockout times if logged in */
			if (   (0 != faillog.fail_max)
			    && (faillog.fail_cnt >= faillog.fail_max)) {
				(void) puts (_("Warning: login re-enabled after temporary lockout."));
				SYSLOG ((LOG_WARN,
				         "login '%s' re-enabled after temporary lockout (%d failures)",
				         username, (int) faillog.fail_cnt));
			}
		}
		if (   getdef_bool ("LASTLOG_ENAB")
		    && (ll.ll_time != 0)) {
			time_t ll_time = ll.ll_time;

#ifdef HAVE_STRFTIME
			(void) strftime (ptime, sizeof (ptime),
			                 "%a %b %e %H:%M:%S %z %Y",
			                 localtime (&ll_time));
			printf (_("Last login: %s on %s"),
			        ptime, ll.ll_line);
#else
			printf (_("Last login: %.19s on %s"),
			        ctime (&ll_time), ll.ll_line);
#endif
#ifdef HAVE_LL_HOST		/* __linux__ || SUN4 */
			if ('\0' != ll.ll_host[0]) {
				printf (_(" from %.*s"),
				        (int) sizeof ll.ll_host, ll.ll_host);
			}
#endif
			printf (".\n");
		}
		agecheck (spwd);

		mailcheck ();	/* report on the status of mail */
#endif				/* !USE_PAM */
	} else {
		addenv ("HUSHLOGIN=TRUE", NULL);
	}

	ttytype (tty);

	(void) signal (SIGQUIT, SIG_DFL);	/* default quit signal */
	(void) signal (SIGTERM, SIG_DFL);	/* default terminate signal */
	(void) signal (SIGALRM, SIG_DFL);	/* default alarm signal */
	(void) signal (SIGHUP, SIG_DFL);	/* added this.  --marekm */
	(void) signal (SIGINT, SIG_DFL);	/* default interrupt signal */

	if (0 == pwd->pw_uid) {
		SYSLOG ((LOG_NOTICE, "ROOT LOGIN %s", fromhost));
	} else if (getdef_bool ("LOG_OK_LOGINS")) {
		SYSLOG ((LOG_INFO, "'%s' logged in %s", username, fromhost));
	}
	closelog ();
	tmp = getdef_str ("FAKE_SHELL");
	if (NULL != tmp) {
		err = shell (tmp, pwd->pw_shell, newenvp); /* fake shell */
	} else {
		/* exec the shell finally */
		err = shell (pwd->pw_shell, (char *) 0, newenvp);
	}

	return ((err == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
}
示例#26
0
文件: usermod.c 项目: OPSF/uClinux
/*
 * process_flags - perform command line argument setting
 *
 *	process_flags() interprets the command line arguments and sets the
 *	values that the user will be created with accordingly. The values
 *	are checked for sanity.
 */
static void process_flags (int argc, char **argv)
{
	const struct group *grp;
	const struct passwd *pwd;

	const struct spwd *spwd = NULL;
	int anyflag = 0;
	int arg;

	if (argc == 1 || argv[argc - 1][0] == '-')
		usage ();

	if (!(pwd = getpwnam (argv[argc - 1]))) {
		fprintf (stderr, _("%s: user %s does not exist\n"),
			 Prog, argv[argc - 1]);
		exit (E_NOTFOUND);
	}

	user_name = argv[argc - 1];
	user_id = pwd->pw_uid;
	user_gid = pwd->pw_gid;
	user_comment = xstrdup (pwd->pw_gecos);
	user_home = xstrdup (pwd->pw_dir);
	user_shell = xstrdup (pwd->pw_shell);
#ifdef WITH_AUDIT
	user_newname = user_name;
	user_newid = user_id;
	user_newgid = user_gid;
	user_newcomment = user_comment;
	user_newhome = user_home;
	user_newshell = user_shell;
#endif

#ifdef	USE_NIS
	/*
	 * Now make sure it isn't an NIS user.
	 */
	if (__ispwNIS ()) {
		char *nis_domain;
		char *nis_master;

		fprintf (stderr, _("%s: user %s is a NIS user\n"),
			 Prog, user_name);

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

	if (is_shadow_pwd && (spwd = getspnam (user_name))) {
		user_expire = spwd->sp_expire;
		user_inactive = spwd->sp_inact;
#ifdef WITH_AUDIT
		user_newexpire = user_expire;
		user_newinactive = user_inactive;
#endif
	}

	{
		/*
		 * Parse the command line options.
		 */
		int c;
		static struct option long_options[] = {
			{"append", required_argument, NULL, 'a'},
			{"comment", required_argument, NULL, 'c'},
			{"home", required_argument, NULL, 'd'},
			{"expiredate", required_argument, NULL, 'e'},
			{"inactive", required_argument, NULL, 'f'},
			{"gid", required_argument, NULL, 'g'},
			{"groups", required_argument, NULL, 'G'},
			{"help", no_argument, NULL, 'h'},
			{"login", required_argument, NULL, 'l'},
			{"lock", no_argument, NULL, 'L'},
			{"move-home", no_argument, NULL, 'm'},
			{"non-unique", no_argument, NULL, 'o'},
			{"password", required_argument, NULL, 'p'},
			{"shell", required_argument, NULL, 's'},
			{"uid", required_argument, NULL, 'u'},
			{"unlock", no_argument, NULL, 'U'},
			{NULL, 0, NULL, '\0'}
		};
		while ((c =
			getopt_long (argc, argv, "ac:d:e:f:g:G:l:Lmop:s:u:U",
				     long_options, NULL)) != -1) {
			switch (c) {
			case 'a':
				aflg++;
				break;
			case 'c':
				if (!VALID (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
#ifdef WITH_AUDIT
				user_newcomment = optarg;
#else
				user_comment = optarg;
#endif
				cflg++;
				break;
			case 'd':
				if (!VALID (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
				dflg++;
				user_newhome = optarg;
				break;
			case 'e':
				if (*optarg) {
#ifdef WITH_AUDIT
					user_newexpire = strtoday (optarg);
					if (user_newexpire == -1) {
#else
					user_expire = strtoday (optarg);
					if (user_expire == -1) {
#endif
						fprintf (stderr,
							 _
							 ("%s: invalid date `%s'\n"),
							 Prog, optarg);
						exit (E_BAD_ARG);
					}
#ifdef WITH_AUDIT
					user_newexpire *= DAY / SCALE;
#else
					user_expire *= DAY / SCALE;
#endif
				} else
#ifdef WITH_AUDIT
					user_newexpire = -1;
#else
					user_expire = -1;
#endif
				eflg++;
				break;
			case 'f':
#ifdef WITH_AUDIT
				user_newinactive = get_number (optarg);
#else
				user_inactive = get_number (optarg);
#endif
				fflg++;
				break;
			case 'g':
				grp = getgr_nam_gid (optarg);
				if (!grp) {
					fprintf (stderr,
						 _("%s: unknown group %s\n"),
						 Prog, optarg);
					exit (E_NOTFOUND);
				}
				user_newgid = grp->gr_gid;
				gflg++;
				break;
			case 'G':
				if (get_groups (optarg))
					exit (E_NOTFOUND);
				Gflg++;
				break;
			case 'l':
				if (!check_user_name (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}

				/*
				 * If the name does not really change, we mustn't
				 * set the flag as this will cause rather serious
				 * problems later!
				 */
				if (strcmp (user_name, optarg))
					lflg++;

				user_newname = optarg;
				break;
			case 'L':
				if (Uflg || pflg)
					usage ();

				Lflg++;
				break;
			case 'm':
				if (!dflg)
					usage ();

				mflg++;
				break;
			case 'o':
				if (!uflg)
					usage ();

				oflg++;
				break;
			case 'p':
				if (Lflg || Uflg)
					usage ();

				user_pass = optarg;
				pflg++;
				break;
			case 's':
				if (!VALID (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
#ifdef WITH_AUDIT
				user_newshell = optarg;
#else
				user_shell = optarg;
#endif
				sflg++;
				break;
			case 'u':
				user_newid = get_id (optarg);
				uflg++;
				break;
			case 'U':
				if (Lflg && pflg)
					usage ();

				Uflg++;
				break;
			default:
				usage ();
			}
			anyflag++;
		}
	}

	if (anyflag == 0) {
		fprintf (stderr, _("%s: no flags given\n"), Prog);
		exit (E_USAGE);
	}
	if (!is_shadow_pwd && (eflg || fflg)) {
		fprintf (stderr,
			 _
			 ("%s: shadow passwords required for -e and -f\n"),
			 Prog);
		exit (E_USAGE);
	}

	if (optind != argc - 1)
		usage ();

	if (aflg && (!Gflg)) {
		fprintf (stderr,
			 _("%s: -a flag is ONLY allowed with the -G flag\n"),
			 Prog);
		usage ();
		exit (E_USAGE);
	}

	if (dflg && strcmp (user_home, user_newhome) == 0)
		dflg = mflg = 0;

	if (uflg && user_id == user_newid)
		uflg = oflg = 0;

	if (lflg && getpwnam (user_newname)) {
		fprintf (stderr, _("%s: user %s exists\n"), Prog, user_newname);
		exit (E_NAME_IN_USE);
	}

	if (uflg && !oflg && getpwuid (user_newid)) {
		fprintf (stderr, _("%s: uid %lu is not unique\n"),
			 Prog, (unsigned long) user_newid);
		exit (E_UID_IN_USE);
	}
}

/*
 * close_files - close all of the files that were opened
 *
 *	close_files() closes all of the files that were opened for this new
 *	user. This causes any modified entries to be written out.
 */
static void close_files (void)
{
	if (!pw_close ()) {
		fprintf (stderr, _("%s: cannot rewrite password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd && !spw_close ()) {
		fprintf (stderr,
			 _("%s: cannot rewrite shadow password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd)
		spw_unlock ();
	(void) pw_unlock ();

	/*
	 * Close the DBM and/or flat files
	 */
	endpwent ();
	endspent ();
	endgrent ();
#ifdef	SHADOWGRP
	endsgent ();
#endif
}

/*
 * open_files - lock and open the password files
 *
 *	open_files() opens the two password files.
 */
static void open_files (void)
{
	if (!pw_lock ()) {
		fprintf (stderr, _("%s: unable to lock password file\n"), Prog);
		exit (E_PW_UPDATE);
	}
	if (!pw_open (O_RDWR)) {
		fprintf (stderr, _("%s: unable to open password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd && !spw_lock ()) {
		fprintf (stderr,
			 _("%s: cannot lock shadow password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd && !spw_open (O_RDWR)) {
		fprintf (stderr,
			 _("%s: cannot open shadow password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
}

/*
 * usr_update - create the user entries
 *
 *	usr_update() creates the password file entries for this user and
 *	will update the group entries if required.
 */
static void usr_update (void)
{
	struct passwd pwent;
	const struct passwd *pwd;

	struct spwd spent;
	const struct spwd *spwd = NULL;

	/*
	 * Locate the entry in /etc/passwd, which MUST exist.
	 */
	pwd = pw_locate (user_name);
	if (!pwd) {
		fprintf (stderr, _("%s: %s not found in /etc/passwd\n"),
			 Prog, user_name);
		fail_exit (E_NOTFOUND);
	}
	pwent = *pwd;
	new_pwent (&pwent);


	/* 
	 * Locate the entry in /etc/shadow. It doesn't have to exist, and
	 * won't be created if it doesn't.
	 */
	if (is_shadow_pwd && (spwd = spw_locate (user_name))) {
		spent = *spwd;
		new_spent (&spent);
	}

	if (lflg || uflg || gflg || cflg || dflg || sflg || pflg
	    || Lflg || Uflg) {
		if (!pw_update (&pwent)) {
			fprintf (stderr,
				 _("%s: error changing password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
		if (lflg && !pw_remove (user_name)) {
			fprintf (stderr,
				 _("%s: error removing password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
	}
	if (spwd && (lflg || eflg || fflg || pflg || Lflg || Uflg)) {
		if (!spw_update (&spent)) {
			fprintf (stderr,
				 _
				 ("%s: error adding new shadow password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
		if (lflg && !spw_remove (user_name)) {
			fprintf (stderr,
				 _
				 ("%s: error removing shadow password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
	}
}

/*
 * move_home - move the user's home directory
 *
 *	move_home() moves the user's home directory to a new location. The
 *	files will be copied if the directory cannot simply be renamed.
 */
static void move_home (void)
{
	struct stat sb;

	if (mflg && stat (user_home, &sb) == 0) {
		/*
		 * Don't try to move it if it is not a directory
		 * (but /dev/null for example).  --marekm
		 */
		if (!S_ISDIR (sb.st_mode))
			return;

		if (access (user_newhome, F_OK) == 0) {
			fprintf (stderr, _("%s: directory %s exists\n"),
				 Prog, user_newhome);
			fail_exit (E_HOMEDIR);
		} else if (rename (user_home, user_newhome)) {
			if (errno == EXDEV) {
				if (mkdir (user_newhome, sb.st_mode & 0777)) {
					fprintf (stderr,
						 _
						 ("%s: can't create %s\n"),
						 Prog, user_newhome);
				}
				if (chown (user_newhome, sb.st_uid, sb.st_gid)) {
					fprintf (stderr,
						 _("%s: can't chown %s\n"),
						 Prog, user_newhome);
					rmdir (user_newhome);
					fail_exit (E_HOMEDIR);
				}
				if (copy_tree (user_home, user_newhome,
					       uflg ? user_newid : -1,
					       gflg ? user_newgid : -1) == 0) {
					if (remove_tree (user_home) != 0 ||
					    rmdir (user_home) != 0)
						fprintf (stderr,
							 _
							 ("%s: warning: failed to completely remove old home directory %s"),
							 Prog, user_home);
#ifdef WITH_AUDIT
					audit_logger (AUDIT_USER_CHAUTHTOK,
						      Prog,
						      "moving home directory",
						      user_newname, user_newid,
						      1);
#endif
					return;
				}

				(void) remove_tree (user_newhome);
				(void) rmdir (user_newhome);
			}
			fprintf (stderr,
				 _
				 ("%s: cannot rename directory %s to %s\n"),
				 Prog, user_home, user_newhome);
			fail_exit (E_HOMEDIR);
		}
#ifdef WITH_AUDIT
		audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			      "moving home directory", user_newname, user_newid,
			      1);
#endif
	}
	if (uflg || gflg) {
#ifdef WITH_AUDIT
		audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			      "changing home directory owner", user_newname,
			      user_newid, 1);
#endif
		chown (dflg ? user_newhome : user_home,
		       uflg ? user_newid : user_id,
		       gflg ? user_newgid : user_gid);
	}
}

/*
 * update_files - update the lastlog and faillog files
 */
static void update_files (void)
{
	struct lastlog ll;
	struct faillog fl;
	int fd;

	/*
	 * Relocate the "lastlog" entries for the user. The old entry is
	 * left alone in case the UID was shared. It doesn't hurt anything
	 * to just leave it be.
	 */
	if ((fd = open (LASTLOG_FILE, O_RDWR)) != -1) {
		lseek (fd, (off_t) user_id * sizeof ll, SEEK_SET);
		if (read (fd, (char *) &ll, sizeof ll) == sizeof ll) {
			lseek (fd, (off_t) user_newid * sizeof ll, SEEK_SET);
			write (fd, (char *) &ll, sizeof ll);
		}
		close (fd);
	}

	/*
	 * Relocate the "faillog" entries in the same manner.
	 */
	if ((fd = open (FAILLOG_FILE, O_RDWR)) != -1) {
		lseek (fd, (off_t) user_id * sizeof fl, SEEK_SET);
		if (read (fd, (char *) &fl, sizeof fl) == sizeof fl) {
			lseek (fd, (off_t) user_newid * sizeof fl, SEEK_SET);
			write (fd, (char *) &fl, sizeof fl);
		}
		close (fd);
	}
}

#ifndef NO_MOVE_MAILBOX
/*
 * This is the new and improved code to carefully chown/rename the user's
 * mailbox. Maybe I am too paranoid but the mail spool dir sometimes
 * happens to be mode 1777 (this makes mail user agents work without
 * being setgid mail, but is NOT recommended; they all should be fixed
 * to use movemail).  --marekm
 */
static void move_mailbox (void)
{
	const char *maildir;
	char mailfile[1024], newmailfile[1024];
	int fd;
	struct stat st;

	maildir = getdef_str ("MAIL_DIR");
#ifdef MAIL_SPOOL_DIR
	if (!maildir && !getdef_str ("MAIL_FILE"))
		maildir = MAIL_SPOOL_DIR;
#endif
	if (!maildir)
		return;

	/*
	 * O_NONBLOCK is to make sure open won't hang on mandatory locks.
	 * We do fstat/fchown to make sure there are no races (someone
	 * replacing /var/spool/mail/luser with a hard link to /etc/passwd
	 * between stat and chown).  --marekm
	 */
	snprintf (mailfile, sizeof mailfile, "%s/%s", maildir, user_name);
	fd = open (mailfile, O_RDONLY | O_NONBLOCK, 0);
	if (fd < 0) {
		/* no need for warnings if the mailbox doesn't exist */
		if (errno != ENOENT)
			perror (mailfile);
		return;
	}
	if (fstat (fd, &st) < 0) {
		perror ("fstat");
		close (fd);
		return;
	}
	if (st.st_uid != user_id) {
		/* better leave it alone */
		fprintf (stderr, _("%s: warning: %s not owned by %s\n"),
			 Prog, mailfile, user_name);
		close (fd);
		return;
	}
	if (uflg) {
		if (fchown (fd, user_newid, (gid_t) - 1) < 0) {
			perror (_("failed to change mailbox owner"));
		}
#ifdef WITH_AUDIT
		else {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
				      "changing mail file owner", user_newname,
				      user_newid, 1);
		}
#endif
	}

	close (fd);

	if (lflg) {
		snprintf (newmailfile, sizeof newmailfile, "%s/%s",
			  maildir, user_newname);
		if (link (mailfile, newmailfile) || unlink (mailfile)) {
			perror (_("failed to rename mailbox"));
		}
#ifdef WITH_AUDIT
		else {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
				      "changing mail file name", user_newname,
				      user_newid, 1);
		}
#endif
	}
}
#endif

/*
 * main - usermod command
 */
int main (int argc, char **argv)
{
	int grp_err = 0;

#ifdef USE_PAM
	pam_handle_t *pamh = NULL;
	struct passwd *pampw;
	int retval;
#endif

#ifdef WITH_AUDIT
	audit_help_open ();
#endif

	/*
	 * Get my name so that I can use it to report errors.
	 */
	Prog = Basename (argv[0]);

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

	sys_ngroups = sysconf (_SC_NGROUPS_MAX);
	user_groups = malloc ((1 + sys_ngroups) * sizeof (char *));
	user_groups[0] = (char *) 0;

	OPENLOG ("usermod");

	is_shadow_pwd = spw_file_present ();
#ifdef SHADOWGRP
	is_shadow_grp = sgr_file_present ();
#endif

	process_flags (argc, argv);

#ifdef USE_PAM
	retval = PAM_SUCCESS;

	pampw = getpwuid (getuid ());
	if (pampw == NULL) {
		retval = PAM_USER_UNKNOWN;
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_start ("usermod", pampw->pw_name, &conv, &pamh);
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_authenticate (pamh, 0);
		if (retval != PAM_SUCCESS) {
			pam_end (pamh, retval);
		}
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_acct_mgmt (pamh, 0);
		if (retval != PAM_SUCCESS) {
			pam_end (pamh, retval);
		}
	}

	if (retval != PAM_SUCCESS) {
		fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
		exit (1);
	}
#endif				/* USE_PAM */

	/*
	 * Do the hard stuff - open the files, change the user entries,
	 * change the home directory, then close and update the files.
	 */
	open_files ();

	usr_update ();
	nscd_flush_cache ("passwd");
	nscd_flush_cache ("group");

	close_files ();

	if (Gflg || lflg)
		grp_err = grp_update ();

	if (mflg)
		move_home ();

#ifndef NO_MOVE_MAILBOX
	if (lflg || uflg)
		move_mailbox ();
#endif

	if (uflg) {
		update_files ();

		/*
		 * Change the UID on all of the files owned by `user_id' to
		 * `user_newid' in the user's home directory.
		 */
		chown_tree (dflg ? user_newhome : user_home,
			    user_id, user_newid,
			    user_gid, gflg ? user_newgid : user_gid);
	}

	if (grp_err)
		exit (E_GRP_UPDATE);

#ifdef USE_PAM
	if (retval == PAM_SUCCESS)
		pam_end (pamh, PAM_SUCCESS);
#endif				/* USE_PAM */

	exit (E_SUCCESS);
	/* NOT REACHED */
}
示例#27
0
int main (int argc, char **argv)
{
	const struct group *gr;
	struct group grent;
	const struct sgrp *sg;

	Prog = Basename (argv[0]);

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

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

	OPENLOG ("grpunconv");

	process_flags (argc, argv);

	if (sgr_file_present () == 0) {
		exit (0);	/* no /etc/gshadow, nothing to do */
	}

	if (gr_lock () == 0) {
		fprintf (stderr,
		         _("%s: cannot lock %s; try again later.\n"),
		         Prog, gr_dbname ());
		fail_exit (5);
	}
	gr_locked = true;
	if (gr_open (O_RDWR) == 0) {
		fprintf (stderr,
		         _("%s: cannot open %s\n"), Prog, gr_dbname ());
		fail_exit (1);
	}

	if (sgr_lock () == 0) {
		fprintf (stderr,
		         _("%s: cannot lock %s; try again later.\n"),
		         Prog, sgr_dbname ());
		fail_exit (5);
	}
	sgr_locked = true;
	if (sgr_open (O_RDONLY) == 0) {
		fprintf (stderr,
		         _("%s: cannot open %s\n"), Prog, sgr_dbname ());
		fail_exit (1);
	}

	/*
	 * Update group passwords if non-shadow password is "x".
	 */
	(void) gr_rewind ();
	while ((gr = gr_next ()) != NULL) {
		sg = sgr_locate (gr->gr_name);
		if (   (NULL != sg)
		    && (strcmp (gr->gr_passwd, SHADOW_PASSWD_STRING) == 0)) {
			/* add password to /etc/group */
			grent = *gr;
			grent.gr_passwd = sg->sg_passwd;
			if (gr_update (&grent) == 0) {
				fprintf (stderr,
				         _("%s: failed to prepare the new %s entry '%s'\n"),
				         Prog, gr_dbname (), grent.gr_name);
				fail_exit (3);
			}
		}
	}

	(void) sgr_close (); /* was only open O_RDONLY */

	if (gr_close () == 0) {
		fprintf (stderr,
		         _("%s: failure while writing changes to %s\n"),
		         Prog, gr_dbname ());
		SYSLOG ((LOG_ERR, "failure while writing changes to %s", gr_dbname ()));
		fail_exit (3);
	}

	if (unlink (SGROUP_FILE) != 0) {
		fprintf (stderr,
		         _("%s: cannot delete %s\n"),
		         Prog, SGROUP_FILE);
		SYSLOG ((LOG_ERR, "cannot delete %s", SGROUP_FILE));
		fail_exit (3);
	}

	if (gr_unlock () == 0) {
		fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, gr_dbname ());
		SYSLOG ((LOG_ERR, "failed to unlock %s", gr_dbname ()));
		/* continue */
	}

	if (sgr_unlock () == 0) {
		fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, sgr_dbname ());
		SYSLOG ((LOG_ERR, "failed to unlock %s", sgr_dbname ()));
		/* continue */
	}

	nscd_flush_cache ("group");

	return 0;
}
示例#28
0
int main(int argc, char ** args){
    char *flag_array[] = FLAG_ARRAY;
    int flags = process_flags(argc, args, FLAG_ARRAY_SIZE, flag_array);
    double * numeric_args = malloc(sizeof(double) * (argc - 1));
    int numeric_arg_count = process_numeric_args(argc, args, numeric_args);

    if(flags & FLAG_HELP){
        help();
        return 0;
    }

    if(flags & FLAG_RESUME){
        printf("Unimplemented. Sorry.\n");
        return 1;
    }

    // first argument should always be a file unless --stdout
    FILE * fout;
    if(flags & FLAG_STDOUT){
        // write to stdout. This is useful if we want to pipe the data somewhere (ie, for visualisation)
        fout = stdout;
    }else{
        fout = fopen(args[1], "w");
        if(fout == NULL){
            printf("Could not open file at %s for writing. No such directory or permission denied.\n", args[1]);
            return 1;
        }
    }

    if(flags & FLAG_ORBIT){
        if(flags & FLAG_SIMPLE){
            if(flags & FLAG_2D){
                if(numeric_arg_count == 8){
                    char *labels[8] = {"time", "xpos", "ypos", "xvel", "yvel", "object_mass", "time_limit", "total_energy"};
                    set_up_runge_kutta_4th(5, 2);
                    iterate_to_file(&simple_2d_orbit_runge_kutta_4th, 8, numeric_args, numeric_args[7], labels, fout);
                    free_runge_kutta_4th();
                }else{
                    printf("Invalid number of numerical arguments. Need 8, %d given.\n", numeric_arg_count);
                }
            }else{
                printf("Simple 3D simulation has not been implemented. Please specify --2D.\n");
            }
        }else if(flags & FLAG_FREE){
            if(flags & FLAG_2D){
                // make sure a valid number of args has been entered
                if(numeric_arg_count >= 8 && (numeric_arg_count - 3) % 5 == 0){
                    body_count = (numeric_arg_count - 3) / 5;
                    char ** labels = malloc(sizeof(char *) * (body_count * 5 + 2));
                    labels[0] = "time";
                    int i;
                    for(i=0;i<body_count;i++){
                        labels[i * 5 + 1] = malloc(8);
                        sprintf(labels[i * 5 + 1], "%d.xpos", i);
                        labels[i * 5 + 2] = malloc(8);
                        sprintf(labels[i * 5 + 2], "%d.ypos", i);
                        labels[i * 5 + 3] = malloc(8);
                        sprintf(labels[i * 5 + 3], "%d.xvel", i);
                        labels[i * 5 + 4] = malloc(8);
                        sprintf(labels[i * 5 + 4], "%d.yvel", i);
                        labels[i * 5 + 5] = malloc(8);
                        sprintf(labels[i * 5 + 5], "%d.mass", i);
                    }
                    labels[body_count * 5 + 1] = "time_limit";
                    set_up_runge_kutta_4th(5 * body_count + 1, 1);
                    iterate_to_file(&free_2d_orbit_runge_kutta_4th, 5 * body_count + 2, numeric_args, numeric_args[numeric_arg_count - 1], labels, fout);
                    free_runge_kutta_4th();
                }else{
                    printf("Invalid number of numerical arguments. Need at least 8 with 5 arguments for each body. %d given\n", numeric_arg_count);
                    help();
                    return 1;
                }
            }else if(flags & FLAG_3D){
                // make sure a valid number of args have been entered
                if(numeric_arg_count >= 10 && (numeric_arg_count - 3) % 7 == 0){
                    body_count = (numeric_arg_count - 3) / 7;
                    char ** labels = malloc(sizeof(char *) * (body_count * 7 + 2));
                    labels[0] = "time";
                    int i;
                    for(i=0;i<body_count;i++){
                        labels[i * 7 + 1] = malloc(8);
                        sprintf(labels[i * 7 + 1], "%d.xpos", i);
                        labels[i * 7 + 2] = malloc(8);
                        sprintf(labels[i * 7 + 2], "%d.ypos", i);
                        labels[i * 7 + 3] = malloc(8);
                        sprintf(labels[i * 7 + 3], "%d.zpos", i);
                        labels[i * 7 + 4] = malloc(8);
                        sprintf(labels[i * 7 + 4], "%d.xvel", i);
                        labels[i * 7 + 5] = malloc(8);
                        sprintf(labels[i * 7 + 5], "%d.yvel", i);
                        labels[i * 7 + 6] = malloc(8);
                        sprintf(labels[i * 7 + 6], "%d.zvel", i);
                        labels[i * 7 + 7] = malloc(8);
                        sprintf(labels[i * 7 + 7], "%d.mass", i);
                    }
                    labels[body_count * 7 + 1] = "time_limit";
                    set_up_runge_kutta_4th(7 * body_count + 1, 1);
                    iterate_to_file(&free_3d_orbit_runge_kutta_4th, 7 * body_count + 2, numeric_args, numeric_args[numeric_arg_count - 1], labels, fout);
                    free_runge_kutta_4th();
                }else{
                    printf("Invalid number of numerical arguments. Need at least 10 with 7 arguments for each body. %d given\n", numeric_arg_count);
                    help();
                    return 1;
                }
            }else{
                printf("Please specify either --2D or --3D\n");
                help();
                return 1;
            }
        }else{
            printf("Please specify either --simple or --free\n");
            help();
            return 1;
        }
    }

    return 0;
}