Esempio n. 1
0
static VALUE
rb_shadow_putspent(VALUE self, VALUE entry, VALUE file)
{
  struct spwd centry;
  FILE* cfile;
  VALUE val[9];
  int i;
  int result;

  for(i=0; i<=8; i++)
    val[i] = RSTRUCT_PTR(entry)[i];
  cfile = file_ptr(RFILE(file)->fptr);

  centry.sp_namp = StringValuePtr(val[0]);
  centry.sp_pwdp = StringValuePtr(val[1]);
  centry.sp_lstchg = FIX2INT(val[2]);
  centry.sp_min = FIX2INT(val[3]);
  centry.sp_max = FIX2INT(val[4]);
  centry.sp_warn = FIX2INT(val[5]);
  centry.sp_inact = FIX2INT(val[6]);
  centry.sp_expire = FIX2INT(val[7]);
  centry.sp_flag = FIX2INT(val[8]);

  result = putspent(&centry,cfile);

  if( result == -1 )
    rb_raise(rb_eStandardError,"can't change password");

  return Qtrue;
};
Esempio n. 2
0
// {{{ user_set_password()
/// Set the password for the specified username
void user_set_password(user_t *o, char *username, volatile char* passwd)
{
   FILE *f;
   struct spwd *sp = NULL;

   o->error[0]=0;

   sp = getspnam(username);
   if(!sp)
   {
      sstrncpy(o->error, "user_set_password() unknown user",
         USER_ERROR_SIZE);
      return;
   }


   /* salt */
   struct timeval tv;
   static char salt[40];

   salt[0] = '\0';

   gettimeofday (&tv, (struct timezone *) 0);
   strcat(salt, l64a (tv.tv_usec));
   strcat(salt, l64a (tv.tv_sec + getpid () + clock ()));

   if (strlen (salt) > 3 + 8)  
      salt[11] = '\0';


   /* shadow */
   sp->sp_pwdp = (char*)crypt((const char*)passwd, salt);


   if(user_del_line(username, "/etc/shadow")!=0)
   {
      sstrncpy(o->error, "user_set_password() cannot modify /etc/shadow",
         USER_ERROR_SIZE);
      return;
   }

   f = fopen("/etc/shadow", "a+");
   if(!f)
   {
      sstrncpy(o->error, "user_set_password(): cannot open /etc/shadow",
            USER_ERROR_SIZE);
      return;
   }

   if (putspent(sp, f) == -1) 
   {
      sstrncpy(o->error, "user_add(): putspent() error", USER_ERROR_SIZE);
      return;
   }

   fclose(f);



}
Esempio n. 3
0
static int _update_shadow(const char *forwho, char *towhat)
{
    struct spwd *spwdent = NULL, *stmpent = NULL;
    FILE *pwfile, *opwfile;
    int err = 1;
    int oldmask;

    spwdent = getspnam(forwho);
    if (spwdent == NULL) {
	return PAM_USER_UNKNOWN;
    }
    oldmask = umask(077);
    pwfile = fopen(SH_TMPFILE, "w");
    umask(oldmask);
    if (pwfile == NULL) {
	return PAM_AUTHTOK_ERR;
    }

    opwfile = fopen("/etc/shadow", "r");
    if (opwfile == NULL) {
	fclose(pwfile);
	return PAM_AUTHTOK_ERR;
    }

    chown(SH_TMPFILE, 0, 0);
    chmod(SH_TMPFILE, 0600);
    stmpent = fgetspent(opwfile);
    while (stmpent) {

	if (!strcmp(stmpent->sp_namp, forwho)) {
	    stmpent->sp_pwdp = towhat;
	    stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24);
	    err = 0;
	    D(("Set password %s for %s", stmpent->sp_pwdp, forwho));
	}

	if (putspent(stmpent, pwfile)) {
	    D(("error writing entry to shadow file: %s\n", strerror(errno)));
	    err = 1;
	    break;
	}

	stmpent = fgetspent(opwfile);
    }
    fclose(opwfile);

    if (fclose(pwfile)) {
	D(("error writing entries to shadow file: %s\n", strerror(errno)));
	err = 1;
    }

    if (!err) {
	rename(SH_TMPFILE, "/etc/shadow");
	return PAM_SUCCESS;
    } else {
	unlink(SH_TMPFILE);
	return PAM_AUTHTOK_ERR;
    }
}
Esempio n. 4
0
static int shadow_put (const void *ent, FILE * file)
{
	const struct spwd *sp = ent;

	if (   (NULL == sp)
	    || (valid_field (sp->sp_namp, ":\n") == -1)
	    || (valid_field (sp->sp_pwdp, ":\n") == -1)) {
		return -1;
	}

	return (putspent (sp, file) == -1) ? -1 : 0;
}
Esempio n. 5
0
static int write_root_shadow(const char *path, const struct spwd *p) {
        _cleanup_fclose_ FILE *f = NULL;
        assert(path);
        assert(p);

        RUN_WITH_UMASK(0777)
                f = fopen(path, "wex");
        if (!f)
                return -errno;

        errno = 0;
        if (putspent(p, f) != 0)
                return errno ? -errno : -EIO;

        return fflush_and_check(f);
}
Esempio n. 6
0
static int
shadow_put(const void *ent, FILE *file)
{
	const struct spwd *sp = ent;
	return (putspent(sp, file) == -1) ? -1 : 0;
}
Esempio n. 7
0
/*
 * files_update_shadow(char *name, struct spwd *spwd)
 *
 * update the shadow password file SHADOW to contain the spwd structure
 * "spwd" for user "name"
 */
