mirror of
https://github.com/GnoConsortium/gno.git
synced 2024-05-31 15:41:31 +00:00
Makefile, mklink.data, mkso.data, newuser.desc, newuser.rez:
- initial checkin README: - updated installation notes installit, newuserv.c: - deleted (obsolete) newuser.1: - renamed to newuser.8 newuser.c, newuser.8: - account home directories are now made in /home rather than /user - made all the routines internal to this file to be class 'static' - fit sources into GNO base distribution builds - added checks for parsing NEWID_FILE - added various conchecks to prevent buffer overflow and similar problems - ensure the password is at least MIN_PASSWD_LEN characters long - don't set the terminal type; that is the responsibility of initd/getty. - instead of creating explicit files in the user's home directory, copy every file that is in the SKELETONS directory. - account creation is now logged via syslogd - added -g flag for selecting non-default group ids - check to ensure that the new uid returned by get_next_uid is not already in use; if it is, then log a warning via syslog, skip it, and get another uid
This commit is contained in:
parent
5ffbafc1b5
commit
330e74b7e9
15
usr.sbin/newuser/Makefile
Normal file
15
usr.sbin/newuser/Makefile
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#
|
||||||
|
# $Id: Makefile,v 1.1 1999/02/15 00:22:10 gdr-ftp Exp $
|
||||||
|
#
|
||||||
|
|
||||||
|
PROG = newuser
|
||||||
|
SRCS = newuser.c
|
||||||
|
LDADD = -lcrypt -lcontrib
|
||||||
|
DEBUG = 25
|
||||||
|
OPTIMIZE= 0
|
||||||
|
CFLAGS += -D__STACK_CHECK__
|
||||||
|
STACK = 4096 # observed: 940
|
||||||
|
BINDIR = /usr/sbin
|
||||||
|
CHAPTER = 8
|
||||||
|
|
||||||
|
.INCLUDE: /src/gno/prog.mk
|
|
@ -1,7 +1,17 @@
|
||||||
After running the 'install' program, you need to create the files
|
$Id: README,v 1.2 1999/02/15 00:22:10 gdr-ftp Exp $
|
||||||
/var/adm/newuser/newid and /var/adm/newuser/gshrc. The latter is simply
|
|
||||||
a template gshrc file that all new users will be given. The former is
|
In order to run newuser/newuserv, the following files must exist. They
|
||||||
a file with a single integer (1-5 digits) and *nothing else*. New users
|
are installed as part of the GNO base distribution, but you may have to
|
||||||
will be assigned the userid found in this file each time newuser is run,
|
install them manually if you received newuser/newuserv as a standalone
|
||||||
and the userid will be automatically incremented by newuser. So you only
|
archive:
|
||||||
have to set it up once.
|
|
||||||
|
/home
|
||||||
|
A directory. All user home directories will be created in this
|
||||||
|
directory.
|
||||||
|
/var/adm/newuser/newid:
|
||||||
|
A text file containing the next UID that newuser/newuserv
|
||||||
|
should assign.
|
||||||
|
/var/adm/newuser/skel:
|
||||||
|
A directory. All plain files in this directory will be copied
|
||||||
|
into a user's $HOME directory, when $HOME is created. It is normal
|
||||||
|
to have a skelton glogin and gshrc in here.
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
echo "Moving files to appropriate places..."
|
|
||||||
echo
|
|
||||||
mv -vi newuser /usr/sbin
|
|
||||||
mv -vi newuserv /usr/sbin
|
|
||||||
mv -vi newuser.1 /usr/man/man1/
|
|
||||||
echo
|
|
||||||
echo "Make sure the directory /var/adm/newuser exists, and has as"
|
|
||||||
echo "template 'gshrc' file in it. Also required in that directory"
|
|
||||||
echo "is the 'newid' file, which holds the next available userid."
|
|
9
usr.sbin/newuser/mklink.data
Normal file
9
usr.sbin/newuser/mklink.data
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# 0
|
||||||
|
# 1 The first column is the "real" program; the second is what _should_
|
||||||
|
# 2 be the symlink, but for now is a copy.
|
||||||
|
# 3 All paths should be relative to the root directory. This list
|
||||||
|
# 4 should be kept sorted.
|
||||||
|
# 5
|
||||||
|
# 6 $Id: mklink.data,v 1.1 1999/02/15 00:22:10 gdr-ftp Exp $
|
||||||
|
# 7
|
||||||
|
usr/sbin/newuser usr/sbin/newuserv
|
8
usr.sbin/newuser/mkso.data
Normal file
8
usr.sbin/newuser/mkso.data
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# 0
|
||||||
|
# 1 The first column is the "real" man page; the second is the .so link.
|
||||||
|
# 2 All paths should be relative to the /usr/man directory. This list
|
||||||
|
# 3 should be kept sorted.
|
||||||
|
# 4
|
||||||
|
# 5 $Id: mkso.data,v 1.1 1999/02/15 00:22:10 gdr-ftp Exp $
|
||||||
|
# 6
|
||||||
|
man8/newuser.8 man8/newuserv.8
|
|
@ -1,52 +0,0 @@
|
||||||
.TH NEWUSER 8
|
|
||||||
.SH NAME
|
|
||||||
.nf
|
|
||||||
newuser - add a new user to the system
|
|
||||||
newuserv - add a new user to the system, subject to validation
|
|
||||||
.fi
|
|
||||||
.LP
|
|
||||||
.SH DESCRIPTION
|
|
||||||
This is
|
|
||||||
.B newuser
|
|
||||||
for GNO/ME. Its basic intent is
|
|
||||||
to let people add themselves to the system without requiring the system
|
|
||||||
administrator to do it all manually.
|
|
||||||
.LP
|
|
||||||
.B newuser
|
|
||||||
will ask for real name, account name, terminal type and password (verifying
|
|
||||||
the password once) and then create the directory /user/(account name) and
|
|
||||||
copy a template
|
|
||||||
.B gshrc
|
|
||||||
into that directory. Then it will add the user to
|
|
||||||
.B /etc/passwd
|
|
||||||
and exit.
|
|
||||||
.PP
|
|
||||||
If the
|
|
||||||
.B -v
|
|
||||||
(verify) flag is selected, everything is done as normal, except
|
|
||||||
that the new entry is appended to
|
|
||||||
.B /var/adm/newuser/newusers
|
|
||||||
instead of being appended to
|
|
||||||
.BR /etc/passwd ". "
|
|
||||||
.LP
|
|
||||||
.SH FILES
|
|
||||||
.nf
|
|
||||||
.BR /var/adm/newuser/newid " -- This file holds the next available"
|
|
||||||
userID. newuser will increment it as necessary.
|
|
||||||
.BR /var/adm/newuser/gshrc " -- This is the 'template' gshrc file"
|
|
||||||
that all new users will get. In addition to this, newuser will append
|
|
||||||
'set' commands to set $home and $user.
|
|
||||||
.BR /etc/passwd " -- Not required if you use -v. But what's the point"
|
|
||||||
in newuser if you don't have it? :)
|
|
||||||
.BR /user/ " -- Has to exist. This is where the user's home directories"
|
|
||||||
go.
|
|
||||||
.fi
|
|
||||||
.LP
|
|
||||||
.B newuser
|
|
||||||
will time out after 60 seconds of operation.
|
|
||||||
.LP
|
|
||||||
.SH AUTHOR
|
|
||||||
.nf
|
|
||||||
James Brookes
|
|
||||||
jamesb@cscihp.ecst.csuchico.edu
|
|
||||||
.fi
|
|
|
@ -1,52 +1,88 @@
|
||||||
.TH NEWUSER 8
|
.TH NEWUSER 8 "14 February 1999" GNO "System Administration"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.nf
|
.BR newuser ,
|
||||||
newuser - add a new user to the system
|
.BR newuserv
|
||||||
newuserv - add a new user to the system, subject to validation
|
\- add a new user to the system
|
||||||
.fi
|
.SH SYNOPSIS
|
||||||
.LP
|
.BR newuser
|
||||||
|
[
|
||||||
|
.BR -v
|
||||||
|
] [
|
||||||
|
.B -g
|
||||||
|
.I gid
|
||||||
|
]
|
||||||
|
.br
|
||||||
|
.BR newuserv
|
||||||
|
[
|
||||||
|
.BR -v
|
||||||
|
] [
|
||||||
|
.B -g
|
||||||
|
.I gid
|
||||||
|
]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
This is
|
This manual page documents
|
||||||
.B newuser
|
.B newuser
|
||||||
for GNO/ME. Its basic intent is
|
and
|
||||||
|
.B newuserv
|
||||||
|
version 1.2 for GNO. Its basic intent is
|
||||||
to let people add themselves to the system without requiring the system
|
to let people add themselves to the system without requiring the system
|
||||||
administrator to do it all manually.
|
administrator to do it all manually.
|
||||||
.LP
|
.LP
|
||||||
.B newuser
|
.B newuser
|
||||||
will ask for real name, account name, terminal type and password (verifying
|
will ask for a real name, account name, terminal type and password (verifying
|
||||||
the password once) and then create the directory /user/(account name) and
|
the password once) and then create the directory \fB/home/\fIaccount_name\fR.
|
||||||
copy a template
|
.BR newuser
|
||||||
.B gshrc
|
will also copy all the regular files from the
|
||||||
into that directory. Then it will add the user to
|
.BR /var/adm/newuser/skel
|
||||||
|
directory into the \fB/home/\fIaccount_name\fR directory.
|
||||||
|
It will not recurse.
|
||||||
|
Finally, it will add the appropriate entry to
|
||||||
.B /etc/passwd
|
.B /etc/passwd
|
||||||
and exit.
|
and then exit.
|
||||||
.PP
|
.PP
|
||||||
If the
|
If the
|
||||||
.B -v
|
.B -v
|
||||||
(verify) flag is selected, everything is done as normal, except
|
(verify) flag is selected, or if invoked as
|
||||||
that the new entry is appended to
|
.BR newuserv ,
|
||||||
.B /var/adm/newuser/newusers
|
everything is done as normal, except that the new entry is appended to
|
||||||
|
.B /var/adm/newuser/pending
|
||||||
instead of being appended to
|
instead of being appended to
|
||||||
.BR /etc/passwd ". "
|
.BR /etc/passwd .
|
||||||
.LP
|
.LP
|
||||||
.SH FILES
|
Accounts are normally created with group ID 100. The
|
||||||
.nf
|
.B -g
|
||||||
.BR /var/adm/newuser/newid " -- This file holds the next available"
|
flag overrides this group ID.
|
||||||
userID. newuser will increment it as necessary.
|
.LP
|
||||||
.BR /var/adm/newuser/gshrc " -- This is the 'template' gshrc file"
|
Both
|
||||||
that all new users will get. In addition to this, newuser will append
|
.BR newuser
|
||||||
'set' commands to set $home and $user.
|
and
|
||||||
.BR /etc/passwd " -- Not required if you use -v. But what's the point"
|
.BR newuserv
|
||||||
in newuser if you don't have it? :)
|
will log created accounts via
|
||||||
.BR /user/ " -- Has to exist. This is where the user's home directories"
|
.BR syslogd (8)
|
||||||
go.
|
using the auth.info facility.
|
||||||
.fi
|
|
||||||
.LP
|
.LP
|
||||||
.B newuser
|
.B newuser
|
||||||
will time out after 60 seconds of operation.
|
will time out after 60 seconds of operation.
|
||||||
.LP
|
.SH FILES
|
||||||
|
.IP \fB/home\fR
|
||||||
|
The directory where new user home directories will be placed.
|
||||||
|
.IP \fB/var/adm/newuser/newid\fR
|
||||||
|
The text file containing the next available user ID. It must consist
|
||||||
|
of exactly one line, containing only a decimal number.
|
||||||
|
.BR newuser
|
||||||
|
will update this file as required.
|
||||||
|
.IP \fB/var/adm/newuser/pending\fR
|
||||||
|
This file contains all of the
|
||||||
|
.BR /etc/passwd
|
||||||
|
entries that are waiting for approval before activation.
|
||||||
|
.IP \fB/var/adm/newuser/skel\fR
|
||||||
|
All regular files in this directory will be copied to the newly created
|
||||||
|
home directory.
|
||||||
|
.SH BUGS
|
||||||
|
.BR newuser
|
||||||
|
should create a lock file in
|
||||||
|
.BR /var/locks
|
||||||
|
to ensure that a race condition with multiple instantiations is avoided.
|
||||||
|
They are currently possible.
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
.nf
|
James Brookes. Maintained by Devin Reade.
|
||||||
James Brookes
|
|
||||||
jamesb@cscihp.ecst.csuchico.edu
|
|
||||||
.fi
|
|
||||||
|
|
|
@ -1,85 +1,114 @@
|
||||||
/* */
|
/*
|
||||||
/* newuser - add a new user to the system, v1.1 -- James Brookes */
|
* newuser - add a new user to the system -- James Brookes
|
||||||
/* */
|
*
|
||||||
/* Changes from 1.0 */
|
* $Id: newuser.c,v 1.3 1999/02/15 00:22:11 gdr-ftp Exp $
|
||||||
/* */
|
*
|
||||||
/* * Removed code to add "set $home/$user" stuff to new user's gshrc */
|
* Changes for version 1.2 (Modifications by Devin Reade)
|
||||||
/* file, per request of Phil Vandry. */
|
* - account home directories are now made in /home rather than /user
|
||||||
/* * Added restriction that the new password entered must be greater */
|
* - made all the routines internal to this file to be class 'static'
|
||||||
/* than four characters. */
|
* - fit sources into GNO base distribution builds
|
||||||
/* * Newuser will now try multiple times to open up the /etc/passwd */
|
* - added checks for parsing NEWID_FILE
|
||||||
/* file, just as passwd itself does. */
|
* - added various conchecks to prevent buffer overflow and similar
|
||||||
/* */
|
* problems
|
||||||
/* Some code borrowed from Eric Shepard's passwd source. */
|
* - ensure the password is at least MIN_PASSWD_LEN characters long
|
||||||
/* */
|
* - don't set the terminal type; that is the responsibility of
|
||||||
/* files: /var/adm/newuser/newid */
|
* initd/getty.
|
||||||
/* /var/adm/newuser/newusers */
|
* - instead of creating explicit files in the user's home directory,
|
||||||
/* /var/adm/newuser/gshrc */
|
* copy every file that is in the SKELETONS directory.
|
||||||
/* /user/ */
|
* - account creation is now logged via syslogd
|
||||||
/* */
|
* - added -g flag for selecting non-default group ids
|
||||||
|
* - check to ensure that the new uid returned by get_next_uid is
|
||||||
/*#pragma optimize -1 */
|
* not already in use; if it is, then log a warning via syslog,
|
||||||
#pragma stacksize 512
|
* skip it, and get another uid
|
||||||
|
*
|
||||||
|
* Changes for version 1.1
|
||||||
|
*
|
||||||
|
* * Removed code to add "set $home/$user" stuff to new user's gshrc
|
||||||
|
* file, per request of Phil Vandry.
|
||||||
|
* * Added restriction that the new password entered must be greater
|
||||||
|
* than four characters.
|
||||||
|
* * Newuser will now try multiple times to open up the /etc/passwd
|
||||||
|
* file, just as passwd itself does.
|
||||||
|
*
|
||||||
|
* Original version 1.0:
|
||||||
|
* * Some code borrowed from Eric Shepard's passwd source.
|
||||||
|
*
|
||||||
|
* files: /var/adm/newuser/newid
|
||||||
|
* /var/adm/newuser/newusers
|
||||||
|
* /var/adm/newuser/gshrc
|
||||||
|
* /user/
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <paths.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sgtty.h>
|
#include <sgtty.h>
|
||||||
#include <gno/gno.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <syslog.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <gno/gno.h>
|
||||||
|
#include <gno/contrib.h>
|
||||||
|
|
||||||
#pragma lint -1
|
#define HOME "/home"
|
||||||
|
#define NEWID_FILE "/var/adm/newuser/newid" /* next ID to assign */
|
||||||
|
#define NEWUSERS_FILE "/var/adm/newuser/pending" /* addtions "on hold */
|
||||||
|
#define SKELETONS "/var/adm/newuser/skel" /* files to copy */
|
||||||
|
#define DEFAULT_SHELL _PATH_GSHELL /* default shell */
|
||||||
|
|
||||||
char *getpass(char *prompt);
|
#define MIN_PASSWD_LEN 5 /* minimum length of cleartext password */
|
||||||
char *crypt(char *key, char *salt);
|
#define DEFAULT_GID 100 /* default group ID assigned to new user */
|
||||||
|
#define ACCT_NAME_LEN 32 /* max # of chars in account name, +1 */
|
||||||
void time_out(void);
|
/* We later truncate the account name to */
|
||||||
void makesalt(char *salt, long seed);
|
/* to no more than 8 chars. */
|
||||||
int get_next_uid(void);
|
#define REAL_NAME_LEN 31 /* max # of chars in real name, +1 */
|
||||||
void getpassword(char *password, char *salt, char *passstring);
|
#define CRYPT_PASS_LEN 14 /* max # of chars in encrypted passwd +1 */
|
||||||
int bad_name(char *acct_name);
|
#define MAX_TRIES 3 /* max # of trials for opening passwd file */
|
||||||
void myfgets(char *string, int maxchar, FILE *FilePtr);
|
|
||||||
FILE *smartopen(char *file, char *mode);
|
|
||||||
|
|
||||||
#define NEWID_FILE "/var/adm/newuser/newid"
|
|
||||||
#define NEWUSERS_FILE "/var/adm/newuser/newusers"
|
|
||||||
#define NEWGSHRC_FILE "/var/adm/newuser/gshrc"
|
|
||||||
|
|
||||||
#define DEFAULT_GID 2 /* default group ID assigned to new user */
|
|
||||||
#define ACCT_NAME_LEN 8 /* max # of chars in account name */
|
|
||||||
#define REAL_NAME_LEN 30 /* max # of chars in real name */
|
|
||||||
#define TERM_TYPE_LEN 8 /* max # of chars in terminal type */
|
|
||||||
#define MAX_TRIES 3 /* max # of trials for opening passwd file */
|
|
||||||
|
|
||||||
#ifndef FALSE
|
#ifndef FALSE
|
||||||
#define FALSE 0
|
#define FALSE 0
|
||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char acct_name[ACCT_NAME_LEN+1],
|
static void time_out(void);
|
||||||
buffer[80],
|
static void makesalt(char *salt, long seed);
|
||||||
name[REAL_NAME_LEN+1],
|
static uid_t get_next_uid(void);
|
||||||
pass1[14], pass2[14],
|
static int getpassword(char *, int, char *, char *);
|
||||||
salt[3],
|
static int bad_name(char *acct_name);
|
||||||
scratch[256],
|
static void mygets(char *string, int maxchar);
|
||||||
term_type[TERM_TYPE_LEN+1];
|
static FILE * smartopen(char *file, char *mode);
|
||||||
|
|
||||||
|
static char acct_name[ACCT_NAME_LEN];
|
||||||
|
static char name[REAL_NAME_LEN];
|
||||||
|
static char pass1[CRYPT_PASS_LEN];
|
||||||
|
static char pass2[CRYPT_PASS_LEN];
|
||||||
|
static char salt[3];
|
||||||
|
|
||||||
|
static char newhome[PATH_MAX];
|
||||||
|
|
||||||
static unsigned char salttab[] = /* table of chars for salt */
|
static unsigned char salttab[] = /* table of chars for salt */
|
||||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
|
|
||||||
void time_out(void)
|
#pragma databank 1
|
||||||
|
static void
|
||||||
{
|
time_out(void)
|
||||||
printf("\nnewuser timed out after 60 seconds.\n");
|
{
|
||||||
exit(1);
|
printf("\nnewuser timed out after 60 seconds.\n");
|
||||||
}
|
exit(1);
|
||||||
|
}
|
||||||
|
#pragma databank 0
|
||||||
|
|
||||||
/* Borrowed from Eric's passwd.cc */
|
/* Borrowed from Eric's passwd.cc */
|
||||||
|
|
||||||
void
|
static void
|
||||||
makesalt(char *salt, long seed)
|
makesalt(char *salt, long seed)
|
||||||
{
|
{
|
||||||
int num = 2;
|
int num = 2;
|
||||||
|
@ -89,14 +118,27 @@ makesalt(char *salt, long seed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/*
|
||||||
|
* get_next_uid()
|
||||||
|
*
|
||||||
|
* Return the next available user id from NEWID_FILE, and update the
|
||||||
|
* NEWID_FILE under the assumption that the returned id will be assigned
|
||||||
|
* in /etc/passwd. Abort on any errors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static uid_t
|
||||||
get_next_uid(void)
|
get_next_uid(void)
|
||||||
{
|
{
|
||||||
FILE *FPtr;
|
FILE *FPtr;
|
||||||
int uid;
|
uid_t uid;
|
||||||
|
|
||||||
FPtr = fopen(NEWID_FILE,"r+");
|
if ((FPtr = fopen(NEWID_FILE,"r+")) == NULL) {
|
||||||
fscanf(FPtr,"%d\n",&uid);
|
err(1, "failed to id file %s", NEWID_FILE);
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
if (fscanf(FPtr,"%d\n",&uid) != 1) {
|
||||||
|
errx(1, "scan of %s failed", NEWID_FILE);
|
||||||
|
}
|
||||||
rewind(FPtr);
|
rewind(FPtr);
|
||||||
fprintf(FPtr,"%d\n",uid+1);
|
fprintf(FPtr,"%d\n",uid+1);
|
||||||
fclose(FPtr);
|
fclose(FPtr);
|
||||||
|
@ -104,56 +146,120 @@ get_next_uid(void)
|
||||||
return(uid);
|
return(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/*
|
||||||
getpassword(char *password, char *salt, char *passstring)
|
* getpassword
|
||||||
|
* prompt for a password with <passstrings>. put the encrypted
|
||||||
|
* password into <password>, aborting if it's length is greater
|
||||||
|
* than <passwdlen>-1. Return the length of the plaintext password.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
getpassword(char *password, int passwdlen, char *salt, char *passstring)
|
||||||
{
|
{
|
||||||
char *pass, *passcode;
|
char *pass, *passcode;
|
||||||
|
int length_clear, length_crypt, quit_now;
|
||||||
|
|
||||||
pass = getpass(passstring);
|
pass = getpass(passstring);
|
||||||
passcode = crypt(pass,salt);
|
|
||||||
|
if (*pass == '\0') { /* ^D */
|
||||||
|
quit_now = 1;
|
||||||
|
} else {
|
||||||
|
quit_now = 0;
|
||||||
|
length_clear = strlen(pass);
|
||||||
|
passcode = crypt(pass,salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* zero out the cleartext password */
|
||||||
|
for (length_crypt=0; length_crypt<_PASSWORD_LEN; length_crypt++) {
|
||||||
|
if (pass[length_crypt] == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pass[length_crypt] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* password not given? */
|
||||||
|
if (quit_now) {
|
||||||
|
errx(1, "aborted");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length_crypt > passwdlen-1) {
|
||||||
|
errx(1,
|
||||||
|
"internal error: encrypted password length (%d) > buffer length (%d)",
|
||||||
|
length_crypt+1, passwdlen);
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
strcpy(password,passcode);
|
strcpy(password,passcode);
|
||||||
|
return length_clear;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
/*
|
||||||
|
* bad_name()
|
||||||
|
*
|
||||||
|
* return nonzero if <acct_name> is unsuitable as an account name. It must
|
||||||
|
* be between 2 and 8 characters long, start with a lower case letter, and
|
||||||
|
* contain only lower case letters or digits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
bad_name(char *acct_name)
|
bad_name(char *acct_name)
|
||||||
{
|
{
|
||||||
if (!isalpha(*acct_name++))
|
int len;
|
||||||
|
|
||||||
|
len = strlen(acct_name);
|
||||||
|
if ((len < 2) || (len > 8) || !islower(*acct_name)) {
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
|
}
|
||||||
|
len = 1;
|
||||||
|
acct_name++;
|
||||||
|
|
||||||
while (*acct_name != '\0')
|
while (*acct_name != '\0') {
|
||||||
if (!isalnum(*acct_name++))
|
len++;
|
||||||
|
if ((len > 8) || (!islower(*acct_name) && !isdigit(*acct_name))) {
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
|
}
|
||||||
|
acct_name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* it's a good account name */
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
myfgets(char *string, int maxchar, FILE *FilePtr)
|
mygets(char *string, int maxchar)
|
||||||
{
|
{
|
||||||
int last_char;
|
int len;
|
||||||
char *tmp_buf;
|
|
||||||
|
fgets(string, maxchar, stdin);
|
||||||
tmp_buf = (char *) malloc (256);
|
fflush(stdin);
|
||||||
|
if (*string == 0x00) { /* ^D */
|
||||||
maxchar++;
|
goto fail;
|
||||||
fgets(tmp_buf,maxchar,FilePtr);
|
}
|
||||||
if (*tmp_buf == 0x00) /* ^D */
|
len = strlen(string);
|
||||||
exit(1);
|
if (len == 0) {
|
||||||
last_char = strlen(tmp_buf)-1;
|
goto fail;
|
||||||
|
}
|
||||||
/* remove terminating \n if necessary */
|
|
||||||
|
/* remove terminating \n if necessary */
|
||||||
if ((tmp_buf[last_char] == '\n') || (tmp_buf[last_char] == '\r'))
|
if ((string[len-1] == '\r') || (string[len-1] == '\n')) {
|
||||||
tmp_buf[last_char] = '\0';
|
string[len-1] = '\0';
|
||||||
|
len--;
|
||||||
strcpy(string,tmp_buf);
|
}
|
||||||
fflush(stdin);
|
|
||||||
free(tmp_buf);
|
/* check for empty string */
|
||||||
|
if ((len == 0)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
errx(1, "aborted");
|
||||||
|
/*NOTREACHED*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try multiple times to open /etc/passwd file */
|
/* try multiple times to open /etc/passwd file */
|
||||||
|
|
||||||
FILE *
|
static FILE *
|
||||||
smartopen(char *file, char *mode)
|
smartopen(char *file, char *mode)
|
||||||
{
|
{
|
||||||
FILE *FOutPtr;
|
FILE *FOutPtr;
|
||||||
|
@ -171,15 +277,54 @@ smartopen(char *file, char *mode)
|
||||||
return(FOutPtr);
|
return(FOutPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage (void)
|
||||||
|
{
|
||||||
|
printf("Usage: newuser [-v] [-g gid]\n");
|
||||||
|
printf(" newuserv [-v] [-g gid]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
int validate, uid;
|
int validate, ch;
|
||||||
FILE *FInPtr, *FOutPtr;
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
FILE *FOutPtr;
|
||||||
|
DIR *dirp;
|
||||||
|
struct dirent *entp;
|
||||||
struct sgttyb *s;
|
struct sgttyb *s;
|
||||||
s = (struct sgttyb *) malloc (sizeof(struct sgttyb));
|
char *srcfile;
|
||||||
|
|
||||||
|
__REPORT_STACK();
|
||||||
|
|
||||||
|
/* check usage */
|
||||||
|
gid = DEFAULT_GID;
|
||||||
|
validate = (strcmp(basename(argv[0]), "newuserv") == 0) ? TRUE : FALSE;
|
||||||
|
while ((ch = getopt(argc, argv, "vg:")) != EOF) {
|
||||||
|
switch(ch) {
|
||||||
|
case 'g':
|
||||||
|
if ((gid = atoi(optarg)) == 0) {
|
||||||
|
gid = DEFAULT_GID;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
validate = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argc - optind > 0) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set up for system logging */
|
||||||
|
openlog(basename(argv[0]), LOG_PID | LOG_NDELAY, LOG_AUTH | LOG_INFO);
|
||||||
|
|
||||||
|
|
||||||
|
/* set up signal handlers */
|
||||||
signal(SIGINT,SIG_IGN);
|
signal(SIGINT,SIG_IGN);
|
||||||
signal(SIGHUP,SIG_IGN);
|
signal(SIGHUP,SIG_IGN);
|
||||||
signal(SIGQUIT,SIG_IGN);
|
signal(SIGQUIT,SIG_IGN);
|
||||||
|
@ -187,40 +332,34 @@ main (int argc, char **argv)
|
||||||
signal(SIGALRM,time_out);
|
signal(SIGALRM,time_out);
|
||||||
|
|
||||||
/* Set proper erase character */
|
/* Set proper erase character */
|
||||||
|
s = malloc (sizeof(struct sgttyb));
|
||||||
gtty(STDIN_FILENO,s);
|
gtty(STDIN_FILENO,s);
|
||||||
s->sg_erase = 0x7f;
|
s->sg_erase = 0x7f;
|
||||||
stty(STDIN_FILENO,s);
|
stty(STDIN_FILENO,s);
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
validate = FALSE;
|
|
||||||
|
|
||||||
if (argc == 2 && !strcmp(argv[1],"-v"))
|
|
||||||
validate = TRUE;
|
|
||||||
else if (argc == 1);
|
|
||||||
else
|
|
||||||
exit(1);
|
|
||||||
|
|
||||||
/* Make sure all required files exist before going any further */
|
/* Make sure all required files exist before going any further */
|
||||||
|
if (access(NEWID_FILE, R_OK | W_OK) != 0) {
|
||||||
if ((FInPtr = fopen(NEWID_FILE,"r+")) == NULL) {
|
errx(1, "no read/write access for %s", NEWID_FILE);
|
||||||
fprintf(stderr,"unable to open %s; exiting.\n",NEWID_FILE);
|
}
|
||||||
exit(1);
|
if (access(HOME, R_OK | W_OK | X_OK) != 0) {
|
||||||
|
errx(1, "no read/write/execute access for %s", HOME);
|
||||||
|
}
|
||||||
|
if (access(SKELETONS, R_OK | X_OK) != 0) {
|
||||||
|
errx(1, "no read/execute access for %s", SKELETONS);
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(FInPtr);
|
printf("\n\tYou have requested a new account. You will be required\n");
|
||||||
|
printf("\tto enter the account information, after which ");
|
||||||
if ((FInPtr = fopen(NEWGSHRC_FILE,"r+")) == NULL) {
|
if (validate) {
|
||||||
fprintf(stderr,"unable to open %s; exiting.\n",NEWGSHRC_FILE);
|
printf("your account\n\tWill be placed on hold until it is verified\n");
|
||||||
exit(1);
|
} else {
|
||||||
|
printf("you will be\n\table to log into the system\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(FInPtr);
|
/* Get the user's "Real Name" for the GECOS field */
|
||||||
|
printf("\nReal Name: ");
|
||||||
/* Get information */
|
mygets(name, REAL_NAME_LEN);
|
||||||
|
|
||||||
printf("\nReal Name: ");
|
|
||||||
myfgets(name,REAL_NAME_LEN,stdin);
|
|
||||||
|
|
||||||
/* Get login name. If the login name is duplicate, prompt for */
|
/* Get login name. If the login name is duplicate, prompt for */
|
||||||
/* a new login name. If the login name would call for the */
|
/* a new login name. If the login name would call for the */
|
||||||
|
@ -232,91 +371,142 @@ main (int argc, char **argv)
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
printf("Login Name: ");
|
printf("Login Name: ");
|
||||||
myfgets(acct_name,ACCT_NAME_LEN,stdin);
|
mygets(acct_name, ACCT_NAME_LEN);
|
||||||
printf("\n\n(login name: '%s')\n\n",acct_name);
|
#if 0
|
||||||
if (getpwnam(acct_name) != NULL) {
|
printf("\n\n(login name: '%s')\n\n", acct_name);
|
||||||
printf("Duplicate username: please choose another.\n");
|
#endif
|
||||||
} else if (bad_name(acct_name)) {
|
|
||||||
printf("\n** Invalid username: please choose a name comprised of\n");
|
if (bad_name(acct_name)) {
|
||||||
printf(" alphanumeric characters which starts with an alphabetic\n");
|
puts("\nInvalid login name. Login names must be between 2 and 8");
|
||||||
printf(" character.\n");
|
puts("characters long, must start with a lower case letter, and");
|
||||||
|
puts("must consist of only digits and lower case letters.\n");
|
||||||
|
} else if (getpwnam(acct_name) != NULL) {
|
||||||
|
printf("The login name \"%s\" is already in use.\n", acct_name);
|
||||||
|
printf("Please choose another.\n");
|
||||||
} else {
|
} else {
|
||||||
break;
|
#if 0
|
||||||
|
/* bad_name ensures that strlen(acct_name) < 8 */
|
||||||
|
if (sizeof(HOME) + strlen(acct_name) > PATH_MAX) {
|
||||||
|
/* what are the chances? */
|
||||||
|
err(1, "buffer overflow at line %d", __LINE__);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
sprintf(newhome, "%s/%s", HOME, acct_name);
|
||||||
|
if (access(newhome, X_OK) == 0) {
|
||||||
|
printf("The login name \"%s\" has already been requested by someone else\n",
|
||||||
|
acct_name);
|
||||||
|
printf("Please choose another.\n");
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Terminal Type: ");
|
/* close the file descriptor we have open on /etc/passswd */
|
||||||
myfgets(term_type,TERM_TYPE_LEN,stdin);
|
endpwent();
|
||||||
|
|
||||||
/* Get password of > 4 chars, with verification */
|
|
||||||
|
|
||||||
|
/* Get password of >= MIN_PASSWD_LEN chars, with verification */
|
||||||
makesalt(salt, rand());
|
makesalt(salt, rand());
|
||||||
while(1) {
|
while(1) {
|
||||||
getpassword(pass1,salt,"Password: ");
|
if (getpassword(pass1, CRYPT_PASS_LEN, salt, "Password: ")
|
||||||
getpassword(pass2,salt,"Verify: ");
|
< MIN_PASSWD_LEN) {
|
||||||
if (!strcmp(pass1,pass2) && (strlen(pass1) > 4)) {
|
printf("The password must be at least %d characters long.\nTry again.\n",
|
||||||
|
MIN_PASSWD_LEN);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
getpassword(pass2, CRYPT_PASS_LEN, salt,"Verify: ");
|
||||||
|
if (strcmp(pass1,pass2) == 0) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
printf("*** Failed verification.\n");
|
printf("Passwords don't match. Try again.\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uid = get_next_uid(); /* get and update next free ID# */
|
/*
|
||||||
|
* Get the next free uid and update the NEWID_FILE. When we return from
|
||||||
/* make home directory */
|
* this routine, we are now past the point of no return; if we fail
|
||||||
|
* anything, then we have used up a user id.
|
||||||
sprintf(scratch,"mkdir -s /user/%s",acct_name);
|
*/
|
||||||
exec("/bin/mkdir",scratch);
|
while(1) {
|
||||||
sleep(2);
|
uid = get_next_uid();
|
||||||
|
if (getpwuid(uid) == NULL) {
|
||||||
/* and copy default gshrc to it */
|
break;
|
||||||
|
} else {
|
||||||
sprintf(scratch,"/user/%s/gshrc",acct_name);
|
syslog(LOG_WARNING, "uid %d is already in use; skipping", uid);
|
||||||
FOutPtr = fopen(scratch,"w");
|
}
|
||||||
|
|
||||||
FInPtr = fopen(NEWGSHRC_FILE,"r");
|
|
||||||
|
|
||||||
while(fgets(buffer,80,FInPtr) != NULL) {
|
|
||||||
fputs(buffer,FOutPtr);
|
|
||||||
}
|
}
|
||||||
fclose(FInPtr);
|
|
||||||
|
|
||||||
/* update default gshrc to have correct $home, $user, and $term */
|
/*
|
||||||
|
* make the home directory
|
||||||
/* Phil asked that this be removed, so... :) */
|
*/
|
||||||
#if 0
|
if (mkdir(newhome) != 0) {
|
||||||
fprintf(FOutPtr,"set home=/user/%s\n",acct_name);
|
err(1, "failed to create directory %s", newhome);
|
||||||
fprintf(FOutPtr,"set user=%s\n",acct_name);
|
}
|
||||||
#endif
|
|
||||||
fprintf(FOutPtr,"set term=%s\n",term_type);
|
|
||||||
|
|
||||||
#if 0
|
/*
|
||||||
fprintf(FOutPtr,"export home user term\n");
|
* Copy each of the files in SKELETONS into the user's home directory.
|
||||||
#else
|
* Initially change directory into SKELETONS so that we can use partial
|
||||||
fprintf(FOutPtr,"export term\n");
|
* pathnames when copying the files into $HOME.
|
||||||
#endif
|
*/
|
||||||
fclose(FOutPtr);
|
putchar('\n');
|
||||||
|
if (chdir(SKELETONS) != 0) {
|
||||||
|
err(1, "couldn't change directory into %s", SKELETONS);
|
||||||
|
/*NOTREACHED*/
|
||||||
|
}
|
||||||
|
if ((dirp = opendir(SKELETONS)) == NULL) {
|
||||||
|
err(1, "read of directory %d failed", SKELETONS);
|
||||||
|
}
|
||||||
|
while ((entp = readdir(dirp)) != NULL) {
|
||||||
|
|
||||||
|
/* only copy regular files, and don't recurse through subdirectories */
|
||||||
|
if (entp->d_type == DT_DIR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip entries for current and parent directories */
|
||||||
|
srcfile = entp->d_name;
|
||||||
|
if (((srcfile[0]=='.') && (srcfile[1]=='\0')) ||
|
||||||
|
((srcfile[0]=='.') && (srcfile[1]=='.') && (srcfile[2]=='\0'))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* do the copy */
|
||||||
|
srcfile = LC_CopyFile(srcfile, newhome, LC_COPY_DATA | LC_COPY_REZ);
|
||||||
|
if (srcfile == NULL) {
|
||||||
|
err(1, "couldn't copy %s", entp->d_name);
|
||||||
|
} else {
|
||||||
|
printf("creating %s\n", srcfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
closedir(dirp);
|
||||||
|
|
||||||
|
/* Save the password information away. */
|
||||||
|
|
||||||
if (!validate) { /* no validation, so append new entry to /etc/passwd */
|
if (!validate) { /* no validation, so append new entry to /etc/passwd */
|
||||||
FOutPtr = smartopen("/etc/passwd","a");
|
FOutPtr = smartopen(_PATH_PASSWD, "a");
|
||||||
if (FOutPtr == NULL) {
|
if (FOutPtr == NULL) {
|
||||||
fprintf(stderr,"Trouble opening /etc/passwd file.\nExiting\n");
|
err(1, "couldn't open %s", _PATH_PASSWD);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(FOutPtr,"%s:%s:%d:%d:%s:/user/%s:/bin/gsh\n",acct_name,pass1,
|
fprintf(FOutPtr, "%s:%s:%d:%d:%s:%s/%s:%s\n",
|
||||||
uid,DEFAULT_GID,name,acct_name);
|
acct_name, pass1, uid, gid, name, HOME, acct_name, DEFAULT_SHELL);
|
||||||
fclose(FOutPtr);
|
fclose(FOutPtr);
|
||||||
|
syslog(LOG_INFO, "created account %s", acct_name);
|
||||||
printf("You may now log in.\n");
|
printf("You may now log in.\n");
|
||||||
|
|
||||||
} else { /* validation selected -- so append new entry to NEWUSERS_FILE */
|
} else { /* validation selected -- so append new entry to NEWUSERS_FILE */
|
||||||
|
|
||||||
FOutPtr = fopen(NEWUSERS_FILE,"a");
|
if ((FOutPtr = fopen(NEWUSERS_FILE, "a")) == NULL) {
|
||||||
fprintf(FOutPtr,"%s:%s:%d:0:%s:/user/%s:/bin/gsh\n",acct_name,pass1,
|
err(1, "couldn't open %s", NEWUSERS_FILE);
|
||||||
uid,name,acct_name);
|
}
|
||||||
|
fprintf(FOutPtr,"%s:%s:%d:%d:%s:%s/%s:%s\n",
|
||||||
|
acct_name, pass1, uid, gid, name, HOME, acct_name, DEFAULT_SHELL);
|
||||||
fclose(FOutPtr);
|
fclose(FOutPtr);
|
||||||
printf("Try back in 24 hours.\n");
|
syslog(LOG_INFO, "created account %s pending validation", acct_name);
|
||||||
|
printf("\nYour account will be available after the system administrator");
|
||||||
|
printf("has had a\nchance to review it.\n");
|
||||||
}
|
}
|
||||||
|
closelog();
|
||||||
|
|
||||||
exit(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
23
usr.sbin/newuser/newuser.desc
Normal file
23
usr.sbin/newuser/newuser.desc
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
Name: newuser
|
||||||
|
Version: 1.2
|
||||||
|
Shell: GNO
|
||||||
|
Author: James Brookes. Maintained by Devin Reade.
|
||||||
|
Contact: gdr@trenco.gno.org
|
||||||
|
Where: /usr/sbin
|
||||||
|
FTP: ftp.gno.org
|
||||||
|
|
||||||
|
Create a home directory in /home with a template $HOME/gshrc and $HOME/glogin
|
||||||
|
for a new user, and add the user's entry into the /etc/passwd file for
|
||||||
|
immediate access. See also newuserv.
|
||||||
|
|
||||||
|
Name: newuserv
|
||||||
|
Version: 1.2
|
||||||
|
Shell: GNO
|
||||||
|
Author: James Brookes. Maintained by Devin Reade.
|
||||||
|
Contact: gdr@trenco.gno.org
|
||||||
|
Where: /usr/sbin
|
||||||
|
FTP: ftp.gno.org
|
||||||
|
|
||||||
|
Create a home directory in /home with a template $HOME/gshrc and $HOME/glogin
|
||||||
|
for a new user, and add the user's entry into the /var/adm/newuser/newusers
|
||||||
|
file for validation by the system operator. See also newuserv.
|
18
usr.sbin/newuser/newuser.rez
Normal file
18
usr.sbin/newuser/newuser.rez
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/*
|
||||||
|
* $Id: newuser.rez,v 1.1 1999/02/15 00:22:11 gdr-ftp Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Types.Rez"
|
||||||
|
#include "builddate.rez"
|
||||||
|
|
||||||
|
resource rVersion (0x1, purgeable3, nocrossbank) {
|
||||||
|
|
||||||
|
{ 1, 2, 0, /* version */
|
||||||
|
release, /* development|alpha|beta|final|release */
|
||||||
|
0 /* non-final release number */
|
||||||
|
},
|
||||||
|
verUS,
|
||||||
|
"newuser/newuserv",
|
||||||
|
"create new accounts\n"
|
||||||
|
BUILD_DATE
|
||||||
|
};
|
|
@ -1,16 +0,0 @@
|
||||||
#pragma optimize -1
|
|
||||||
#pragma stacksize 256
|
|
||||||
|
|
||||||
/* */
|
|
||||||
/* newverify.c - a simple program to launch newuser with the -v option */
|
|
||||||
/* */
|
|
||||||
|
|
||||||
#include<stdio.h>
|
|
||||||
#include<stdlib.h>
|
|
||||||
#include<gno/gno.h>
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
|
|
||||||
{
|
|
||||||
execve("/usr/sbin/newuser","newuser -v");
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user