Пример #1
0
/*
 * getpwnam - get entries from password database
 */
int
dogetpw(const char **list)
{
	struct passwd *pwp;
	int rc = EXC_SUCCESS;
	char *ptr;
	uid_t uid;


	if (list == NULL || *list == NULL) {
		while ((pwp = getpwent()) != NULL)
			(void) putpwent(pwp, stdout);
	} else {
		for (; *list != NULL; list++) {
			uid = strtol(*list, &ptr, 10);
			if (ptr == *list)
				pwp = getpwnam(*list);
			else
				pwp = getpwuid(uid);
			if (pwp == NULL)
				rc = EXC_NAME_NOT_FOUND;
			else
				(void) putpwent(pwp, stdout);
		}
	}

	return (rc);
}
Пример #2
0
LISP lputpwent(LISP alist,LISP file)
{int iflag = no_interrupt(1);
 int status;
 struct passwd p;
 lencode_pwent(alist,&p);
 status = putpwent(&p,get_c_file(file,NULL));
 no_interrupt(iflag);
 return(NIL);}
Пример #3
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;
    }
}
Пример #4
0
/*
 * getpwnam - get entries from password database
 */
int
dogetpw(const char **list)
{
	struct passwd *pwp;
	int rc = EXC_SUCCESS;
	char *ptr;
	uid_t uid;


	if (list == NULL || *list == NULL) {
		while ((pwp = getpwent()) != NULL)
			(void) putpwent(pwp, stdout);
	} else {
		for (; *list != NULL; list++) {
			errno = 0;

			/*
			 * Here we assume that the argument passed is
			 * a uid, if it can be completely transformed
			 * to a long integer. So we check for uid in
			 * the database and if we fail then we check
			 * for the user name.
			 * If the argument passed is not numeric, then
			 * we take it as the user name and proceed.
			 */
			uid = strtol(*list, &ptr, 10);
			if (!(*ptr == '\0' && errno == 0) ||
			    ((pwp = getpwuid(uid)) == NULL)) {
				pwp = getpwnam(*list);
			}

			if (pwp == NULL)
				rc = EXC_NAME_NOT_FOUND;
			else
				(void) putpwent(pwp, stdout);
		}
	}

	return (rc);
}
Пример #5
0
static int passwd_put (const void *ent, FILE * file)
{
	const struct passwd *pw = ent;

	if (   (NULL == pw)
	    || (valid_field (pw->pw_name, ":\n") == -1)
	    || (valid_field (pw->pw_passwd, ":\n") == -1)
	    || (pw->pw_uid == (uid_t)-1)
	    || (pw->pw_gid == (gid_t)-1)
	    || (valid_field (pw->pw_gecos, ":\n") == -1)
	    || (valid_field (pw->pw_dir, ":\n") == -1)
	    || (valid_field (pw->pw_shell, ":\n") == -1)) {
		return -1;
	}

	return (putpwent (pw, file) == -1) ? -1 : 0;
}
Пример #6
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;
}
Пример #7
0
int main(int argc, char **argv) {
    char * tmpdir = getenv("_FAKEUSER_DIR_");
    char *passwd_file, *group_file;

    name = argv[0];
    int opt, ret = 0;
    int action = 0, uid = 0, gid = 0;
    char *name = NULL, *passwd = NULL, *members = NULL, *shell = NULL, *gecos = NULL, *dir = NULL;
    extern char *optarg;

    while ((opt = getopt(argc, argv, "UGu:g:n:p:m:s:c:d:h")) != -1) {
        switch (opt) {
        case 'U':
            action = 'U';
            break;
        case 'G':
            action = 'G';
            break;
        case 'u':
            uid = atoi(optarg);
            break;
        case 'g':
            gid = atoi(optarg);
            break;
        case 'n':
            name = optarg;
            break;
        case 'p':
            passwd = optarg;
            break;
        case 'm':
            members = optarg;
            break;
        case 's':
            shell = optarg;
            break;
        case 'c':
            gecos = optarg;
            break;
        case 'd':
            dir = optarg;
            break;
        case 'h':
            help();
            exit(EXIT_SUCCESS);
        default: /* '?' */
            usage_fd(stderr);
            exit(EXIT_FAILURE);
        }
    }
    if (action == 0 || name == NULL) {
        usage();
        exit(EXIT_FAILURE);
    }
    // only continue when environment variable with directory found.
    if (!tmpdir) {
        fputs("Error! Not in fakeuser environment\n", stderr);
        exit(EXIT_FAILURE);
    }
    // init file paths
    passwd_file = (char*)malloc(strlen(tmpdir)+10);
    strcpy(passwd_file, tmpdir);
    strcat(passwd_file, "/passwd");

    group_file = (char*)malloc(strlen(tmpdir)+10);
    strcpy(group_file, tmpdir);
    strcat(group_file, "/group");

    // Create directory structure
    mkdir_r(tmpdir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);

    if (action == 'U') {
        // create and append passwd entry
        struct passwd pw;
        pw.pw_name = name;
        pw.pw_passwd = passwd ? passwd : "";
        pw.pw_gecos = gecos ? gecos : "";
        pw.pw_dir = dir ? dir : "";
        pw.pw_shell = shell ? shell : "";
        pw.pw_uid = uid;
        pw.pw_gid = gid;
        // append to file with error handling.
        FILE * pwf = fopen(passwd_file, "a");
        if (pwf) {
            if(putpwent(&pw, pwf))
                ret = EIO;
            if (fclose(pwf))
                ret = EIO;
        } else
            ret = EIO;
    } else if (action == 'G') {
        // create and append group entry
        struct group gr;
        gr.gr_name = name;
        gr.gr_passwd = passwd ? passwd : "";
        gr.gr_gid = gid;
        char *strings;
        gr.gr_mem = members ? string_to_array(members, " ,;", &strings) : (char *[]) {
            NULL
        };
        // append to file with error handling.
        FILE * pwf = fopen(group_file, "a");
        if (pwf) {
            if(putgrent(&gr, pwf))
                ret = EIO;
            if (fclose(pwf))
                ret = EIO;
        } else
            ret = EIO;
    }
    // return 0 on success or the error value
    return ret;
}
Пример #8
0
/*
 *  setpwnam () --
 *	takes a struct passwd in which every field is filled in and valid.
 *	If the given username exists in the passwd file, the entry is
 *	replaced with the given entry.
 */