int
files_update_shadow(char *name, struct spwd *spwd)
{
	struct stat64 stbuf;
	FILE *dst;
	FILE *src;
	struct spwd cur;
	char buf[SPW_SCRATCH_SIZE];
	int tempfd;
	mode_t filemode;
	int result = -1;
	int err = PWU_SUCCESS;

	/* Mode of the shadow file should be 400 or 000 */
	if (stat64(SHADOW, &stbuf) < 0) {
		err = PWU_STAT_FAILED;
		goto shadow_exit;
	}

	/* copy mode from current shadow file (0400 or 0000) */
	filemode = stbuf.st_mode & S_IRUSR;

	/*
	 * we can't specify filemodes to fopen(), and we SHOULD NOT
	 * set umask in multi-thread safe libraries, so we use
	 * a combination of open() and fdopen()
	 */
	tempfd = open(SHADTEMP, O_WRONLY|O_CREAT|O_TRUNC, filemode);
	if (tempfd < 0) {
		err = PWU_OPEN_FAILED;
		goto shadow_exit;
	}
	(void) fchown(tempfd, (uid_t)0, stbuf.st_gid);

	if ((dst = fdopen(tempfd, "wF")) == NULL) {
		err = PWU_OPEN_FAILED;
		goto shadow_exit;
	}

	if ((src = fopen(SHADOW, "rF")) == NULL) {
		err = PWU_OPEN_FAILED;
		(void) fclose(dst);
		(void) unlink(SHADTEMP);
		goto shadow_exit;
	}

	/*
	 * copy old shadow to temporary file while replacing the entry
	 * that matches "name".
	 */
	while (fgetspent_r(src, &cur, buf, sizeof (buf)) != NULL) {

		if (strcmp(cur.sp_namp, name) == 0)
			result = putspent(spwd, dst);
		else
			result = putspent(&cur, dst);

		if (result != 0) {
			err = PWU_WRITE_FAILED;
			(void) fclose(src);
			(void) fclose(dst);
			goto shadow_exit;
		}
	}

	(void) fclose(src);

	if (fclose(dst) != 0) {
		/*
		 * Something went wrong (ENOSPC for example). Don't
		 * use the resulting temporary file!
		 */
		err = PWU_CLOSE_FAILED;
		(void) unlink(SHADTEMP);
		goto shadow_exit;
	}

	/*
	 * Rename stmp to shadow:
	 *   1. make sure /etc/oshadow is gone
	 *   2. ln /etc/shadow /etc/oshadow
	 *   3. mv /etc/stmp /etc/shadow
	 */
	if (unlink(OSHADOW) && access(OSHADOW, 0) == 0) {
		err = PWU_UPDATE_FAILED;
		(void) unlink(SHADTEMP);
		goto shadow_exit;
	}

	if (link(SHADOW, OSHADOW) == -1) {
		err = PWU_UPDATE_FAILED;
		(void) unlink(SHADTEMP);
		goto shadow_exit;
	}

	if (rename(SHADTEMP, SHADOW) == -1) {
		err = PWU_UPDATE_FAILED;
		(void) unlink(SHADTEMP);
		goto shadow_exit;
	}
	(void) unlink(OSHADOW);

shadow_exit:
	return (err);
}
Esempio n. 8
0
int auth_change_pwd(char *user, char *newpwd)
{
	struct passwd *spw;
	struct spwd *stp;
	char hash[35] = "";
	long today;

	FILE *fd;

	if (0 != lckpwdf())
	{
		return 1;
	}

	/* open passwd */
	spw = getpwnam(user);

	if (spw == 0)
	{
		return 1;
	}

	if (g_strncmp(spw->pw_passwd, "x", 3) != 0)
	{
		/* old system with only passwd */
		if (auth_crypt_pwd(spw->pw_passwd, newpwd, hash) != 0)
		{
			ulckpwdf();
			return 1;
		}

		spw->pw_passwd = g_strdup(hash);
		fd = fopen("/etc/passwd", "rw");
		putpwent(spw, fd);
	}
	else
	{
		/* the system is using shadow */
		stp = getspnam(user);

		if (stp == 0)
		{
			return 1;
		}

		/* old system with only passwd */
		if (auth_crypt_pwd(stp->sp_pwdp, newpwd, hash) != 0)
		{
			ulckpwdf();
			return 1;
		}

		stp->sp_pwdp = g_strdup(hash);
		today = g_time1() / SECS_PER_DAY;
		stp->sp_lstchg = today;
		stp->sp_expire = today + stp->sp_max + stp->sp_inact;
		fd = fopen("/etc/shadow", "rw");
		putspent(stp, fd);
	}

	ulckpwdf();
	return 0;
}
Esempio n. 9
0
PAMH_ARG_DECL(int unix_update_shadow,
	const char *forwho, char *towhat)
{
    struct spwd spwdent, *stmpent = NULL;
    struct stat st;
    FILE *pwfile, *opwfile;
    int err = 0;
    int oldmask;
    int wroteentry = 0;
#ifdef WITH_SELINUX
    security_context_t prev_context=NULL;
#endif

    oldmask = umask(077);

#ifdef WITH_SELINUX
    if (SELINUX_ENABLED) {
      security_context_t shadow_context=NULL;
      if (getfilecon("/etc/shadow",&shadow_context)<0) {
	return PAM_AUTHTOK_ERR;
      };
      if (getfscreatecon(&prev_context)<0) {
	freecon(shadow_context);
	return PAM_AUTHTOK_ERR;
      }
      if (setfscreatecon(shadow_context)) {
	freecon(shadow_context);
	freecon(prev_context);
	return PAM_AUTHTOK_ERR;
      }
      freecon(shadow_context);
    }
#endif
    pwfile = fopen(SH_TMPFILE, "w");
    umask(oldmask);
    if (pwfile == NULL) {
	err = 1;
	goto done;
    }

    opwfile = fopen("/etc/shadow", "r");
    if (opwfile == NULL) {
	fclose(pwfile);
	err = 1;
	goto done;
    }

    if (fstat(fileno(opwfile), &st) == -1) {
	fclose(opwfile);
	fclose(pwfile);
	err = 1;
	goto done;
    }

    if (fchown(fileno(pwfile), st.st_uid, st.st_gid) == -1) {
	fclose(opwfile);
	fclose(pwfile);
	err = 1;
	goto done;
    }
    if (fchmod(fileno(pwfile), st.st_mode) == -1) {
	fclose(opwfile);
	fclose(pwfile);
	err = 1;
	goto done;
    }

    stmpent = fgetspent(opwfile);
    while (stmpent) {

	if (!strcmp(stmpent->sp_namp, forwho)) {
	    stmpent->sp_pwdp = towhat;
	    stmpent->sp_lstchg = time(NULL) / (60 * 60 * 24);
	    if (stmpent->sp_lstchg == 0)
	        stmpent->sp_lstchg = -1; /* Don't request passwort change
					    only because time isn't set yet. */
	    wroteentry = 1;
	    D(("Set password %s for %s", stmpent->sp_pwdp, forwho));
	}

	if (putspent(stmpent, pwfile)) {
	    D(("error writing entry to shadow file: %m"));
	    err = 1;
	    break;
	}

	stmpent = fgetspent(opwfile);
    }

    fclose(opwfile);

    if (!wroteentry && !err) {
	spwdent.sp_namp = forwho;
	spwdent.sp_pwdp = towhat;
	spwdent.sp_lstchg = time(NULL) / (60 * 60 * 24);
	if (spwdent.sp_lstchg == 0)
	    spwdent.sp_lstchg = -1; /* Don't request passwort change
				       only because time isn't set yet. */
	spwdent.sp_min = spwdent.sp_max = spwdent.sp_warn = spwdent.sp_inact =
	    spwdent.sp_expire = -1;
	spwdent.sp_flag = (unsigned long)-1l;
	if (putspent(&spwdent, pwfile)) {
	    D(("error writing entry to shadow file: %m"));
	    err = 1;
	}
    }

    if (fflush(pwfile) || fsync(fileno(pwfile))) {
	D(("fflush or fsync error writing entries to shadow file: %m"));
	err = 1;
    }

    if (fclose(pwfile)) {
	D(("fclose error writing entries to shadow file: %m"));
	err = 1;
    }

 done:
    if (!err) {
	if (!rename(SH_TMPFILE, "/etc/shadow"))
	    pam_syslog(pamh,
		LOG_NOTICE, "password changed for %s", forwho);
	else
	    err = 1;
    }

#ifdef WITH_SELINUX
    if (SELINUX_ENABLED) {
      if (setfscreatecon(prev_context)) {
	err = 1;
      }
      if (prev_context)
	freecon(prev_context);
      prev_context=NULL;
    }
#endif

    if (!err) {
	return PAM_SUCCESS;
    } else {
	unlink(SH_TMPFILE);
	return PAM_AUTHTOK_ERR;
    }
}
Esempio n. 10
0
static const char* set_passwd(const char *name, const char *passwd, char **msg)
{
	FILE *f = NULL;
	struct spwd *spwd, new_spwd;
	const char *en_passwd; /* encrypted password */
	struct stat st;

	assert(name);
	assert(passwd);

	/* check password format */
	if ((passwd[0] != '$') ||
			(passwd[1] != '0' && passwd[1] != '1' && passwd[1] != '5' && passwd[1] != '6') ||
			(passwd[2] != '$')) {
		asprintf(msg, "Wrong password format (user %s).", name);
		return (NULL);
	}

	if (passwd[1] == '0') {
		/* encrypt the password */
		get_login_defs();
		en_passwd = pw_encrypt(&(passwd[3]), crypt_make_salt(NULL, NULL));
	} else {
		en_passwd = passwd;
	}

	/*
	 * store encrypted password into shadow
	 */

	/* lock shadow file */
	if (lckpwdf() != 0) {
		*msg = strdup("Failed to acquire shadow file lock.");
		return (NULL);
	}
	/* init position in shadow */
	setspent();

	/* open new shadow */
	f = fopen(SHADOW_COPY, "w");
	if (f == NULL) {
		asprintf(msg, "Unable to prepare shadow copy (%s).", strerror(errno));
		endspent();
		ulckpwdf();
		return (NULL);
	}
	/* get file stat of the original file to make a nice copy of it */
	stat(SHADOW_ORIG, &st);
	fchmod(fileno(f), st.st_mode);
	fchown(fileno(f), st.st_uid, st.st_gid);

	while ((spwd = getspent()) != NULL) {
		if (strcmp(spwd->sp_namp, name) == 0) {
			/*
			 * we have the entry to change,
			 * make the copy, modifying the original
			 * structure doesn't seem as a good idea
			 */
			memcpy(&new_spwd, spwd, sizeof(struct spwd));
			new_spwd.sp_pwdp = (char*) en_passwd;
			spwd = &new_spwd;
		}
		/* store the record into the shadow copy */
		putspent(spwd, f);
	}
	endspent();
	fclose(f);

	if (rename(SHADOW_COPY, SHADOW_ORIG) == -1) {
		asprintf(msg, "Unable to rewrite shadow database (%s).", strerror(errno));
		unlink(SHADOW_COPY);
		ulckpwdf();
		return (NULL);
	}
	ulckpwdf();

	return (en_passwd);
}
Esempio n. 11
0
void
changepasswd(SVCXPRT *transp)
{
	/*
	 * Put these numeric constants into const variables so
	 *   a) they're visible in a debugger
	 *   b) the compiler can play it's cool games with em
	 */
	static const int cryptpwsize = CRYPT_MAXCIPHERTEXTLEN;
	static const int fingersize = FINGERSIZE;
	static const int shellsize = SHELLSIZE;

	struct yppasswd yppwd;
	struct passwd newpw, opwd;
	struct spwd ospwd;
	struct sigaction sa, osa1, osa2, osa3;
	struct stat pwstat, spstat, adjstat;
	char *oldpass_crypt = NULL;

	char newpasswdfile[FILENAME_MAX];
	char newshadowfile[FILENAME_MAX];
	char newadjunctfile[FILENAME_MAX];
	char tmppasswdfile[FILENAME_MAX];
	char tmpshadowfile[FILENAME_MAX];
	char tmpadjunctfile[FILENAME_MAX];
	char pwbuf[NSS_LINELEN_PASSWD], spbuf[NSS_LINELEN_SHADOW];
	char adjbuf[BUFSIZ+1], adjbuf_new[BUFSIZ+1], cmdbuf[BUFSIZ];
	char adj_encrypt[CRYPT_MAXCIPHERTEXTLEN + 1];
	/*
	 * The adj_crypt_* pointers are used to point into adjbuf
	 * NOT adj_encrypt
	 */
	char *adj_crypt_begin, *adj_crypt_end;
	char name[UTUSERLEN + sizeof (":")];
	char *p;

	FILE *opwfp = NULL, *ospfp = NULL, *oadjfp = NULL,
	    *npwfp = NULL, *nspfp = NULL, *nadjfp = NULL;
	int npwfd = -1, nspfd = -1, nadjfd = -1;

	int i, ans, chsh, chpw, chgecos, namelen;
	int gotadjunct = 0, gotshadow = 0, gotpasswd = 0;
	int doneflag = 0, root_on_master = 0;
	pid_t retval;

	time_t now;

	long pwpos = 0, sppos = 0;

	/* Globals :-( */
	extern int single, nogecos, noshell, nopw, mflag, Mstart, Argc;
	extern char **Argv;
	extern char passwd_file[], shadow_file[], adjunct_file[];
	extern int useadjunct;
	extern int useshadow;

	/* Clean out yppwd */
	memset(&yppwd, 0, sizeof (struct yppasswd));

	/* Get the RPC args */
	if (!svc_getargs(transp, xdr_yppasswd, (caddr_t)&yppwd)) {
		svcerr_decode(transp);
		return;
	}

	/* Perform basic validation */
	if (/* (!validstr(yppwd.oldpass, PWSIZE)) || */ /* see PR:nis/38 */
	    (!validstr(yppwd.newpw.pw_passwd, cryptpwsize)) ||
	    (!validstr(yppwd.newpw.pw_name, UTUSERLEN)) ||
	    (!validstr(yppwd.newpw.pw_gecos, fingersize)) ||
	    (!validstr(yppwd.newpw.pw_shell, shellsize))) {
		svcerr_decode(transp);
		return;
	}

	/*
	 * Special case: root on the master server can change other users'
	 * passwords without first entering the old password.  We need to
	 * ensure that this is indeed root on the master server. (bug 1253949)
	 */
	if (strcmp(transp->xp_netid, "ticlts") == 0) {
		svc_local_cred_t cred;
		if (!svc_get_local_cred(transp, &cred)) {
			syslog(LOG_ERR, "yppasswdd: Couldn't get "
			    "local user credentials.\n");
		} else if (cred.ruid == 0)
			root_on_master = 1;
	}

	newpw = yppwd.newpw;
	strcpy(name, newpw.pw_name);
	strcat(name, ":");
	namelen = strlen(name);
	ans = 2;
	chsh = chpw = chgecos = 0;

	/* Get all the filenames straight */
	strcpy(newpasswdfile, passwd_file);
	strcat(newpasswdfile, ".ptmp");
	strcpy(newshadowfile, shadow_file);
	strcat(newshadowfile, ".ptmp");
	strcpy(newadjunctfile, adjunct_file);
	strcat(newadjunctfile, ".ptmp");

	memset(&sa, 0, sizeof (struct sigaction));
	sa.sa_handler = SIG_IGN;
	sigaction(SIGTSTP, &sa, (struct sigaction *)0);
	sigaction(SIGHUP,  &sa, &osa1);
	sigaction(SIGINT,  &sa, &osa2);
	sigaction(SIGQUIT, &sa, &osa3);

	/* Lock, then open the passwd and shadow files */

	if (yplckpwdf() < 0) {
		syslog(LOG_ERR,
		    "yppasswdd: Password file(s) busy. "
		    "Try again later.\n");
		ans = 8;
		goto cleanup;
	}

	if ((opwfp = fopen(passwd_file, "r")) == NULL) {
		syslog(LOG_ERR, "yppasswdd: Could not open %s\n", passwd_file);
		goto cleanup;
	}

	fstat(fileno(opwfp), &pwstat);

	if (useshadow) {
		if ((ospfp = fopen(shadow_file, "r")) == NULL) {
			syslog(LOG_ERR,
			    "yppasswdd: Could not open %s\n", shadow_file);
			goto cleanup;
		}

		fstat(fileno(ospfp), &spstat);
	}

	if (useadjunct) {
		if ((oadjfp = fopen(adjunct_file, "r")) == NULL) {
			syslog(LOG_ERR,
			    "yppasswdd: Could not open %s\n",
			    adjunct_file);
			goto cleanup;
		}

		fstat(fileno(oadjfp), &adjstat);
	}

	/*
	 * Open the new passwd and shadow tmp files,
	 * first with open and then create a FILE * with fdopen()
	 */
	if ((npwfd = open(newpasswdfile, O_WRONLY | O_CREAT | O_EXCL,
	    pwstat.st_mode)) < 0) {
		if (errno == EEXIST) {
			syslog(LOG_WARNING,
			    "yppasswdd: passwd file busy - try again\n");
			ans = 8;
		} else {
			syslog(LOG_ERR, "yppasswdd: %s: %m",
			    newpasswdfile);
			ans = 9;
		}
		goto cleanup;
	}

	fchown(npwfd, pwstat.st_uid, pwstat.st_gid);

	if ((npwfp = fdopen(npwfd, "w")) == NULL) {
		syslog(LOG_ERR,
		    "yppasswdd: fdopen() on %s failed\n", newpasswdfile);
		goto cleanup;
	}

	if (useshadow) {
		if ((nspfd = open(newshadowfile, O_WRONLY | O_CREAT | O_EXCL,
		    spstat.st_mode)) < 0) {
			if (errno == EEXIST) {
				syslog(LOG_WARNING,
				    "yppasswdd: shadow file busy - try "
				    "again\n");
				ans = 8;
			} else {
				syslog(LOG_ERR, "yppasswdd: %s: %m",
				    newshadowfile);
				ans = 9;
			}
			goto cleanup;
		}

		fchown(nspfd, spstat.st_uid, spstat.st_gid);

		if ((nspfp = fdopen(nspfd, "w")) == NULL) {
			syslog(LOG_ERR,
			    "yppasswdd: fdopen() on %s failed\n",
			    newshadowfile);
			goto cleanup;
		}
	}

	if (useadjunct) {
		if ((nadjfd = open(newadjunctfile, O_WRONLY | O_CREAT | O_EXCL,
		    adjstat.st_mode)) < 0) {
			if (errno == EEXIST) {
				syslog(LOG_WARNING,
				    "yppasswdd: adjunct file busy - try "
				    "again\n");
				ans = 8;
			} else {
				syslog(LOG_ERR, "yppasswdd: %s: %m",
				    newadjunctfile);
				ans = 9;
			}
			goto cleanup;
		}

		fchown(nadjfd, adjstat.st_uid, adjstat.st_gid);

		if ((nadjfp = fdopen(nadjfd, "w")) == NULL) {
			syslog(LOG_ERR,
			    "yppasswdd: fdopen() on %s failed\n",
			    newadjunctfile);
			goto cleanup;
		}
	}

	/*
	 * The following code may not seem all that elegant, but my
	 * interpretation of the man pages relating to the passwd and
	 * shadow files would seem to indicate that there is no guarantee
	 * that the entries contained in those files will be in the same
	 * order...
	 *
	 * So here's the high level overview:
	 *
	 *    Loop through the passwd file reading in lines and writing them
	 *    out to the new file UNTIL we get to the correct entry.
	 *    IF we have a shadow file, loop through it reading in lines and
	 *    writing them out to the new file UNTIL we get to the correct
	 *    entry. IF we have an adjunct file, loop through it reading in
	 *    lines and writing them out to the new file UNTIL we get to the
	 *    correct entry.
	 *
	 *    Figure out what's changing, contruct the new passwd, shadow,
	 *    and adjunct entries and spit em out to the temp files.
	 *    At this point, set the done flag and leap back into the loop(s)
	 *    until you're finished with the files and then leap to the
	 *    section that installs the new files.
	 */

loop_in_files:
	/* While we find things in the passwd file */
	while (fgets(pwbuf, NSS_LINELEN_PASSWD, opwfp)) {

		/*
		 * Is this the passwd entry we want?
		 * If not, then write it out to the new passwd temp file
		 * and remember our position.
		 */
		if (doneflag || strncmp(name, pwbuf, namelen)) {
			if (fputs(pwbuf, npwfp) == EOF) {
				syslog(LOG_ERR,
				    "yppasswdd: write to passwd file "
				    "failed.\n");
				goto cleanup;
			}
			pwpos = ftell(opwfp);
			continue;
		}
		gotpasswd = 1;
		break;
	}

	/* no match */
	if (!gotpasswd) {
		syslog(LOG_ERR, "yppasswdd: user %s does not exist\n", name);
		goto cleanup;
	}

	/* While we find things in the shadow file */
	while (useshadow && fgets(spbuf, NSS_LINELEN_SHADOW, ospfp)) {

		/*
		 * Is this the shadow entry that we want?
		 * If not, write it out to the new shadow temp file
		 * and remember our position.
		 */
		if (doneflag || strncmp(name, spbuf, namelen)) {
			if (fputs(spbuf, nspfp) == EOF) {
				syslog(LOG_ERR,
				    "yppasswdd: write to shadow file "
				    "failed.\n");
				goto cleanup;
			}
			sppos = ftell(ospfp);
			continue;
		}
		gotshadow = 1;
		break;
	}

	/* While we find things in the adjunct file */
	while (useadjunct && fgets(adjbuf, BUFSIZ, oadjfp)) {

		/*
		 * is this the adjunct entry that we want?
		 * If not, write it out to the new temp file
		 * and remember our position.
		 */
		if (doneflag || strncmp(name, adjbuf, namelen)) {
			if (fputs(adjbuf, nadjfp) == EOF) {
				syslog(LOG_ERR,
				    "yppasswdd: write to adjunct file "
				    "failed.\n");
				goto cleanup;
			}
			continue;
		}
		gotadjunct = 1;
		break;
	}

	if (doneflag)
		goto install_files;

	if (useshadow && !gotshadow) {
		syslog(LOG_ERR, "yppasswdd: no passwd in shadow for %s\n",
		    newpw.pw_name);
		ans = 4;
		goto cleanup;
	}
	if (useadjunct && !gotadjunct) {
		syslog(LOG_ERR, "yppasswdd: no passwd in adjunct for %s\n",
		    newpw.pw_name);
		ans = 4;
		goto cleanup;
	}

	/*
	 * Now that we've read in the correct passwd AND
	 * shadow lines, we'll rewind to the beginning of
	 * those lines and let the fget*ent() calls do
	 * the work.  Since we are only working with the
	 * first two fields of the adjunct entry, leave
	 * it as a char array.
	 */
	fseek(opwfp, pwpos, SEEK_SET);
	opwd  = *fgetpwent(opwfp);

	if (useshadow) {
		fseek(ospfp, sppos, SEEK_SET);
		ospwd = *fgetspent(ospfp);
	}

	oldpass_crypt = cryptoldpasswd(yppwd.oldpass, newpw.pw_passwd,
	    newpw.pw_name);
	if (oldpass_crypt == NULL) {
		ans = 3;
		goto cleanup;
	}
	p = newpw.pw_passwd;
	if ((!nopw) &&
	    p && *p &&
	    !((*p++ == '#') && (*p++ == '#') &&
	    (strcmp(p, opwd.pw_name) == 0)) &&
	    (strcmp(oldpass_crypt, newpw.pw_passwd) != 0))
		chpw = 1;
	oldpass_crypt = NULL;

	if ((!noshell) && (strcmp(opwd.pw_shell, newpw.pw_shell) != 0)) {
		if (single)
			chpw = 0;
		chsh = 1;
	}

	if ((!nogecos) && (strcmp(opwd.pw_gecos, newpw.pw_gecos) != 0)) {
		if (single) {
			chpw = 0;
			chsh = 0;
		}
		chgecos = 1;
	}

	if (!(chpw + chsh + chgecos)) {
		syslog(LOG_NOTICE, "yppasswdd: no change for %s\n",
		    newpw.pw_name);
		ans = 3;
		goto cleanup;
	}

	if (useshadow && !root_on_master) {
		oldpass_crypt = cryptoldpasswd(yppwd.oldpass, ospwd.sp_pwdp,
		    newpw.pw_name);
		if (oldpass_crypt == NULL)
			goto cleanup;
		if (ospwd.sp_pwdp && *ospwd.sp_pwdp &&
		    (strcmp(oldpass_crypt, ospwd.sp_pwdp) != 0)) {

			syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n",
			    newpw.pw_name);
			ans = 7;
			goto cleanup;
		}
	} else if (useadjunct) {
		/*
		 * Clear the adj_encrypt array.  Extract the encrypted passwd
		 * into adj_encrypt by setting adj_crypt_begin and
		 * adj_crypt_end to point at the first character of the
		 * encrypted passwd and the first character following the
		 * encrypted passwd in adjbuf, respectively, and copy the
		 * stuff between (there may not be anything) into adj_ecrypt.
		 * Then, check that adj_encrypt contains something and that
		 * the old passwd is correct.
		 */
		memset(adj_encrypt, 0, sizeof (adj_encrypt));
		adj_crypt_begin = adjbuf + namelen;
		adj_crypt_end = strchr(adj_crypt_begin, ':');
		strncpy(adj_encrypt, adj_crypt_begin,
		    adj_crypt_end - adj_crypt_begin);
		oldpass_crypt = cryptoldpasswd(yppwd.oldpass, adj_encrypt,
		    newpw.pw_name);
		if (oldpass_crypt == NULL)
			goto cleanup;
		if (!root_on_master && *adj_encrypt &&
		    (strcmp(oldpass_crypt, adj_encrypt) != 0)) {

			syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n",
			    newpw.pw_name);
			ans = 7;
			goto cleanup;
		}
	} else {
		oldpass_crypt = cryptoldpasswd(yppwd.oldpass, opwd.pw_passwd,
		    newpw.pw_name);
		if (oldpass_crypt == NULL)
			goto cleanup;
		if (!root_on_master && opwd.pw_passwd && *opwd.pw_passwd &&
		    (strcmp(oldpass_crypt, opwd.pw_passwd) != 0)) {

			syslog(LOG_NOTICE, "yppasswdd: passwd incorrect\n",
			    newpw.pw_name);
			ans = 7;
			goto cleanup;
		}
	}

