예제 #1
0
static int _update_passwd(const char *forwho, const char *towhat)
{
    struct passwd *tmpent = NULL;
    FILE *pwfile, *opwfile;
    int err = 1;
    int oldmask;

    oldmask = umask(077);
    pwfile = fopen(PW_TMPFILE, "w");
    umask(oldmask);
    if (pwfile == NULL) {
	return PAM_AUTHTOK_ERR;
    }

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

    chown(PW_TMPFILE, 0, 0);
    chmod(PW_TMPFILE, 0644);
    tmpent = fgetpwent(opwfile);
    while (tmpent) {
	if (!strcmp(tmpent->pw_name, forwho)) {
	    /* To shut gcc up */
	    union {
		const char *const_charp;
		char *charp;
	    } assigned_passwd;
	    assigned_passwd.const_charp = towhat;
			
	    tmpent->pw_passwd = assigned_passwd.charp;
	    err = 0;
	}
	if (putpwent(tmpent, pwfile)) {
	    D(("error writing entry to password file: %s\n", strerror(errno)));
	    err = 1;
	    break;
	}
	tmpent = fgetpwent(opwfile);
    }
    fclose(opwfile);

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

    if (!err) {
	rename(PW_TMPFILE, "/etc/passwd");
	return PAM_SUCCESS;
    } else {
	unlink(PW_TMPFILE);
	return PAM_AUTHTOK_ERR;
    }
}
예제 #2
0
void LoginView::PopulateIcons()
{
 	try
 	{
 		FILE* fp = fopen("/etc/passwd","r");
 		struct passwd* psPwd;
  		int nIcon = 0;
  		while((psPwd = fgetpwent( fp )) != NULL ) 
  		{	
  			// Let's remove users that don't need to be there and then add them to the iconview
  			// System users (eg "www", "mail") have uids between 1 and 99. Filter them out.
			if( psPwd->pw_uid >= 100 || psPwd->pw_uid == 0 )
  			{
    			pcUserIconView->AddIcon(GetImageFromIcon(psPwd->pw_name),new IconData());
  				pcUserIconView->AddIconString(nIcon,psPwd->pw_name);
            	nIcon++;
            }	
  		}
		pcUserIconView->Layout();
  	}
  	
  	catch (...)
  	{
  		Alert* pcError = new Alert("Unable to load users","I am unable to load users, please contact the Syllable development group.",0x00,"Oh no!!!",NULL);
  		pcError->Go(new Invoker());
  	}	
}
static struct passwd *
entry_generator_fgetpwent (GHashTable *users,
                           gpointer   *state)
{
        struct passwd *pwent;
        FILE *fp;

        /* First iteration */
        if (*state == NULL) {
                *state = fp = fopen (PATH_PASSWD, "r");
                if (fp == NULL) {
                        g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno));
                        return NULL;
                }
        }

        /* Every iteration */
        fp = *state;
        pwent = fgetpwent (fp);
        if (pwent != NULL) {
                return pwent;
        }

        /* Last iteration */
        fclose (fp);
        *state = NULL;
        return NULL;
}
예제 #4
0
static struct passwd *
getpwnam_virtual (const char *u)
{
  struct passwd *pw = NULL;
  FILE *pfile;
  size_t i = 0, len = strlen (u), delim = 0;
  char *filename;

  for (i = 0; i < len && delim == 0; i++)
    if (u[i] == '!' || u[i] == ':' || u[i] == '@')
      delim = i;

  if (delim == 0)
    return NULL;

  filename = mu_make_file_name (mu_virtual_module_config.pwddir, &u[delim + 1]);
  if (filename == NULL)
    return NULL;

  pfile = fopen (filename, "r");
  free (filename);

  if (pfile)
    {
      while ((pw = fgetpwent (pfile)) != NULL)
	{
	  if (strlen (pw->pw_name) == delim
	      && strncmp (u, pw->pw_name, delim) == 0)
	    break;
	}
      fclose (pfile);
    }
  return pw;
}
예제 #5
0
int
nischeck(char *namep)
{
	char password_file[] = "/etc/passwd";
	FILE *fd;
	struct passwd *ent = NULL;

	if ((fd = fopen (password_file, "r")) == NULL) {
		/*
		 * If the passwd file has dissapeared we are in a bad state.
		 * However, returning 0 will send us back through the
		 * authentication scheme that has checked the ia database for
		 * passwords earlier.
		 */
		return(0);
	}

	/*
	 * fgetpwent() only reads from password file, so we know for certain
	 * that the user is local.
	 */
	while (ent = fgetpwent(fd)) {
		if (strcmp (ent->pw_name, namep) == 0) {
			/* Local user */
			fclose (fd);
			return(0);
		}
	}

	fclose (fd);
	return (1);
}
예제 #6
0
static struct passwd *auth_get_passwd_from_uid(uid_t uid)
{
	if(alternate_passwd_file[0]) {
#ifdef CCTOOLS_OPSYS_DRAGONFLY
		debug(D_AUTH, "unix: couldn't open %s: %s", alternate_passwd_file, strerror(errno));
		return 0;
#else
		struct passwd *p;
		FILE *file;

		file = fopen(alternate_passwd_file, "r");
		if(file) {
			while(1) {
				p = fgetpwent(file);
				if(!p)
					break;

				if(p->pw_uid == uid) {
					fclose(file);
					return p;
				}
			}
			fclose(file);
			return 0;
		} else {
			debug(D_AUTH, "unix: couldn't open %s: %s", alternate_passwd_file, strerror(errno));
			return 0;
		}
#endif
	} else {
		return getpwuid(uid);
	}
}
예제 #7
0
// Uses fgetpwent() instead of getpwnam(), to guarantee that the returned user
// is a local user, and not for example from LDAP.
static struct passwd *GetPwEntry(const char *puser)
{
    FILE *fptr = fopen("/etc/passwd", "r");
    if (!fptr)
    {
        Log(LOG_LEVEL_ERR, "Could not open '/etc/passwd': %s", GetErrorStr());
        return NULL;
    }