int 
setpwnam (struct passwd *pwd)
{
    FILE *fp = NULL, *pwf = NULL;
    int x, save_errno, fd, ret;
    boolean found;
    int oldumask;
    int namelen;
    int buflen = 256;
    int contlen;
    char *linebuf = malloc(buflen);

    if (!linebuf) return -1;

    oldumask = umask(0);   /* Create with exact permissions */

    pw_init();

    /* sanity check */
    for (x = 0; x < 3; x++) {
	if (x > 0) sleep(1);
	fd = open(PTMPTMP_FILE, O_WRONLY|O_CREAT, 0644);
	if (fd == -1) {
	    umask(oldumask);
	    return -1;
	}
	ret = link(PTMPTMP_FILE, PTMP_FILE);
	unlink(PTMPTMP_FILE);
	if (ret == -1)
	    close(fd);
	else
	    break;
    }
    umask(oldumask);
    if (ret == -1) return -1;

    /* ptmp should be owned by root.root or root.wheel */
    if (chown(PTMP_FILE, (uid_t) 0, (gid_t) 0) < 0) return -1;

    /* open ptmp for writing and passwd for reading */
    fp = fdopen(fd, "w");
    if (!fp) goto fail;

    pwf = fopen(PASSWD_FILE, "r");
    if (!pwf) goto fail;

    namelen = strlen(pwd->pw_name);

    /* parse the passwd file */
    found = false;
    /* Do you wonder why I don't use getpwent? Read comments at top of file */
    while (fgets(linebuf, buflen, pwf) != NULL) {
	contlen = strlen(linebuf);
	while (linebuf[contlen-1] != '\n' && !feof(pwf)) {
	    /* Extend input buffer if it failed getting the whole line */

	    /* So now we double the buffer size */
	    buflen *= 2;

	    linebuf = realloc(linebuf, buflen);
	    if (linebuf == NULL) goto fail;

	    /* And fill the rest of the buffer */
	    if (fgets(&linebuf[contlen], buflen/2, pwf) == NULL) break;
	    contlen = strlen(linebuf);
      
	    /* That was a lot of work for nothing.  Gimme perl! */
	}

	/* Is this the username we were sent to change? */
	if (!found && linebuf[namelen] == ':' &&
	    !strncmp(linebuf, pwd->pw_name, namelen)) {
	    /* Yes! So go forth in the name of the Lord and change it! */
	    if (putpwent(pwd, fp) < 0) goto fail;
	    found = true;
	    continue;
	}
	/* Nothing in particular happened, copy input to output */
	fputs(linebuf, fp);
    }

    if (fclose(fp) < 0) goto fail;
    fp = NULL;
    close (fd);
    fd = -1;
    fclose (pwf); /* I don't think I want to know if this failed */
    pwf = NULL;

    if (!found) {
	errno = ENOENT; /* give me something better */
	goto fail;
    }

    /* we don't care if we can't remove the backup file */
    unlink(PASSWD_FILE".OLD");
    /* we don't care if we can't create the backup file */
    link(PASSWD_FILE, PASSWD_FILE".OLD");
    /* we DO care if we can't rename to the passwd file */
    if(rename(PTMP_FILE, PASSWD_FILE) < 0)
	goto fail;
    /* finally:  success */
    return 0;

fail:
    save_errno = errno;
    if (fp != NULL) fclose (fp);
    if (pwf != NULL) fclose(pwf);
    if (fd >= 0) close (fd);
    if (linebuf != NULL) free(linebuf);
    unlink(PTMP_FILE);
    errno = save_errno;
    return -1;
}
Пример #9
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;
}
Пример #10
0
int
files_update_passwd(char *name, struct passwd *pwd)
{
	struct stat64 stbuf;
	FILE *src, *dst;
	int tempfd;
	struct passwd cur;
	char buf[PWD_SCRATCH_SIZE];
	int result;
	int err = PWU_SUCCESS;

	if (stat64(PASSWD, &stbuf) < 0) {
		err = PWU_STAT_FAILED;
		goto passwd_exit;
	}

	/* see files_update_shadow() for open()+fdopen() rationale */

	if ((tempfd = open(PASSTEMP, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) {
		err = PWU_OPEN_FAILED;
		goto passwd_exit;
	}
	if ((dst = fdopen(tempfd, "wF")) == NULL) {
		err = PWU_OPEN_FAILED;
		goto passwd_exit;
	}
	if ((src = fopen(PASSWD, "rF")) == NULL) {
		err = PWU_OPEN_FAILED;
		(void) fclose(dst);
		(void) unlink(PASSTEMP);
		goto passwd_exit;
	}

	/*
	 * copy old password entries to temporary file while replacing
	 * the entry that matches "name"
	 */
	while (fgetpwent_r(src, &cur, buf, sizeof (buf)) != NULL) {
		if (strcmp(cur.pw_name, name) == 0)
			result = putpwent(pwd, dst);
		else
			result = putpwent(&cur, dst);
		if (result != 0) {
			err = PWU_WRITE_FAILED;
			(void) fclose(src);
			(void) fclose(dst);
			goto passwd_exit;
		}
	}

	(void) fclose(src);
	if (fclose(dst) != 0) {
		err = PWU_CLOSE_FAILED;
		goto passwd_exit; /* Don't trust the temporary file */
	}

	/* Rename temp to passwd */
	if (unlink(OPASSWD) && access(OPASSWD, 0) == 0) {
		err = PWU_UPDATE_FAILED;
		(void) unlink(PASSTEMP);
		goto passwd_exit;
	}

	if (link(PASSWD, OPASSWD) == -1) {
		err = PWU_UPDATE_FAILED;
		(void) unlink(PASSTEMP);
		goto passwd_exit;
	}

	if (rename(PASSTEMP, PASSWD) == -1) {
		err = PWU_UPDATE_FAILED;
		(void) unlink(PASSTEMP);
		goto passwd_exit;
	}

	(void) chmod(PASSWD, 0644);

passwd_exit:
	return (err);

}
Пример #11
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;
    }
}
Пример #12
0
void main() {
  char foo[64];
  char uname[9],person[32],passwd[9],dir[32],shell[32],salt[3];
  unsigned int group,uid;
  int bad=0,i,correct=0;
  time_t tm;
  struct passwd *pw;
  FILE *passwd_file;  /* Yep, it's a file allright */

  unused_uid = FIRST;
  if (getuid()!=0) {
     printf("You don't have access to add a new user.\n");
     printf("Only root can add new users to the system.\n");
     exit(1);
  }
  if ((bull=fopen("/etc/shadow","r"))!=NULL) found_shadow();
  if ((bull=fopen("/etc/passwd","r"))==NULL) {
   printf("Fatal error: password file not found.\n");
   exit(1);
  }
  while (!correct) {		/* loop until a "good" uname is chosen */

getlogin:
   printf("\nLogin to add (^C to quit): ");
   fflush(stdout);
   gets(uname);
   if (strlen(uname)>8) {
    printf("The login name must be maximum 8 characters long.\n");
    goto getlogin;
   }
   for (i=0;i<strlen(uname);i++) {
    if (!(((uname[i]>='A') && (uname[i]<='Z')) || 
          ((uname[i]>='a') && (uname[i]<='z')) ||
          ((uname[i]>='0') && (uname[i]<='9')))) {
     printf("Invalid character in login.\n");
     goto getlogin;
    }
   }
   if (nag=getpwnam(uname) != NULL) {
    printf("Login in use. Choose another one.\n");
    goto getlogin;
   }

   putchar('\n');
   unused_uid = find_unused(++unused_uid);
   
   printf("\nEditing information for new user [%s]:\n",uname);
   printf("\nFull name: ");
   fflush(stdout);
   gets(person);
      
   printf("GID [%d]: ",DEFAULT_GROUP);
   fflush(stdout);
   gets(foo);
   group=atoi(foo);
   if (group==0) group=DEFAULT_GROUP;
   
   printf("UID [%d]: ",unused_uid);
   fflush(stdout);
   gets(foo);
   uid=atoi(foo);
   if (uid==0) uid=unused_uid;
   if ((pw=getpwuid(uid))!=NULL) {
        printf("\nWarning: UID [%d] already in use, this would conflict with\n",uid);
        printf("who already owns this user ID. [%s]'s UID has been reset to\n",uname);
        printf("the last unused UID: [%d].\n",unused_uid);
        uid=unused_uid;
   }

   fflush(stdin);
   printf("Home Directory [%s/%s]: ",DEFAULT_HOME,uname);
   fflush(stdout);
   gets(dir);
   if (!strcmp(dir,"")) sprintf(dir,"%s/%s",DEFAULT_HOME,uname);

   fflush(stdin);
   printf("Shell [%s]: ",DEFAULT_SHELL);
   fflush(stdout);
   gets(shell);
   if (!strcmp(shell,"")) sprintf(shell,"%s",DEFAULT_SHELL);
   
   fflush(stdin);   
   printf("Password [%s]: ",uname);
   fflush(stdout);
   gets(passwd);
   if (!strcmp(passwd,"")) sprintf(passwd,"%s",uname);
   time(&tm);
   salt[0]=(tm.t_time & 0x0f)+'A';
   salt[1]=((tm.t_time & 0xf0) >> 4)+'a';
   salt[2]=0;
  
   printf("\nInformation for new user [%s]:\n",uname);
   printf("Home directory: [%s]\nShell: [%s]\n",dir,shell);
   printf("Password: [%s]\nUID: [%d]\nGID: [%d]\n",passwd,uid,group);
   printf("\nIs this correct? [y/N]: ");
   fflush(stdout);
   fflush(stdin);
   gets(foo);
   bad=correct=(foo[0]=='y'||foo[0]=='Y');
   if (bad!=1) printf("\nUser [%s] not added.\n",uname);
  }

  printf("\nAdding login [%s]...\n",uname);
  strcpy(foo,PASSWD_FILE);
  strcat(foo,".old");
  if ((passwd_file=fopen(foo,"w")) == NULL) {
   printf("Error creating password backup file.\n");
   exit(1);
  }
  setpwent();
  for (i=0;(pw=getpwent())!=NULL;++i) {
   if (putpwent(pw,passwd_file)==-1) {
    printf("Error writing password backup file.\n");
    exit(1);
   }
  }
  endpwent();
  fclose(passwd_file);
  if (i<1) printf("Can't backup password file.\n");
  passwd_file=fopen(PASSWD_FILE,"a");
  fprintf(passwd_file,"%s:%s:%d:%d:%s:%s:%s\n"
	  ,uname,crypt(passwd,salt),uid,group,person,dir,shell);
  fflush(passwd_file);
  fclose(passwd_file);
  
  printf("Making directory [%s]...\n",dir);
  mkdir(dir,DEFAULT_PERMS);

  chown(dir,uid,group);
  printf("Done.\n");
}
Пример #13
0
int adduser_main(int argc UNUSED_PARAM, char **argv)
{
	struct passwd pw;
	const char *usegroup = NULL;
	FILE *file;

#if ENABLE_FEATURE_ADDUSER_LONG_OPTIONS
	applet_long_options = adduser_longopts;
#endif

	/* got root? */
	if (geteuid()) {
		bb_error_msg_and_die(bb_msg_perm_denied_are_you_root);
	}

	pw.pw_gecos = (char *)"Linux User,,,";
	pw.pw_shell = (char *)DEFAULT_SHELL;
	pw.pw_dir = NULL;

	/* exactly one non-option arg */
	opt_complementary = "=1";
	getopt32(argv, "h:g:s:G:DSH", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup);
	argv += optind;

	/* fill in the passwd struct */
	pw.pw_name = argv[0];
	die_if_bad_username(pw.pw_name);
	if (!pw.pw_dir) {
		/* create string for $HOME if not specified already */
		pw.pw_dir = xasprintf("/home/%s", argv[0]);
	}
	pw.pw_passwd = (char *)"x";
	pw.pw_gid = usegroup ? xgroup2gid(usegroup) : 0; /* exits on failure */

	/* make sure everything is kosher and setup uid && maybe gid */
	passwd_study(&pw);

	/* add to passwd */
	file = xfopen(bb_path_passwd_file, "a");
	//fseek(file, 0, SEEK_END); /* paranoia, "a" should ensure that anyway */
	if (putpwent(&pw, file) != 0) {
		bb_perror_nomsg_and_die();
	}
	/* do fclose even if !ENABLE_FEATURE_CLEAN_UP.
	 * We will exec passwd, files must be flushed & closed before that! */
	fclose(file);

#if ENABLE_FEATURE_SHADOWPASSWDS
	/* add to shadow if necessary */
	file = fopen_or_warn(bb_path_shadow_file, "a");
	if (file) {
		//fseek(file, 0, SEEK_END);
		fprintf(file, "%s:!:%u:0:99999:7:::\n",
				pw.pw_name,             /* username */
				(unsigned)(time(NULL) / 86400) /* sp->sp_lstchg */
				/*0,*/                  /* sp->sp_min */
				/*99999,*/              /* sp->sp_max */
				/*7*/                   /* sp->sp_warn */
		);
		fclose(file);
	}
#endif

	/* add to group */
	/* addgroup should be responsible for dealing w/ gshadow */
	/* if using a pre-existing group, don't create one */
	if (!usegroup)
		addgroup_wrapper(&pw);

	/* Clear the umask for this process so it doesn't
	 * screw up the permissions on the mkdir and chown. */
	umask(0);
	if (!(option_mask32 & OPT_DONT_MAKE_HOME)) {
		/* Set the owner and group so it is owned by the new user,
		   then fix up the permissions to 2755. Can't do it before
		   since chown will clear the setgid bit */
		if (mkdir(pw.pw_dir, 0755)
		 || chown(pw.pw_dir, pw.pw_uid, pw.pw_gid)
		 || chmod(pw.pw_dir, 02755) /* set setgid bit on homedir */
		) {
			bb_simple_perror_msg(pw.pw_dir);
		}
	}

	if (!(option_mask32 & OPT_DONT_SET_PASS)) {
		/* interactively set passwd */
		passwd_wrapper(pw.pw_name);
	}

	return 0;
}
Пример #14
0
/*
 *  setpwnam () --
 *	takes a struct passwd in which every field is filled in and valid.
 *	If the given username exists in the passwd file, the entry is
 *	replaced with the given entry.
 */