#ifdef DEBUG
	printf("%d %d %d\n", chsh, chgecos, chpw);

	printf("%s %s %s\n",
	    yppwd.newpw.pw_shell,
	    yppwd.newpw.pw_gecos,
	    yppwd.newpw.pw_passwd);

	printf("%s %s %s\n",
	    opwd.pw_shell,
	    opwd.pw_gecos,
	    ospwd.sp_pwdp);
#endif

	if (chsh &&
	    !validloginshell(opwd.pw_shell, newpw.pw_shell, root_on_master)) {
		goto cleanup;
	}

	/* security hole fix from original source */
	for (p = newpw.pw_name; (*p != '\0'); p++)
		if ((*p == ':') || !(isprint(*p)))
			*p = '$';	/* you lose buckwheat */
	for (p = newpw.pw_passwd; (*p != '\0'); p++)
		if ((*p == ':') || !(isprint(*p)))
			*p = '$';	/* you lose buckwheat */

	if (chgecos)
		opwd.pw_gecos = newpw.pw_gecos;

	if (chsh)
		opwd.pw_shell = newpw.pw_shell;

	/*
	 * If we're changing the shell or gecos fields and we're
	 * using a shadow or adjunct file or not changing the passwd
	 * then go ahead and update the passwd file.  The case where
	 * the passwd is being changed and we are not using a shadow
	 * or adjunct file is handled later.
	 */
	if ((chsh || chgecos) && (useshadow || useadjunct || !chpw) &&
	    putpwent(&opwd, npwfp)) {

		syslog(LOG_ERR, "yppasswdd: putpwent failed: %s\n",
		    passwd_file);
		goto cleanup;
	}

	if (chpw) {
		if (useshadow) {
			ospwd.sp_pwdp = newpw.pw_passwd;
			now = DAY_NOW;
			/* password aging - bug for bug compatibility */
			if (ospwd.sp_max != -1) {
				if (now < ospwd.sp_lstchg + ospwd.sp_min) {
					syslog(LOG_ERR,
					    "yppasswdd: Sorry: < %ld days "
					    "since the last change.\n",
					    ospwd.sp_min);
					goto cleanup;
				}
			}
			ospwd.sp_lstchg = now;
			if (putspent(&ospwd, nspfp)) {
				syslog(LOG_ERR,
				    "yppasswdd: putspent failed: %s\n",
				    shadow_file);
				goto cleanup;
			}
		} else if (useadjunct) {
			sprintf(adjbuf_new,
			    "%s%s%s", name, newpw.pw_passwd, adj_crypt_end);
			if (fputs(adjbuf_new, nadjfp) == EOF) {
				syslog(LOG_ERR,
				    "yppasswdd: write to adjunct failed: %s\n",
				    adjunct_file);
				goto cleanup;
			}
		} else {
			opwd.pw_passwd = newpw.pw_passwd;
			if (putpwent(&opwd, npwfp)) {
				syslog(LOG_ERR,
				    "yppasswdd: putpwent failed: %s\n",
				    passwd_file);
				goto cleanup;
			}
		}
	}

	if (!doneflag) {
		doneflag = 1;
		goto loop_in_files;
	}