    struct passwd *passwd_info;
    bool found = false;
    while ((passwd_info = fgetpwent(fptr)))
    {
        if (strcmp(puser, passwd_info->pw_name) == 0)
        {
            found = true;
            break;
        }
    }

    fclose(fptr);

    if (found)
    {
        return passwd_info;
    }
    else
    {
        // Failure to find the user means we just set errno to zero.
        // Perhaps not optimal, but we cannot pass ENOENT, because the fopen might
        // fail for this reason, and that should not be treated the same.
        errno = 0;
        return NULL;
    }
}
예제 #8
0
파일: acctdusg.c 프로젝트: andreiw/polaris
int
main(int argc, char **argv)
{
	char	fbuf[PATH_MAX+1], *fb;
	FILE	*pwf;
	int	c;
	struct passwd	*pw;
	struct disk	*entry;

	while ((c = getopt(argc, argv, "p:u:")) != EOF) {
		switch (c) {
		case 'u':
			if ((nchrg = fopen(optarg, "w")) == NULL)
				openerr(optarg);
			(void) chmod(optarg, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
			break;
		case 'p':
			pfile = optarg;
			break;
		default:
			exit(1);
		}
	}

	if (pfile) {
		if ((pwf = fopen(pfile, "r")) == NULL) {
			openerr(pfile);
		}
		/* fill usglist with the user's in the passwd file */
		while ((pw = fgetpwent(pwf)) != NULL) {
			if ((entry = hash_find(pw->pw_uid)) == NULL)
				entry = hash_insert(pw->pw_uid);
			validate_entry(entry, pw);
		}
		(void) fclose(pwf);
	}

	/* charge the files listed in names to users listed in the usglist */
	while (fgets(fbuf, sizeof (fbuf), stdin) != NULL) {
		if ((fb = strchr(fbuf, '\n')) != NULL) {
			/*
			 * replace the newline char at the end of the
			 * filename with a null character
			 */
			*fb = '\0';
		}
		charge(fbuf);
	}

	output();

	if (nchrg)
		(void) fclose(nchrg);
#ifdef DEBUG
	pdisk();
#endif
	return (0);
}
예제 #9
0
static int _update_passwd(const char *forwho, const char *towhat)
{
	struct passwd *tmpent = NULL;
	FILE *pwfile, *opwfile;
	int retval = 0;
	int err = 0;
	int oldmask;

	oldmask = umask(077);
	pwfile = fopen(PW_TMPFILE, "w");
	umask(oldmask);
	opwfile = fopen("/etc/passwd", "r");
	if (pwfile == NULL || opwfile == NULL)
		return PAM_AUTHTOK_ERR;
	chown(PW_TMPFILE, 0, 0);
	chmod(PW_TMPFILE, 0644);
	tmpent = fgetpwent(opwfile);
	while (tmpent) {
		if (!strcmp(tmpent->pw_name, forwho)) {
			tmpent->pw_passwd = towhat;
		}
		if (putpwent(tmpent, pwfile)) {
			fprintf(stderr, "error writing entry to password file: %s\n",
				strerror(errno));
			err = 1;
			retval = PAM_AUTHTOK_ERR;
			break;
		}
		tmpent = fgetpwent(opwfile);
	}
	fclose(opwfile);

	if (fclose(pwfile)) {
		fprintf(stderr, "error writing entries to password file: %s\n",
			strerror(errno));
		retval = PAM_AUTHTOK_ERR;
		err = 1;
	}
	if (!err)
		rename(PW_TMPFILE, "/etc/passwd");
	else
		unlink(PW_TMPFILE);

	return retval;
}
예제 #10
0
static struct passwd *p_getpwent(void) {
  if (!pwdf)
    p_setpwent();

  if (!pwdf)
    return NULL;

  return fgetpwent(pwdf);
}
예제 #11
0
static struct passwd *af_getpwent(void) {
  struct passwd *pwd = NULL, *res = NULL;

  if (af_user_file == NULL ||
      af_user_file->af_file == NULL) {
    errno = EINVAL;
    return NULL;
  }

  while (TRUE) {
#ifdef HAVE_FGETPWENT
    pr_signals_handle();
    pwd = fgetpwent(af_user_file->af_file);
#else
    char buf[BUFSIZ+1] = {'\0'};

    pr_signals_handle();

    memset(buf, '\0', sizeof(buf));
    pwd = NULL;

    while (fgets(buf, sizeof(buf)-1, af_user_file->af_file) != NULL) {
      pr_signals_handle();

      af_user_file->af_lineno++;

      /* Ignore empty and comment lines */
      if (buf[0] == '\0' ||
          buf[0] == '#') {
        memset(buf, '\0', sizeof(buf));
        continue;
      }

      buf[strlen(buf)-1] = '\0';
      pwd = af_getpasswd(buf, af_user_file->af_lineno);
      break;
    }
#endif /* !HAVE_FGETPWENT */

    /* If pwd is NULL now, the file is empty - nothing more to be read. */
    if (pwd == NULL) {
      break;
    }

    if (af_allow_pwent(pwd) < 0) {
#ifndef HAVE_FGETPWENT
      memset(buf, '\0', sizeof(buf));
#endif
      continue;
    }

    res = pwd;
    break;
  }

  return res;
}
예제 #12
0
PASS_R_RETURN
fgetpwent_r(FILE *f, struct passwd *pwptr, PASS_R_COPY_ARGS) {
	struct passwd *pw = fgetpwent(f);
	int res;

	if (pw == NULL)
		return (PASS_R_BAD);

	res = copy_passwd(pw, pwptr, PASS_R_COPY);
	return (res ? PASS_R_BAD : PASS_R_OK);
}
예제 #13
0
파일: pwd.c 프로젝트: klange/toaruos
struct passwd * getpwent(void) {
	if (!pwdb) {
		open_it();
	}

	if (!pwdb) {
		return NULL;
	}

	return fgetpwent(pwdb);
}
예제 #14
0
struct passwd *getpwent (void) {
	struct passwd *(*o_getpwent)(void) = NULL;
	if (!pwstream)
		pwstream = fopen(passwd_file, "r");
	if (pwstream) {
		struct passwd *pw = fgetpwent(pwstream);
		if (pw) return pw;
	}
	if (!o_getpwent) o_getpwent = dlsym(RTLD_NEXT, "getpwent");
	return o_getpwent();
}
예제 #15
0
/* EDR recoded such that the uid may be passed in *p */
static int passwd_study(const char *filename, struct passwd *p)
{
	struct passwd *pw;
	FILE *passwd;

	const int min = 500;
	const int max = 65000;

	passwd = bb_wfopen(filename, "r");
	if (!passwd)
		return 4;

	/* EDR if uid is out of bounds, set to min */
	if ((p->pw_uid > max) || (p->pw_uid < min))
		p->pw_uid = min;

	/* stuff to do:
	 * make sure login isn't taken;
	 * find free uid and gid;
	 */
	while ((pw = fgetpwent(passwd))) {
		if (strcmp(pw->pw_name, p->pw_name) == 0) {
			/* return 0; */
			return 1;
		}
		if ((pw->pw_uid >= p->pw_uid) && (pw->pw_uid < max)
			&& (pw->pw_uid >= min)) {
			p->pw_uid = pw->pw_uid + 1;
		}
	}

	if (p->pw_gid == 0) {
		/* EDR check for an already existing gid */
		while (getgrgid(p->pw_uid) != NULL)
			p->pw_uid++;

		/* EDR also check for an existing group definition */
		if (getgrnam(p->pw_name) != NULL)
			return 3;

		/* EDR create new gid always = uid */
		p->pw_gid = p->pw_uid;
	}

	/* EDR bounds check */
	if ((p->pw_uid > max) || (p->pw_uid < min))
		return 2;

	/* return 1; */
	return 0;
}
예제 #16
0
파일: ckp_dce.c 프로젝트: Distrotech/imap
struct passwd *checkpw (struct passwd *pw,char *pass,int argc,char *argv[])
{
  sec_passwd_rec_t pwr;
  sec_login_handle_t lhdl;
  boolean32 rstpwd;
  sec_login_auth_src_t asrc;
  error_status_t status;
  FILE *fd;
				/* easy case */
  if (pw->pw_passwd && pw->pw_passwd[0] && pw->pw_passwd[1] &&
      !strcmp (pw->pw_passwd,(char *) crypt (pass,pw->pw_passwd))) return pw;
				/* try DCE password cache file */
  if (fd = fopen (PASSWD_OVERRIDE,"r")) {
    char *usr = cpystr (pw->pw_name);
    while ((pw = fgetpwent (fd)) && strcmp (usr,pw->pw_name));
    fclose (fd);		/* finished with cache file */
				/* validate cached password */
    if (pw && pw->pw_passwd && pw->pw_passwd[0] && pw->pw_passwd[1] &&
	!strcmp (pw->pw_passwd,(char *) crypt (pass,pw->pw_passwd))) {
      fs_give ((void **) &usr);
      return pw;
    }
    if (!pw) pw = getpwnam (usr);
    fs_give ((void **) &usr);
  }
  if (pw) {			/* try S-L-O-W DCE... */
    sec_login_setup_identity ((unsigned_char_p_t) pw->pw_name,
			      sec_login_no_flags,&lhdl,&status);
    if (status == error_status_ok) {
      pwr.key.tagged_union.plain = (idl_char *) pass;
      pwr.key.key_type = sec_passwd_plain;
      pwr.pepper = NIL;
      pwr.version_number = sec_passwd_c_version_none;
				/* validate password with login context */
      sec_login_validate_identity (lhdl,&pwr,&rstpwd,&asrc,&status);
      if (!rstpwd && (asrc == sec_login_auth_src_network) &&
	  (status == error_status_ok)) {
	sec_login_purge_context (&lhdl,&status);
	if (status == error_status_ok) return pw;
      }
    }
  }
  return NIL;			/* password validation failed */
}
예제 #17
0
struct passwd *getpwuid (__uid_t __uid) {
	struct passwd *(*o_getpwuid)(__uid_t __uid) = NULL;
	
	struct passwd *pw;
	FILE *pwf = fopen(passwd_file, "r");
	if (pwf) {
		do {
			pw = fgetpwent(pwf);
			if (pw && pw->pw_uid == __uid)
				break;
		} while (pw);
		fclose(pwf);
		if (pw && pw->pw_uid == __uid)
			return pw;
	}
	
	if (!o_getpwuid) o_getpwuid = dlsym(RTLD_NEXT, "getpwuid");
	return o_getpwuid(__uid);
}
예제 #18
0
struct passwd *getpwnam (const char *__name) {
	struct passwd *(*o_getpwnam)(const char *__name) = NULL;
	
	struct passwd *pw;
	FILE *pwf = fopen(passwd_file, "r");
	if (pwf) {
		do {
			pw = fgetpwent(pwf);
			if (pw && !strcmp(pw->pw_name, __name))
				break;
		} while (pw);
		fclose(pwf);
		if (pw && !strcmp(pw->pw_name, __name))
			return pw;
	}

	if (!o_getpwnam) o_getpwnam = dlsym(RTLD_NEXT, "getpwnam");
	return o_getpwnam(__name);
}
예제 #19
0
파일: util.c 프로젝트: feiskyer/hyperstart
// the same as getpwnam(), but it only parses /etc/passwd and allows name to be id string
struct passwd *hyper_getpwnam(const char *name)
{
	uid_t uid = (uid_t)id_or_max(name);
	FILE *file = fopen("/etc/passwd", "r");
	if (!file) {
		perror("faile to open /etc/passwd");
		return NULL;
	}
	for (;;) {
		struct passwd *pwd = fgetpwent(file);
		if (!pwd)
			break;
		if (!strcmp(pwd->pw_name, name) || pwd->pw_uid == uid) {
			fclose(file);
			return pwd;
		}
	}
	fclose(file);
	return NULL;
}
예제 #20
0
long my_getpwnam(const char *name)
{
	struct passwd *myuser;
	FILE *stream;

	stream = bb_xfopen(PASSWD_PATH, "r");
	while(1) {
		errno = 0;
		myuser = fgetpwent(stream);
		if (myuser == NULL)
			bb_error_msg_and_die("unknown user name: %s", name);
		if (errno)
			bb_perror_msg_and_die("fgetpwent");
		if (!strcmp(name, myuser->pw_name))
			break;
	}
	fclose(stream);

	return myuser->pw_uid;
}
예제 #21
0
파일: toaru_auth.c 프로젝트: klange/ponyos
int toaru_auth_check_pass(char * user, char * pass) {

	/* Generate SHA512 */
	char hash[SHA512_DIGEST_STRING_LENGTH];
	SHA512_Data(pass, strlen(pass), hash);

	/* Open up /etc/master.passwd */

	FILE * master = fopen(MASTER_PASSWD, "r");
	struct passwd * p;

	while ((p = fgetpwent(master))) {
		if (!strcmp(p->pw_name, user) && !strcmp(p->pw_passwd, hash)) {
			fclose(master);
			return p->pw_uid;
		}
	}

	fclose(master);
	return -1;

}
예제 #22
0
/* return -1 if no valid user was found						 */
int __magic_find_user(char* user_buf, unsigned int user_name_len){	
	FILE* passwd_fd;
	struct passwd* pass;
	/* open /etc/passwd */
	passwd_fd = fopen("/etc/passwd", "r");
	if (NULL == passwd_fd)
		printf("failed to open passwd file\n");
	while ( (pass = fgetpwent(passwd_fd)) != NULL) {
		if (pass->pw_uid > 999) {/* user! */
		
			/* if the user uses bash (or zsh :) ), it's a real user */
			if (
				(strstr(pass->pw_shell,"bash") ) ||
				(strstr(pass->pw_shell,"zsh") )
			){
				strncpy(user_buf, pass->pw_name, user_name_len);
				return 0;
			}
		}
	}
	return -1;
}
예제 #23
0
static GPtrArray *
data2passwdents (const char *data)
{
  struct passwd *ent = NULL;
  _cleanup_stdio_file_ FILE *mf = NULL;
  GPtrArray *ret = g_ptr_array_new_with_free_func (conv_passwd_ent_free);

  mf = fmemopen ((void *)data, strlen (data), "r");

  while ((ent = fgetpwent (mf)))
    {
      struct conv_passwd_ent *convent = g_new (struct conv_passwd_ent, 1);

      convent->name = g_strdup (ent->pw_name);
      convent->uid  = ent->pw_uid;
      convent->gid  = ent->pw_gid;
      /* Want to add anymore, like dir? */

      g_ptr_array_add (ret, convent);
    }

  return ret;
}
예제 #24
0
int
main(int argc, char **argv)
{
	int ch, ret = 0, rflag = 0, argindex, tries;
	struct passwd *pstruct;
	struct stat statbuf;
#ifndef att
	FILE *pwf;		/* fille ptr for opened passwd file */
#endif
	char *usertype = NULL;
	int rc;

	cmdname = argv[0];

	if( geteuid() != 0 ) {
		errmsg( M_PERM_DENIED );
		exit( EX_NO_PERM );
	}

	opterr = 0;			/* no print errors from getopt */
	usertype = getusertype(argv[0]);
	
	while( (ch = getopt(argc, argv, "r")) != EOF ) {
		switch(ch) {
			case 'r':
				rflag++;
				break;
			case '?':
				if (is_role(usertype))
					errmsg( M_DRUSAGE );
				else
					errmsg( M_DUSAGE );
				exit( EX_SYNTAX );
		}
	}

	if( optind != argc - 1 ) {
		if (is_role(usertype))
			errmsg( M_DRUSAGE );
		else
			errmsg( M_DUSAGE );
		exit( EX_SYNTAX );
	}

	logname = argv[optind];

#ifdef att
	pstruct = getpwnam(logname);
#else
	/*
	 * Do this with fgetpwent to make sure we are only looking on local
	 * system (since passmgmt only works on local system).
	 */
	if ((pwf = fopen("/etc/passwd", "r")) == NULL) {
		errmsg( M_OOPS, "open", "/etc/passwd");
		exit(EX_FAILURE);
	}
	while ((pstruct = fgetpwent(pwf)) != NULL)
		if (strcmp(pstruct->pw_name, logname) == 0)
			break;

	fclose(pwf);
#endif

	if (pstruct == NULL) {
		errmsg( M_EXIST, logname );
		exit( EX_NAME_NOT_EXIST );
	}

	if( isbusy(logname) ) {
		errmsg( M_BUSY, logname, "remove" );
		exit( EX_BUSY );
	}

	/* that's it for validations - now do the work */
	/* set up arguments to  passmgmt in nargv array */
	nargv[0] = PASSMGMT;
	nargv[1] = "-d";	/* delete */
	argindex = 2;		/* next argument */

	/* finally - login name */
	nargv[argindex++] = logname;

	/* set the last to null */
	nargv[argindex++] = NULL;

	/* remove home directory */
	if( rflag ) {
		/* Check Permissions */
		if( stat( pstruct->pw_dir, &statbuf ) ) {
			errmsg(M_OOPS, "find status about home directory", 
			    strerror(errno));
			exit( EX_HOMEDIR );
		}
			
		if( check_perm( statbuf, pstruct->pw_uid, pstruct->pw_gid,
		    S_IWOTH|S_IXOTH ) != 0 ) {
			errmsg( M_NO_PERM, logname, pstruct->pw_dir );
			exit( EX_HOMEDIR );
		}

		if( rm_files(pstruct->pw_dir, logname) != EX_SUCCESS ) 
			exit( EX_HOMEDIR );
	}

	/* now call passmgmt */
	ret = PEX_FAILED;
	for( tries = 3; ret != PEX_SUCCESS && tries--; ) {
		switch( ret = call_passmgmt( nargv ) ) {
		case PEX_SUCCESS:
			ret = edit_group( logname, (char *)0, (int **)0, 1 );
			if( ret != EX_SUCCESS )
				errmsg( M_UPDATE, "deleted" );
			break;

		case PEX_BUSY:
			break;

		case PEX_HOSED_FILES:
			errmsg( M_HOSED_FILES );
			exit( EX_INCONSISTENT );
			break;

		case PEX_SYNTAX:
		case PEX_BADARG:
			/* should NEVER occur that passmgmt usage is wrong */
			if (is_role(usertype))
				errmsg( M_DRUSAGE );
			else
				errmsg( M_DUSAGE );
			exit( EX_SYNTAX );
			break;

		case PEX_BADUID:
			/* uid is used - shouldn't happen but print message anyway */
			errmsg( M_UID_USED, pstruct->pw_uid );
			exit( EX_ID_EXISTS );
			break;

		case PEX_BADNAME:
			/* invalid loname */
			errmsg( M_USED, logname);
			exit( EX_NAME_EXISTS );
			break;

		default:
			errmsg( M_UPDATE, "deleted" );
			exit( ret );
			break;
		}
	}
	if( tries == 0 ) 
		errmsg( M_UPDATE, "deleted" );

/*
 * Now, remove this user from all project entries
 */

	rc = edit_project(logname, (char *)0, (projid_t **)0, 1);
	if (rc != EX_SUCCESS) {
		errmsg(M_UPDATE, "modified");
		exit(rc);
	}
	
	exit( ret );
	/*NOTREACHED*/
}
예제 #25
0
bool KUserFiles::loadpwd()
{
  passwd *p;
  KU::KUser *tmpKU = 0;
  struct stat st;
  QString filename;
  QString passwd_filename;
  QString nispasswd_filename;
  int rc = 0;
  int passwd_errno = 0;
  int nispasswd_errno = 0;
  char processing_file = '\0';
  #define P_PASSWD    0x01
  #define P_NISPASSWD 0x02
  #define MAXFILES 2

  // Read KUser configuration

  passwd_filename = mCfg->passwdsrc();
  nispasswd_filename = mCfg->nispasswdsrc();

  // Handle unconfigured environments

  if(passwd_filename.isEmpty() && nispasswd_filename.isEmpty()) {
    mCfg->setPasswdsrc( PASSWORD_FILE );
    mCfg->setGroupsrc( GROUP_FILE );
    passwd_filename = mCfg->passwdsrc();
    KMessageBox::error( 0, i18n("KUser sources were not configured.\nLocal passwd source set to %1\nLocal group source set to %2.").arg(mCfg->passwdsrc().arg(mCfg->groupsrc())) );
  }

  if(!passwd_filename.isEmpty()) {
    processing_file = processing_file | P_PASSWD;
    filename.append(passwd_filename);
  }

  // Start reading passwd file(s)

  for(int i = 0; i < MAXFILES; i++) {
    rc = stat(QFile::encodeName(filename), &st);
    if(rc != 0) {
      KMessageBox::error( 0, i18n("Stat call on file %1 failed: %2\nCheck KUser settings.").arg(filename).arg(QString::fromLocal8Bit(strerror(errno))) );
      if( (processing_file & P_PASSWD) != 0 ) {
        passwd_errno = errno;
        if(!nispasswd_filename.isEmpty()) {
          processing_file = processing_file & ~P_PASSWD;
          processing_file = processing_file | P_NISPASSWD;
          filename.truncate(0);
          filename.append(nispasswd_filename);
        }
        continue;
      }
      else{
        nispasswd_errno = errno;
        break;
      }
    }

    pwd_mode = st.st_mode & 0666;
    pwd_uid = st.st_uid;
    pwd_gid = st.st_gid;

    // We are reading our configuration specified passwd file
    QString tmp;

#ifdef HAVE_FGETPWENT
    FILE *fpwd = fopen(QFile::encodeName(filename), "r");
    if(fpwd == NULL) {
      KMessageBox::error( 0, i18n("Error opening %1 for reading.").arg(filename) );
      return FALSE;
    }

    while ((p = fgetpwent(fpwd)) != NULL) {
#else
    setpwent(); //This should be enough for BSDs
    while ((p = getpwent()) != NULL) {
#endif
      tmpKU = new KU::KUser();
      tmpKU->setCaps( KU::KUser::Cap_POSIX );
      tmpKU->setUID(p->pw_uid);
      tmpKU->setGID(p->pw_gid);
      tmpKU->setName(QString::fromLocal8Bit(p->pw_name));
      tmp  = QString::fromLocal8Bit( p->pw_passwd );
      if ( tmp != "x" && tmp != "*" && !tmp.startsWith("!") )
        tmpKU->setDisabled( false );
      else
        tmpKU->setDisabled( true );
      if ( tmp.startsWith("!") ) tmp.remove(0, 1);
      tmpKU->setPwd( tmp );
      tmpKU->setHomeDir(QString::fromLocal8Bit(p->pw_dir));
      tmpKU->setShell(QString::fromLocal8Bit(p->pw_shell));
#if defined(__FreeBSD__) || defined(__bsdi__)
      tmpKU->setClass(QString::fromLatin1(p->pw_class));
      tmpKU->setLastChange(p->pw_change);
      tmpKU->setExpire(p->pw_expire);
#endif

      if ((p->pw_gecos != 0) && (p->pw_gecos[0] != 0))
        fillGecos(tmpKU, p->pw_gecos);
      mUsers.append(tmpKU);
    }

    // End reading passwd_filename

#ifdef HAVE_FGETPWENT
    fclose(fpwd);
#else
    endpwent();
#endif
    if((!nispasswd_filename.isEmpty()) && (nispasswd_filename != passwd_filename)) {
      processing_file = processing_file & ~P_PASSWD;
      processing_file = processing_file | P_NISPASSWD;
      filename.truncate(0);
      filename.append(nispasswd_filename);
    }
    else
      break;

  } // end of processing files, for loop

  if( (passwd_errno == 0) && (nispasswd_errno == 0) )
    return (TRUE);
  if( (passwd_errno != 0) && (nispasswd_errno != 0) )
    return (FALSE);
  else
    return(TRUE);
}

// Load shadow passwords

bool KUserFiles::loadsdw()
{
#ifdef HAVE_SHADOW
  QString shadow_file,tmp;
  struct spwd *spw;
  KU::KUser *up = NULL;
  struct stat st;

  shadow_file = mCfg->shadowsrc();
  if ( shadow_file.isEmpty() )
    return TRUE;

  stat( QFile::encodeName(shadow_file), &st);
  sdw_mode = st.st_mode & 0666;
  sdw_uid = st.st_uid;
  sdw_gid = st.st_gid;

#ifdef HAVE_FGETSPENT
  FILE *f;
  kdDebug() << "open shadow file: " << shadow_file << endl;
  if ((f = fopen( QFile::encodeName(shadow_file), "r")) == NULL) {
    KMessageBox::error( 0, i18n("Error opening %1 for reading.").arg(shadow_file) );
    caps &= ~Cap_Shadow;
    return TRUE;
  }
  while ((spw = fgetspent( f ))) {     // read a shadow password structure
#else
  setspent();
  while ((spw = getspent())) {     // read a shadow password structure
#endif

    kdDebug() << "shadow entry: " << spw->sp_namp << endl;
    if ((up = lookup(QString::fromLocal8Bit(spw->sp_namp))) == NULL) {
      KMessageBox::error( 0, i18n("No /etc/passwd entry for %1.\nEntry will be removed at the next `Save'-operation.").arg(QString::fromLocal8Bit(spw->sp_namp)) );
      continue;
    }

    tmp = QString::fromLocal8Bit( spw->sp_pwdp );
    if ( tmp.startsWith("!!") || tmp == "*" ) {
      up->setDisabled( true );
      tmp.remove( 0, 2 );
    } else
      up->setDisabled( false );

    up->setSPwd( tmp );        // cp the encrypted pwd
    up->setLastChange( daysToTime( spw->sp_lstchg ) );
    up->setMin(spw->sp_min);
    up->setMax(spw->sp_max);
#ifndef _SCO_DS
    up->setWarn(spw->sp_warn);
    up->setInactive(spw->sp_inact);
    up->setExpire( daysToTime( spw->sp_expire ) );
    up->setFlag(spw->sp_flag);
#endif
  }

#ifdef HAVE_FGETSPENT
  fclose(f);
#else
  endspent();
#endif

#endif // HAVE_SHADOW
  return TRUE;
}

// Save password file

#define escstr(a,b) tmp2 = user->a(); \
                    tmp2.replace(':',"_"); \
                    tmp2.replace(',',"_"); \
                    user->b( tmp2 );


bool KUserFiles::savepwd()
{
  FILE *passwd_fd = NULL;
  FILE *nispasswd_fd = NULL;
  uid_t minuid = 0;
  int nis_users_written = 0;
  uid_t tmp_uid = 0;
  QString s;
  QString s1;
  QString tmp, tmp2;
  QString passwd_filename;
  QString nispasswd_filename;


  char errors_found = '\0';
    #define NOMINUID    0x01
    #define NONISPASSWD 0x02

  // Read KUser configuration info

  passwd_filename = mCfg->passwdsrc();
  nispasswd_filename = mCfg->nispasswdsrc();
  QString new_passwd_filename =
    passwd_filename + QString::fromLatin1(KU_CREATE_EXT);
  QString new_nispasswd_filename =
    nispasswd_filename+QString::fromLatin1(KU_CREATE_EXT);

  if( nispasswd_filename != passwd_filename ) {
    minuid = mCfg->nisminuid();
  }

  // Backup file(s)

  if(!passwd_filename.isEmpty()) {
    if (!pw_backuped) {
      if (!backup(passwd_filename)) return FALSE;
      pw_backuped = TRUE;
    }
  }
  if(!nispasswd_filename.isEmpty() &&
    (nispasswd_filename != passwd_filename)) {
    if (!pn_backuped) {
      if (!backup(nispasswd_filename)) return FALSE;
      pn_backuped = TRUE;
    }
  }

  // Open file(s)

  if(!passwd_filename.isEmpty()) {
    if ((passwd_fd =
      fopen(QFile::encodeName(new_passwd_filename),"w")) == NULL)
        KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(passwd_filename) );
  }

  if(!nispasswd_filename.isEmpty() && (nispasswd_filename != passwd_filename)){
    if ((nispasswd_fd =
      fopen(QFile::encodeName(new_nispasswd_filename),"w")) == NULL)
        KMessageBox::error( 0, i18n("Error opening %1 for writing.").arg(nispasswd_filename) );
  }

  QPtrListIterator<KU::KUser> it( mUsers );
  KU::KUser *user;
  bool addok = false;
  user = (*it);
  while (true) {
    if ( user == 0 ) {
      if ( addok ) break;
      it = QPtrListIterator<KU::KUser> ( mAdd );
      user = (*it);
      addok = true;
      if ( user == 0 ) break;
    };
    if ( mDel.containsRef( user ) ) {
      ++it;
      user = (*it);
      continue;
    }
    if ( mMod.contains( user ) ) user = &( mMod[ user ] );

    tmp_uid = user->getUID();
    if ( caps & Cap_Shadow )
      tmp = "x";
    else {
      tmp = user->getPwd();
      if ( user->getDisabled() && tmp != "x" && tmp != "*" )
        tmp = "!" + tmp;
    }

    escstr( getName, setName );
    escstr( getHomeDir, setHomeDir );
    escstr( getShell, setShell );
    escstr( getName, setName );
    escstr( getFullName, setFullName );
#if defined(__FreeBSD__) || defined(__bsdi__)
    escstr( getClass, setClass );
    escstr( getOffice, setOffice );
    escstr( getWorkPhone, setWorkPhone );
    escstr( getHomePhone, setHomePhone );
    s =
      user->getName() + ":" +
      tmp + ":" +
      QString::number( user->getUID() ) + ":" +
      QString::number( user->getGID() ) + ":" +
      user->getClass() + ":" +
      QString::number( user->getLastChange() ) + ":" +
      QString::number( user->getExpire() ) + ":";

    s1 =
      user->getFullName() + "," +
      user->getOffice() + "," +
      user->getWorkPhone() + "," +
      user->getHomePhone();
#else
    escstr( getOffice1, setOffice1 );
    escstr( getOffice2, setOffice2 );
    escstr( getAddress, setAddress );
    s =
      user->getName() + ":" +
      tmp + ":" +
      QString::number( user->getUID() ) + ":" +
      QString::number( user->getGID() ) + ":";

    s1 =
      user->getFullName() + "," +
      user->getOffice1() + "," +
      user->getOffice2() + "," +
      user->getAddress();

#endif
    for (int j=(s1.length()-1); j>=0; j--) {
      if (s1[j] != ',')
        break;
      s1.truncate(j);
    }

    s += s1 + ":" +
      user->getHomeDir() + ":" +
      user->getShell() + "\n";

    if( (nispasswd_fd != 0) && (minuid != 0) ) {
      if (minuid <= tmp_uid) {
        fputs(s.local8Bit().data(), nispasswd_fd);
        nis_users_written++;
        ++it;
        user = (*it);
        continue;
      }
    }

    if( (nispasswd_fd != 0) && (minuid == 0) ) {
      errors_found = errors_found | NOMINUID;
    }

    if( (nispasswd_fd == 0) && (minuid != 0) ) {
      errors_found = errors_found | NONISPASSWD;
    }
    kdDebug() << s << endl;
    fputs(s.local8Bit().data(), passwd_fd);

    ++it;
    user = (*it);
  }

  if(passwd_fd) {
    fclose(passwd_fd);
    chmod(QFile::encodeName(new_passwd_filename), pwd_mode);
    chown(QFile::encodeName(new_passwd_filename), pwd_uid, pwd_gid);
    rename(QFile::encodeName(new_passwd_filename),
      QFile::encodeName(passwd_filename));
  }

  if(nispasswd_fd) {
    fclose(nispasswd_fd);
    chmod(QFile::encodeName(new_nispasswd_filename), pwd_mode);
    chown(QFile::encodeName(new_nispasswd_filename), pwd_uid, pwd_gid);
    rename(QFile::encodeName(new_nispasswd_filename),
      QFile::encodeName(nispasswd_filename));
  }

  if( (errors_found & NOMINUID) != 0 ) {
    KMessageBox::error( 0, i18n("Unable to process NIS passwd file without a minimum UID specified.\nPlease update KUser settings (Files).") );
  }

  if( (errors_found & NONISPASSWD) != 0 ) {
    KMessageBox::error( 0, i18n("Specifying NIS minimum UID requires NIS file(s).\nPlease update KUser settings (Files).") );
  }

  // need to run a utility program to build /etc/passwd, /etc/pwd.db
  // and /etc/spwd.db from /etc/master.passwd
#if defined(__FreeBSD__) || defined(__bsdi__)
  if (system(PWMKDB) != 0) {
    KMessageBox::error( 0, i18n("Unable to build password database.") );
    return FALSE;
  }
#else
  if( (nis_users_written > 0) || (nispasswd_filename == passwd_filename) ) {
    if (system(PWMKDB) != 0) {
      KMessageBox::error( 0, i18n("Unable to build password databases.") );
      return FALSE;
    }
  }
#endif

  return TRUE;
}
예제 #26
0
파일: user.c 프로젝트: DeGaido/opendomo
// {{{ 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);
}
예제 #27
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");
}
예제 #28
0
PAMH_ARG_DECL(int unix_update_passwd,
	const char *forwho, const char *towhat)
{
    struct passwd *tmpent = NULL;
    struct stat st;
    FILE *pwfile, *opwfile;
    int err = 1;
    int oldmask;
#ifdef WITH_SELINUX
    security_context_t prev_context=NULL;
#endif

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

    opwfile = fopen("/etc/passwd", "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;
    }

    tmpent = fgetpwent(opwfile);
    while (tmpent) {
	if (!strcmp(tmpent->pw_name, forwho)) {
	    /* To shut gcc up */
	    union {
		const char *const_charp;
		char *charp;
	    } assigned_passwd;
	    assigned_passwd.const_charp = towhat;

	    tmpent->pw_passwd = assigned_passwd.charp;
	    err = 0;
	}
	if (putpwent(tmpent, pwfile)) {
	    D(("error writing entry to password file: %m"));
	    err = 1;
	    break;
	}
	tmpent = fgetpwent(opwfile);
    }
    fclose(opwfile);

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

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

done:
    if (!err) {
	if (!rename(PW_TMPFILE, "/etc/passwd"))
	    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(PW_TMPFILE);
	return PAM_AUTHTOK_ERR;
    }
}
예제 #29
0
struct passwd *_spfgetpwent(FILE *F) { return(_spsubspwd(fgetpwent(F))); }