int setpwnam(struct passwd *pwd)
{
	FILE *fp = NULL, *pwf = NULL;
	int save_errno;
	int found;
	int namelen;
	int buflen = 256;
	int contlen, rc;
	char *linebuf = NULL;
	char *tmpname = NULL;

	pw_init();

	if ((fp = xfmkstemp(&tmpname)) == NULL)
		return -1;

	/* ptmp should be owned by root.root or root.wheel */
	if (fchown(fileno(fp), (uid_t) 0, (gid_t) 0) < 0)
		goto fail;

	/* acquire exclusive lock */
	if (lckpwdf() < 0)
		goto fail;
	pwf = fopen(PASSWD_FILE, "r");
	if (!pwf)
		goto fail;

	namelen = strlen(pwd->pw_name);

	linebuf = malloc(buflen);
	if (!linebuf)
		goto fail;

	/* parse the passwd file */
	found = false;

	/* Do you wonder why I don't use getpwent? Read comments at top of
	 * file */
	while (fgets(linebuf, buflen, pwf) != NULL) {
		contlen = strlen(linebuf);
		while (linebuf[contlen - 1] != '\n' && !feof(pwf)) {
			char *tmp;
			/* Extend input buffer if it failed getting the whole line,
			 * so now we double the buffer size */
			buflen *= 2;
			tmp = realloc(linebuf, buflen);
			if (tmp == NULL)
				goto fail;
			linebuf = tmp;
			/* And fill the rest of the buffer */
			if (fgets(&linebuf[contlen], buflen / 2, pwf) == NULL)
				break;
			contlen = strlen(linebuf);
			/* That was a lot of work for nothing. Gimme perl! */
		}

		/* Is this the username we were sent to change? */
		if (!found && linebuf[namelen] == ':' &&
		    !strncmp(linebuf, pwd->pw_name, namelen)) {
			/* Yes! So go forth in the name of the Lord and
			 * change it!  */
			if (putpwent(pwd, fp) < 0)
				goto fail;
			found = true;
			continue;
		}
		/* Nothing in particular happened, copy input to output */
		fputs(linebuf, fp);
	}

	/* xfmkstemp is too restrictive by default for passwd file */
	if (fchmod(fileno(fp), 0644) < 0)
		goto fail;
	rc = close_stream(fp);
	fp = NULL;
	if (rc != 0)
		goto fail;

	fclose(pwf);	/* I don't think I want to know if this failed */
	pwf = NULL;

	if (!found) {
		errno = ENOENT;	/* give me something better */
		goto fail;
	}

	/* we don't care if we can't remove the backup file */
	unlink(PASSWD_FILE ".OLD");
	/* we don't care if we can't create the backup file */
	ignore_result(link(PASSWD_FILE, PASSWD_FILE ".OLD"));
	/* we DO care if we can't rename to the passwd file */
	if (rename(tmpname, PASSWD_FILE) < 0)
		goto fail;
	/* finally:  success */
	ulckpwdf();
	return 0;

 fail:
	save_errno = errno;
	ulckpwdf();
	if (fp != NULL)
		fclose(fp);
	if (tmpname != NULL)
		unlink(tmpname);
	free(tmpname);
	if (pwf != NULL)
		fclose(pwf);
	free(linebuf);
	errno = save_errno;
	return -1;
}
Пример #15
0
int	main ()
{
	struct	passwd	*pw;
	struct	passwd	*sgetpwent ();
	FILE	*pwd;
	FILE	*npwd;
	struct	spwd	*spwd;
	int	fd;
	char	newage[5];

	if (! (pwd = fopen (PWDFILE, "r"))) {
		perror (PWDFILE);
		return (1);
	}
	unlink ("npasswd");
	if ((fd = open ("npasswd", O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0 ||
			! (npwd = fdopen (fd, "w"))) {
		perror ("npasswd");
		return (1);
	}
	while (fgets (buf, BUFSIZ, pwd) == buf) {
		buf[strlen (buf) - 1] = '\0'; /* remove '\n' character */

		if (buf[0] == '#') {	/* comment line */
			(void) fprintf (npwd, "%s\n", buf);
			continue;
		}
		if (! (pw = sgetpwent (buf))) { /* copy bad lines verbatim */
			(void) fprintf (npwd, "%s\n", buf);
			continue;
		}
		setspent ();		/* rewind shadow file */

		if (! (spwd = getspnam (pw->pw_name))) {
			(void) fprintf (npwd, "%s\n", buf);
			continue;
		}
		pw->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.
	 */

#ifdef	ATT_AGE
		if (spwd->sp_max > (63*WEEK) && spwd->sp_max < 10000)
			spwd->sp_max = (63*WEEK); /* 10000 is infinity */

		if (spwd->sp_min >= 0 && spwd->sp_min <= 63*7 &&
				spwd->sp_max >= 0 && spwd->sp_max <= 63*7) {
			if (spwd->sp_lstchg == -1)
				spwd->sp_lstchg = 0;

			spwd->sp_max /= WEEK;	/* turn it into weeks */
			spwd->sp_min /= WEEK;
			spwd->sp_lstchg /= WEEK;

			strncpy (newage, l64a (spwd->sp_lstchg * (64L*64L) +
				  spwd->sp_min * (64L) + spwd->sp_max), 5);
			pw->pw_age = newage;
		} else
			pw->pw_age = "";
#endif	/* ATT_AGE */
		if (putpwent (pw, npwd)) {
			perror ("pwunconv: write error");
			exit (1);
		}
	}
	endspent ();

	if (ferror (npwd)) {
		perror ("pwunconv");
		(void) unlink ("npasswd");
	}
	(void) fclose (npwd);
	(void) fclose (pwd);
	return (0);
}
Пример #16
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");
}
Пример #17
0
static void
check (struct passwd p, const char *expected)
{
  char *buf;
  size_t buf_size;
  FILE *f = open_memstream (&buf, &buf_size);

  if (f == NULL)
    {
      printf ("open_memstream: %m\n");
      errors = true;
      return;
    }

  int ret = putpwent (&p, f);

  if (expected == NULL)
    {
      if (ret == -1)
	{
	  if (errno != EINVAL)
	    {
	      printf ("putpwent: unexpected error code: %m\n");
	      errors = true;
	    }
	}
      else
	{
	  printf ("putpwent: unexpected success (\"%s\")\n", p.pw_name);
	  errors = true;
	}
    }
  else
    {
      /* Expect success.  */
      size_t expected_length = strlen (expected);
      if (ret == 0)
	{
	  long written = ftell (f);

	  if (written <= 0 || fflush (f) < 0)
	    {
	      printf ("stream error: %m\n");
	      errors = true;
	    }
	  else if (buf[written - 1] != '\n')
	    {
	      printf ("FAILED: \"%s\" without newline\n", expected);
	      errors = true;
	    }
	  else if (strncmp (buf, expected, written - 1) != 0
		   || written - 1 != expected_length)
	    {
	      printf ("FAILED: \"%s\" (%ld), expected \"%s\" (%zu)\n",
		      buf, written - 1, expected, expected_length);
	      errors = true;
	    }
	}
      else
	{
	  printf ("FAILED: putpwent (expected \"%s\"): %m\n", expected);
	  errors = true;
	}
    }

  fclose (f);
  free (buf);
}
Пример #18
0
/* putpwent(3) remix */
static int adduser(const char *filename, struct passwd *p, int makehome, int setpass)
{
	FILE *passwd;
	int r;
#ifdef CONFIG_FEATURE_SHADOWPASSWDS
	FILE *shadow;
	struct spwd *sp;
#endif
	int new_group = 1;

	/* if using a pre-existing group, don't create one */
	if (p->pw_gid != 0)
		new_group = 0;

	/* make sure everything is kosher and setup uid && gid */
	passwd = bb_wfopen(filename, "a");
	if (passwd == NULL) {
		return 1;
	}
	fseek(passwd, 0, SEEK_END);

	/* if (passwd_study(filename, p) == 0) { */
	r = passwd_study(filename, p);
	if (r) {
		if (r == 1)
			bb_error_msg("%s: login already in use", p->pw_name);
		else if (r == 2)
			bb_error_msg("illegal uid or no uids left");
		else if (r == 3)
			bb_error_msg("group name %s already in use", p->pw_name);
		else
			bb_error_msg("generic error.");
		return 1;
	}

	/* add to passwd */
	if (putpwent(p, passwd) == -1) {
		return 1;
	}
	fclose(passwd);

#ifdef CONFIG_FEATURE_SHADOWPASSWDS
	/* add to shadow if necessary */
	if (shadow_enabled) {
		shadow = bb_wfopen(bb_path_shadow_file, "a");
		if (shadow == NULL) {
			return 1;
		}
		fseek(shadow, 0, SEEK_END);
		sp = pwd_to_spwd(p);
		sp->sp_max = 99999;		/* debianish */
		sp->sp_warn = 7;
		fprintf(shadow, "%s:!:%ld:%ld:%ld:%ld:::\n",
				sp->sp_namp, sp->sp_lstchg, sp->sp_min, sp->sp_max,
				sp->sp_warn);
		fclose(shadow);
	}
#endif

	if (new_group) {
		/* add to group */
		/* addgroup should be responsible for dealing w/ gshadow */
		addgroup_wrapper(p->pw_name, p->pw_gid);
	}

	/* Clear the umask for this process so it doesn't
	 * * screw up the permissions on the mkdir and chown. */
	umask(0);

	if (makehome) {
		/* mkdir */
		if (mkdir(p->pw_dir, 0755)) {
			bb_perror_msg("%s", p->pw_dir);
		}
		/* Set the owner and group so it is owned by the new user. */
		if (chown(p->pw_dir, p->pw_uid, p->pw_gid)) {
			bb_perror_msg("%s", p->pw_dir);
		}
		/* Now fix up the permissions to 2755. Can't do it before now
		 * since chown will clear the setgid bit */
		if (chmod(p->pw_dir, 02755)) {
			bb_perror_msg("%s", p->pw_dir);
		}
	}

	if (setpass) {
		/* interactively set passwd */
		passwd_wrapper(p->pw_name);
	}

	return 0;
}
Пример #19
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);
}