install_files:
	/*
	 * Critical section, nothing special needs to be done since we
	 * hold exclusive access to the *.ptmp files
	 */
	fflush(npwfp);
	if (useshadow)
		fflush(nspfp);
	if (useadjunct)
		fflush(nadjfp);

	strcpy(tmppasswdfile, passwd_file);
	strcat(tmppasswdfile, "-");
	if (useshadow) {
		strcpy(tmpshadowfile, shadow_file);
		strcat(tmpshadowfile, "-");
	}
	if (useadjunct) {
		strcpy(tmpadjunctfile, adjunct_file);
		strcat(tmpadjunctfile, "-");
	}

	if ((!useshadow && !useadjunct) || (chsh || chgecos)) {
		if (rename(passwd_file, tmppasswdfile) < 0) {
			syslog(LOG_CRIT, "yppasswdd: failed to backup "
			    "passwd file: %m");
			goto cleanup;
		} else {
			if (rename(newpasswdfile, passwd_file) < 0) {
				syslog(LOG_CRIT,
				    "yppasswdd: failed to mv passwd: %m");
				if (rename(tmppasswdfile, passwd_file) < 0) {
					syslog(LOG_CRIT,
					    "yppasswdd: failed to restore "
					    "backup of passwd file: %m");
				}
				goto cleanup;
			}
		}
	}

	if (useshadow && chpw) {
		if (rename(shadow_file, tmpshadowfile) < 0) {
			syslog(LOG_CRIT, "yppasswdd: failed to back up "
			    "shadow file: %m");
			if (rename(tmppasswdfile, passwd_file) < 0) {
				syslog(LOG_CRIT,
				    "yppasswdd: failed to restore "
				    "backup of passwd file: %m");
			}
			goto cleanup;
		} else {
			if (rename(newshadowfile, shadow_file) < 0) {
				syslog(LOG_CRIT,
				    "yppasswdd: failed to mv shadow: %m");
				if (rename(tmpshadowfile, shadow_file) < 0) {
					syslog(LOG_CRIT,
					    "yppasswdd: failed to restore "
					    "backup of shadow file: %m");
				}
				if (rename(tmppasswdfile, passwd_file) < 0) {
					syslog(LOG_CRIT,
					    "yppasswdd: failed to restore "
					    "backup of passwd file: %m");
				}
				goto cleanup;
			}
		}
	} else if (useadjunct && chpw) {
		if (rename(adjunct_file, tmpadjunctfile) < 0) {
			syslog(LOG_CRIT, "yppasswdd: failed to back up "
			    "adjunct file: %m");
			if (rename(tmppasswdfile, passwd_file) < 0) {
				syslog(LOG_CRIT,
				    "yppasswdd: failed to restore backup "
				    "of passwd: %m");
			}
			goto cleanup;
		} else {
			if (rename(newadjunctfile, adjunct_file) < 0) {
				syslog(LOG_CRIT,
				    "yppassdd: failed to mv adjunct: %m");
				if (rename(tmppasswdfile, passwd_file) < 0) {
					syslog(LOG_CRIT,
					    "yppasswdd: failed to restore "
					    "backup of passwd file: %m");
				}
				if (rename(tmpadjunctfile, adjunct_file) < 0) {
					syslog(LOG_CRIT,
					    "yppasswdd: failed to restore "
					    "backup of adjunct file: %m");
				}
				goto cleanup;
			}
		}
	}

	if (doneflag)
		ans = 0;
	/* End critical section */

	/*
	 *  Here we have come only after the new files have been successfully
	 * renamed to original files. At this point, the temp files would still
	 * be existing we need to remove them from the /etc directory
	 */
	unlink(tmppasswdfile);
	if (useshadow)
		unlink(tmpshadowfile);
	if (useadjunct)
		unlink(tmpadjunctfile);

