* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: pw_user.c,v 1.1.1.3 1996/12/10 23:59:02 joerg Exp $
+ * $Id: pw_user.c,v 1.5 1996/12/17 14:15:35 davidn Exp $
*/
#include <unistd.h>
#include <sys/param.h>
#include <dirent.h>
#include <termios.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <md5.h>
#include "pw.h"
#include "bitmap.h"
#include "pwupd.h"
static char *pw_homepolicy(struct userconf * cnf, struct cargs * args, char const * user);
static char *pw_shellpolicy(struct userconf * cnf, struct cargs * args, char *newshell);
static char *pw_password(struct userconf * cnf, struct cargs * args, char const * user);
-static char *pw_checkname(char *name, int gecos);
static char *shell_path(char const * path, char *shells[], char *sh);
static void rmat(uid_t uid);
cnf->default_group = newstr(grp->gr_name);
}
if ((arg = getarg(args, 'L')) != NULL)
- cnf->default_class = pw_checkname(arg->val, 0);
+ cnf->default_class = pw_checkname((u_char *)arg->val, 0);
if ((arg = getarg(args, 'G')) != NULL && arg->val) {
int i = 0;
return EXIT_SUCCESS;
}
if ((a_name = getarg(args, 'n')) != NULL)
- pwd = getpwnam(pw_checkname(a_name->val, 0));
+ pwd = getpwnam(pw_checkname((u_char *)a_name->val, 0));
a_uid = getarg(args, 'u');
if (a_uid == NULL) {
if ((arg = getarg(args, 'l')) != NULL) {
if (strcmp(pwd->pw_name, "root") == 0)
cmderr(EX_DATAERR, "can't rename `root' account\n");
- pwd->pw_name = pw_checkname(arg->val, 0);
+ pwd->pw_name = pw_checkname((u_char *)arg->val, 0);
}
if ((arg = getarg(args, 'u')) != NULL && isdigit(*arg->val)) {
pwd->pw_uid = (uid_t) atol(arg->val);
* Shared add/edit code
*/
if ((arg = getarg(args, 'c')) != NULL)
- pwd->pw_gecos = pw_checkname(arg->val, 1);
+ pwd->pw_gecos = pw_checkname((u_char *)arg->val, 1);
if ((arg = getarg(args, 'h')) != NULL) {
if (strcmp(arg->val, "-") == 0)
/*
* Calculate a salt value
*/
- srandom((unsigned) (time(NULL) | getpid()));
+ srandom((unsigned) (time(NULL) ^ getpid()));
for (i = 0; i < 8; i++)
salt[i] = chars[random() % 63];
salt[i] = '\0';
return strcpy(buf, crypt(password, salt));
}
+#if defined(__FreeBSD__)
+
+#if defined(USE_MD5RAND)
+u_char *
+pw_getrand(u_char *buf, int len) /* cryptographically secure rng */
+{
+ int i;
+ for (i=0;i<len;i+=16) {
+ u_char ubuf[16];
+
+ MD5_CTX md5_ctx;
+ struct timeval tv, tvo;
+ struct rusage ru;
+ int n=0;
+ int t;
+
+ MD5Init (&md5_ctx);
+ t=getpid();
+ MD5Update (&md5_ctx, (u_char*)&t, sizeof t);
+ t=getppid();
+ MD5Update (&md5_ctx, (u_char*)&t, sizeof t);
+ gettimeofday (&tvo, NULL);
+ do {
+ getrusage (RUSAGE_SELF, &ru);
+ MD5Update (&md5_ctx, (u_char*)&ru, sizeof ru);
+ gettimeofday (&tv, NULL);
+ MD5Update (&md5_ctx, (u_char*)&tv, sizeof tv);
+ } while (n++<20 || tv.tv_usec-tvo.tv_usec<100*1000);
+ MD5Final (ubuf, &md5_ctx);
+ memcpy(buf+i, ubuf, MIN(16, len-n));
+ }
+ return buf;
+}
+
+#else /* Use random device (preferred) */
+
+static u_char *
+pw_getrand(u_char *buf, int len)
+{
+ int fd;
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd==-1)
+ cmderr(EX_OSFILE, "can't open /dev/urandom: %s\n", strerror(errno));
+ else if (read(fd, buf, len)!=len)
+ cmderr(EX_IOERR, "read error on /dev/urandom\n");
+ close(fd);
+ return buf;
+}
+
+#endif
+
+#else /* Portable version */
+
+static u_char *
+pw_getrand(u_char *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ unsigned val = random();
+ /* Use all bits in the random value */
+ buf[i]=(u_char)((val >> 24) ^ (val >> 16) ^ (val >> 8) ^ val);
+ }
+ return buf;
+}
+
+#endif
static char *
pw_password(struct userconf * cnf, struct cargs * args, char const * user)
{
int i, l;
char pwbuf[32];
+ u_char rndbuf[sizeof pwbuf];
switch (cnf->default_password) {
case -1: /* Random password */
- srandom((unsigned) (time(NULL) | getpid()));
+ srandom((unsigned) (time(NULL) ^ getpid()));
l = (random() % 8 + 8); /* 8 - 16 chars */
+ pw_getrand(rndbuf, l);
for (i = 0; i < l; i++)
- pwbuf[i] = chars[random() % sizeof(chars)];
+ pwbuf[i] = chars[rndbuf[i] % sizeof(chars)];
pwbuf[i] = '\0';
/*
struct group *grp = getgrgid(pwd->pw_gid);
char uname[60] = "User &", office[60] = "[None]",
wphone[60] = "[None]", hphone[60] = "[None]";
+ char acexpire[32] = "[None]", pwexpire[32] = "[None]";
+ struct tm * tptr;
if ((p = strtok(pwd->pw_gecos, ",")) != NULL) {
strncpy(uname, p, sizeof uname);
memmove(p, pwd->pw_name, l);
*p = (char) toupper(*p);
}
+ if (pwd->pw_expire > (time_t)0 && (tptr = localtime(&pwd->pw_expire)) != NULL)
+ strftime(acexpire, sizeof acexpire, "%c", tptr);
+ if (pwd->pw_change > (time_t)9 && (tptr = localtime(&pwd->pw_change)) != NULL)
+ strftime(pwexpire, sizeof pwexpire, "%c", tptr);
printf("Login Name : %-10s #%-22ld Group : %-10s #%ld\n"
" Full Name : %s\n"
" Home : %-32.32s Class : %s\n"
" Shell : %-32.32s Office : %s\n"
- "Work Phone : %-32.32s Home Phone : %s\n",
-
+ "Work Phone : %-32.32s Home Phone : %s\n"
+ "Acc Expire : %-32.32s Pwd Expire : %s\n",
pwd->pw_name, (long) pwd->pw_uid,
grp ? grp->gr_name : "(invalid)", (long) pwd->pw_gid,
uname, pwd->pw_dir, pwd->pw_class,
- pwd->pw_shell, office, wphone, hphone);
+ pwd->pw_shell, office, wphone, hphone,
+ acexpire, pwexpire);
setgrent();
j = 0;
while ((grp=getgrent()) != NULL)
return EXIT_SUCCESS;
}
-static char *
-pw_checkname(char *name, int gecos)
+char *
+pw_checkname(u_char *name, int gecos)
{
int l = 0;
char const *notch = gecos ? ":" : " ,\t:+-&#%$^()!@~*?<>=|\\/\"";
while (name[l]) {
- if (strchr(notch, name[l]) != NULL || name[l] < ' ' || name[l] > 126)
- cmderr(EX_DATAERR, (name[l]<' ' || (unsigned char)name[l] > 126)
+ if (strchr(notch, name[l]) != NULL || name[l] < ' ' ||
+ name[l] == 127 || (!gecos && name[l] & 0x80)) /* 8-bit */
+ cmderr(EX_DATAERR, (name[l]<' ' || name[l] > 126)
? "invalid character `%c' in field\n"
: "invalid character 0x$02x in field\n",
name[l]);
}
if (!gecos && l > MAXLOGNAME)
cmderr(EX_DATAERR, "name too long `%s'\n", name);
- return name;
+ return (char *)name;
}