cleanup:

	/* If we don't have opwfp, then we didn't do anything */
	if (opwfp) {
		fclose(opwfp);

		if (ospfp) {
			fclose(ospfp);
		}

		if (oadjfp) {
			fclose(oadjfp);
		}

		unlink(newpasswdfile);
		/* These tests are cheaper than failing syscalls */
		if (useshadow)
			unlink(newshadowfile);
		if (useadjunct)
			unlink(newadjunctfile);

		if (npwfp) {
			fclose(npwfp);

			if (nspfp) {
				fclose(nspfp);
			}
			if (nadjfp) {
				fclose(nadjfp);
			}
		}
	}

	ypulckpwdf();

	if (doneflag && mflag) {
		retval = fork();
		if (retval < 0) {
			syslog(LOG_ERR, "yppasswdd: Fork failed %m");
		} else if (retval == 0) {
			strcpy(cmdbuf, "/usr/ccs/bin/make");
			for (i = Mstart + 1; i < Argc; i++) {
				strcat(cmdbuf, " ");
				strcat(cmdbuf, Argv[i]);
			}

#ifdef DEBUG
			syslog(LOG_ERR, "yppasswdd: about to "
			    "execute %s\n", cmdbuf);
#else
			if (yplckpwdf() < 0) {
				syslog(LOG_ERR, "yppasswdd: Couldn't get the "
				    "lock to update the maps");
			} else {
				setpgrp();
				system(cmdbuf);
				ypulckpwdf();
			}
#endif
			exit(0);
		}
	}

	sigaction(SIGHUP,  &osa1, (struct sigaction *)0);
	sigaction(SIGINT,  &osa2, (struct sigaction *)0);
	sigaction(SIGQUIT, &osa3, (struct sigaction *)0);

	if (!svc_sendreply(transp, xdr_int, (char *)&ans))
		syslog(LOG_WARNING,
		    "yppasswdd: couldn\'t reply to RPC call\n");
}
Esempio n. 12
0
// {{{ user_add()
/// Create a valid user account
void user_add(user_t *o, char *username, volatile char *passwd)
{
   o->error[0]=0;

   struct passwd p;
   struct passwd *pw;
   struct spwd sp;
   FILE *f; 
   int min = 1000;
   int max = 65000;
   char home[256];

   snprintf(home, sizeof(home), "/home/%s", username);

   p.pw_name = (char *)username;
   p.pw_passwd = "x";
   p.pw_uid = USER_DEFAULT_ID;
   p.pw_gid = USER_GROUP_ID;
   p.pw_gecos = "OpenDomo User";
   p.pw_dir = home;
   p.pw_shell = "/bin/sh";


   f = fopen("/etc/passwd", "r");

   /* check user and get valid id */
   while ((pw = fgetpwent(f))) 
   {
      if (strcmp(pw->pw_name, p.pw_name) == 0) 
      {
         sstrncpy(o->error, "user_add(): user exists", USER_ERROR_SIZE);
         return;
      }

      if ((pw->pw_uid >= p.pw_uid) && (pw->pw_uid < max)
            && (pw->pw_uid >= min)) 
      {
         p.pw_uid = pw->pw_uid + 1;
      }
   }

   fclose(f);

   f = fopen("/etc/passwd", "a+");
   if(!f)
   {
      sstrncpy(o->error, "user_add(): cannot open /etc/passwd",USER_ERROR_SIZE);
      return;
   }


   /* add to passwd */
   if (putpwent(&p, f) == -1) 
   {
      sstrncpy(o->error, "user_add(): putpwent() error", USER_ERROR_SIZE);
      return;
   }

   fclose(f);


   /* salt */
   struct timeval tv;
   static char salt[40];

   salt[0] = '\0';

   gettimeofday (&tv, (struct timezone *) 0);
   strcat(salt, l64a (tv.tv_usec));
   strcat(salt, l64a (tv.tv_sec + getpid () + clock ()));

   if (strlen (salt) > 3 + 8)  
      salt[11] = '\0';


   /* shadow */
   sp.sp_namp = p.pw_name;
   sp.sp_pwdp = (char*)crypt((const char*)passwd, salt);
   sp.sp_min = 0;
   sp.sp_max = (10000L * DAY) / SCALE;
   sp.sp_lstchg = time((time_t *) 0) / SCALE;
   sp.sp_warn = -1;
   sp.sp_expire = -1;
   sp.sp_inact = -1;
   sp.sp_flag = -1;


   /* add to shadow */
   f = fopen("/etc/shadow", "a+");
   if(!f)
   {
      sstrncpy(o->error, "user_add(): cannot open /etc/shadow",USER_ERROR_SIZE);
      return;
   }

   if (putspent(&sp, f) == -1) 
   {
      sstrncpy(o->error, "user_add(): putspent() error",USER_ERROR_SIZE);
      return;
   }

   fclose(f);

   /* Create home */
   mkdir(home, 0700);  
   chown(home, p.pw_uid, USER_GROUP_ID);
}
Esempio n. 13
0
bool KUserFiles::savesdw()
{
#ifdef HAVE_SHADOW
  bool addok = false;
  QString tmp;
  FILE *f;
  struct spwd *spwp;
  struct spwd s;
  KU::KUser *up;
  QString shadow_file = mCfg->shadowsrc();
  QString new_shadow_file = shadow_file+QString::fromLatin1(KU_CREATE_EXT);

  if ( shadow_file.isEmpty() )
    return TRUE;

  if (!s_backuped) {
    if (!backup(shadow_file)) return FALSE;
    s_backuped = TRUE;
  }

  if ((f = fopen(QFile::encodeName(new_shadow_file), "w")) == NULL) {
    KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(new_shadow_file) );
    return FALSE;
  }

  s.sp_namp = (char *)malloc(200);
  s.sp_pwdp = (char *)malloc(200);

  QPtrListIterator<KU::KUser> it( mUsers );
  up = (*it);
  while (true) {

    if ( up == 0 ) {
      if ( addok ) break;
      it = QPtrListIterator<KU::KUser> ( mAdd );
      up = (*it);
      addok = true;
      if ( up == 0 ) break;
    };

    if ( mDel.containsRef( up ) ) {
      ++it;
      up = (*it);
      continue;
    }
    if ( mMod.contains( up ) ) up = &( mMod[ up ] );

    strncpy( s.sp_namp, up->getName().local8Bit(), 200 );
    if ( up->getDisabled() )
      strncpy( s.sp_pwdp, QString("!!" + up->getSPwd()).local8Bit(), 200 );
    else
      strncpy( s.sp_pwdp, up->getSPwd().local8Bit(), 200 );

    s.sp_lstchg = timeToDays( up->getLastChange() );
    s.sp_min    = up->getMin();
    s.sp_max    = up->getMax();
#ifndef _SCO_DS
    s.sp_warn   = up->getWarn();
    s.sp_inact  = up->getInactive();
    s.sp_expire = timeToDays( up->getExpire() );
    s.sp_flag   = up->getFlag();
#endif
    spwp = &s;
    putspent(spwp, f);

    ++it;
    up = (*it);
  }
  fclose(f);

  chmod(QFile::encodeName(new_shadow_file), sdw_mode);
  chown(QFile::encodeName(new_shadow_file), sdw_uid, sdw_gid);
  rename(QFile::encodeName(new_shadow_file),
    QFile::encodeName(shadow_file));

  free(s.sp_namp);
  free(s.sp_pwdp);
#endif // HAVE_SHADOW
  return TRUE;
}