Converted from CVS

This commit is contained in:
Mercurial Repos
2009-05-15 22:01:56 +02:00
commit b7b0017dd9
900 changed files with 203942 additions and 0 deletions

1
unix/.cvsignore Normal file
View File

@@ -0,0 +1 @@
filelist login.defs mblogin mbpasswd mbuseradd

115
unix/Makefile Normal file
View File

@@ -0,0 +1,115 @@
# Makefile for MBSE BBS under Linux
# Copyright (c) 1998, 2001 by M. Broek.
# $Id: Makefile,v 1.12 2007/05/27 12:50:48 mbse Exp $
include ../Makefile.global
SRCS = commonio.c putpwent.c salt.c sgetpwent.c xmalloc.c myname.c encrypt.c \
pwio.c shadowio.c mbpasswd.c mbuseradd.c rad64.c getdef.c pw_util.c \
mblogin.c env.c chowntty.c shell.c basename.c pwdcheck.c pwauth.c \
loginprompt.c utmp.c limits.c setupenv.c sub.c log.c setugid.c
HDRS = commonio.h putpwent.h salt.h sgetpwent.h xmalloc.h myname.h encrypt.h \
pwio.h shadowio.h mbpasswd.h mbuseradd.h rad64.h getdef.h pw_util.h \
mblogin.h env.h chowntty.h shell.h basename.h pwdcheck.h pwauth.h \
loginprompt.h utmp.h limits.h setupenv.h sub.h log.h setugid.h
MBUSERADD_OBJS = mbuseradd.o xmalloc.o
MBPASSWD_OBJS = mbpasswd.o commonio.o pwio.o shadowio.o sgetpwent.o \
xmalloc.o myname.o rad64.o salt.o getdef.o encrypt.o putpwent.o pw_util.o
MBLOGIN_OBJS = getdef.o env.o chowntty.o shell.o basename.o pwdcheck.o pwauth.o encrypt.o \
loginprompt.o utmp.o limits.o setupenv.o sub.o xmalloc.o log.o setugid.o \
mblogin.o
OTHER = Makefile login.defs.in
TARGET = mbuseradd mbpasswd mblogin
#############################################################################################################
.c.o:
${CC} ${CFLAGS} ${INCLUDES} ${DEFINES} -c $<
all: ${TARGET}
clean:
rm -f ${TARGET} *.o *.h~ *.c~ core filelist Makefile.bak
mbuseradd: ${MBUSERADD_OBJS}
${CC} -o mbuseradd ${MBUSERADD_OBJS} ${LDFLAGS} ${LIBS}
mbpasswd: ${MBPASSWD_OBJS}
${CC} -o mbpasswd ${MBPASSWD_OBJS} ${LDFLAGS} ${LIBS}
mblogin: ${MBLOGIN_OBJS}
${CC} -o mblogin ${MBLOGIN_OBJS} ${LDFLAGS} ${LIBS}
install: all
@if [ "`id -un`" != "root" ] ; then \
echo; echo " Must be root to install!"; echo; exit 3; \
fi
${INSTALL} -c -s -o ${ROWNER} -g ${RGROUP} -m 6711 mbuseradd ${BINDIR}
${INSTALL} -c -s -o ${ROWNER} -g ${RGROUP} -m 6711 mbpasswd ${BINDIR}
${INSTALL} -c -s -o ${ROWNER} -g ${RGROUP} -m 0755 mblogin ${BINDIR}
@if [ ! -f ${ETCDIR}/login.defs ] ; then \
${INSTALL} -c -o ${OWNER} -g ${GROUP} -m 0644 login.defs ${ETCDIR} ; \
echo "${INSTALL} -c -o ${OWNER} -g ${GROUP} -m 0644 login.defs ${ETCDIR}" ; \
else \
${INSTALL} -c -o ${OWNER} -g ${GROUP} -m 0644 login.defs ${ETCDIR}/login.defs.new ; \
echo "${INSTALL} -c -o ${OWNER} -g ${GROUP} -m 0644 login.defs ${ETCDIR}/login.defs.new" ; \
fi
filelist: Makefile
BASE=`pwd`; \
BASE=`basename $${BASE}`; \
(for f in ${SRCS} ${HDRS} ${OTHER} ; do echo ${PACKAGE}-${VERSION}/$${BASE}/$$f; done) >filelist
depend:
@rm -f Makefile.bak; \
mv Makefile Makefile.bak; \
sed -e '/^# DO NOT DELETE/,$$d' Makefile.bak >Makefile; \
${ECHO} '# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT' \
>>Makefile; \
${ECHO} '# Dependencies generated by make depend' >>Makefile; \
for f in ${SRCS}; \
do \
${ECHO} "Dependencies for $$f:\c"; \
${ECHO} "`basename $$f .c`.o:\c" >>Makefile; \
for h in `sed -n -e \
's/^#[ ]*include[ ]*"\([^"]*\)".*/\1/p' $$f`; \
do \
${ECHO} " $$h\c"; \
${ECHO} " $$h\c" >>Makefile; \
done; \
${ECHO} " done."; \
${ECHO} "" >>Makefile; \
done; \
${ECHO} '# End of generated dependencies' >>Makefile
# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
# Dependencies generated by make depend
commonio.o: ../config.h commonio.h
putpwent.o: ../config.h putpwent.h
salt.o: ../config.h rad64.h getdef.h
sgetpwent.o: ../config.h sgetpwent.h
xmalloc.o: ../config.h xmalloc.h
myname.o: ../config.h
encrypt.o: ../config.h encrypt.h
pwio.o: ../config.h sgetpwent.h commonio.h putpwent.h pwio.h
shadowio.o: ../config.h commonio.h shadowio.h
mbpasswd.o: ../config.h encrypt.h rad64.h myname.h xmalloc.h pwio.h shadowio.h pw_util.h getdef.h mbpasswd.h
mbuseradd.o: ../config.h xmalloc.h mbuseradd.h
rad64.o: ../config.h rad64.h
getdef.o: ../config.h getdef.h
pw_util.o: ../config.h pw_util.h
mblogin.o: ../config.h mblogin.h ../lib/users.h getdef.h env.h chowntty.h basename.h shell.h pwdcheck.h pwauth.h loginprompt.h utmp.h limits.h setupenv.h sub.h log.h setugid.h
env.o: ../config.h mblogin.h xmalloc.h
chowntty.o: ../config.h mblogin.h getdef.h chowntty.h
shell.o: ../config.h mblogin.h basename.h shell.h
basename.o: ../config.h mblogin.h basename.h
pwdcheck.o: ../config.h mblogin.h pwauth.h pwdcheck.h
pwauth.o: ../config.h mblogin.h pwauth.h getdef.h encrypt.h
loginprompt.o: ../config.h mblogin.h getdef.h xmalloc.h env.h loginprompt.h
utmp.o: ../config.h mblogin.h utmp.h
limits.o: ../config.h mblogin.h limits.h
setupenv.o: ../config.h mblogin.h getdef.h xmalloc.h env.h setupenv.h
sub.o: ../config.h mblogin.h sub.h
log.o: ../config.h mblogin.h log.h
setugid.o: ../config.h mblogin.h getdef.h setugid.h
# End of generated dependencies

17
unix/basename.c Normal file
View File

@@ -0,0 +1,17 @@
/*
* basename.c - not worth copyrighting :-). Some versions of Linux libc
* already have basename(), other versions don't. To avoid confusion,
* we will not use the function from libc and use a different name here.
* --marekm
*/
#include "../config.h"
#include "mblogin.h"
#include "basename.h"
char *Basename(char *str)
{
char *cp = strrchr(str, '/');
return cp ? cp+1 : str;
}

9
unix/basename.h Normal file
View File

@@ -0,0 +1,9 @@
/* $Id: basename.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _BASENAME_H
#define _BASENAME_H
char *Basename(char *);
#endif

123
unix/chowntty.c Normal file
View File

@@ -0,0 +1,123 @@
/*****************************************************************************
*
* $Id: chowntty.c,v 1.2 2003/08/15 20:05:36 mbroek Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <syslog.h>
#include <stdio.h>
#include <grp.h>
#include "mblogin.h"
#include <pwd.h>
#include "getdef.h"
#include "chowntty.h"
/*
* is_my_tty -- determine if "tty" is the same as TTY stdin is using
*/
int is_my_tty(const char *tty)
{
struct stat by_name, by_fd;
if (stat (tty, &by_name) || fstat (0, &by_fd))
return 0;
if (by_name.st_rdev != by_fd.st_rdev)
return 0;
else
return 1;
}
/*
* chown_tty() sets the login tty to be owned by the new user ID
* with TTYPERM modes
*/
void chown_tty(const char *tty, const struct passwd *info)
{
char buf[200], full_tty[200];
char *group; /* TTY group name or number */
struct group *grent;
gid_t gid;
/*
* * See if login.defs has some value configured for the port group
* * ID. Otherwise, use the user's primary group ID.
* */
if (! (group = getdef_str ("TTYGROUP")))
gid = info->pw_gid;
else if (group[0] >= '0' && group[0] <= '9')
gid = atoi (group);
else if ((grent = getgrnam (group)))
gid = grent->gr_gid;
else
gid = info->pw_gid;
/*
* Change the permissions on the TTY to be owned by the user with
* the group as determined above.
*/
if (*tty != '/') {
snprintf(full_tty, sizeof full_tty, "/dev/%s", tty);
tty = full_tty;
}
if (! is_my_tty (tty)) {
syslog(LOG_WARNING, "unable to determine TTY name, got %s\n", tty);
closelog();
exit (1);
}
if (chown(tty, info->pw_uid, gid) || chmod(tty, 0600)) {
snprintf(buf, sizeof buf, "Unable to change tty %s", tty);
syslog(LOG_WARNING, "unable to change tty `%s' for user `%s'\n", tty, info->pw_name);
closelog();
perror (buf);
exit(1);
}
#ifdef __linux__
/*
* Please don't add code to chown /dev/vcs* to the user logging in -
* it's a potential security hole. I wouldn't like the previous user
* to hold the file descriptor open and watch my screen. We don't
* have the *BSD revoke() system call yet, and vhangup() only works
* for tty devices (which vcs* is not). --marekm
*/
#endif
}

11
unix/chowntty.h Normal file
View File

@@ -0,0 +1,11 @@
/* $Id: chowntty.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _CHOWNTTY_H
#define _CHOWNTTY_H
int is_my_tty(const char *);
void chown_tty(const char *, const struct passwd *);
#endif

766
unix/commonio.c Normal file
View File

@@ -0,0 +1,766 @@
/*****************************************************************************
*
* $Id: commonio.c,v 1.3 2005/07/14 19:25:58 mbse Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <utime.h>
#include <sys/time.h>
#ifdef SHADOW_PASSWORD
#include <shadow.h>
#endif
#include "commonio.h"
/* local function prototypes */
static int check_link_count (const char *);
static int do_lock_file (const char *, const char *);
static FILE *fopen_set_perms (const char *, const char *, const struct stat *);
static int create_backup (const char *, FILE *);
static void free_linked_list (struct commonio_db *);
static void add_one_entry (struct commonio_db *, struct commonio_entry *);
static int name_is_nis (const char *);
static int write_all (const struct commonio_db *);
static struct commonio_entry *find_entry_by_name (struct commonio_db *, const char *);
#ifdef HAVE_LCKPWDF
static int lock_count = 0;
#endif
static int check_link_count(const char *file)
{
struct stat sb;
if (stat(file, &sb) != 0)
return 0;
if (sb.st_nlink != 2)
return 0;
return 1;
}
static int do_lock_file(const char *file, const char *lock)
{
int fd;
int pid;
int len;
int retval;
char buf[32];
if ((fd = open(file, O_CREAT|O_EXCL|O_WRONLY, 0600)) == -1)
return 0;
pid = getpid();
snprintf(buf, sizeof buf, "%d", pid);
len = strlen(buf) + 1;
if (write (fd, buf, len) != len) {
close(fd);
unlink(file);
return 0;
}
close(fd);
if (link(file, lock) == 0) {
retval = check_link_count(file);
unlink(file);
return retval;
}
if ((fd = open(lock, O_RDWR)) == -1) {
unlink(file);
errno = EINVAL;
return 0;
}
len = read(fd, buf, sizeof(buf) - 1);
close(fd);
if (len <= 0) {
unlink(file);
errno = EINVAL;
return 0;
}
buf[len] = '\0';
if ((pid = strtol(buf, (char **) 0, 10)) == 0) {
unlink(file);
errno = EINVAL;
return 0;
}
if (kill(pid, 0) == 0) {
unlink(file);
errno = EEXIST;
return 0;
}
if (unlink(lock) != 0) {
unlink(file);
return 0;
}
retval = 0;
if (link(file, lock) == 0 && check_link_count(file))
retval = 1;
unlink(file);
return retval;
}
static FILE *fopen_set_perms(const char *name, const char *mode, const struct stat *sb)
{
FILE *fp;
mode_t mask;
mask = umask(0777);
fp = fopen(name, mode);
umask(mask);
if (!fp)
return NULL;
#ifdef HAVE_FCHOWN
if (fchown(fileno(fp), sb->st_uid, sb->st_gid))
goto fail;
#else
if (chown(name, sb->st_mode))
goto fail;
#endif
#ifdef HAVE_FCHMOD
if (fchmod(fileno(fp), sb->st_mode & 0664))
goto fail;
#else
if (chmod(name, sb->st_mode & 0664))
goto fail;
#endif
return fp;
fail:
fclose(fp);
unlink(name);
return NULL;
}
static int create_backup(const char *backup, FILE *fp)
{
struct stat sb;
struct utimbuf ub;
FILE *bkfp;
int c;
mode_t mask;
if (fstat(fileno(fp), &sb))
return -1;
mask = umask(077);
bkfp = fopen(backup, "w");
umask(mask);
if (!bkfp)
return -1;
/* TODO: faster copy, not one-char-at-a-time. --marekm */
rewind(fp);
while ((c = getc(fp)) != EOF) {
if (putc(c, bkfp) == EOF)
break;
}
if (c != EOF || fflush(bkfp)) {
fclose(bkfp);
return -1;
}
if (fclose(bkfp))
return -1;
ub.actime = sb.st_atime;
ub.modtime = sb.st_mtime;
utime(backup, &ub);
return 0;
}
static void free_linked_list(struct commonio_db *db)
{
struct commonio_entry *p;
while (db->head) {
p = db->head;
db->head = p->next;
if (p->line)
free(p->line);
if (p->entry)
db->ops->free(p->entry);
free(p);
}
db->tail = NULL;
}
int commonio_setname(struct commonio_db *db, const char *name)
{
strcpy(db->filename, name);
return 1;
}
int commonio_present(const struct commonio_db *db)
{
return (access(db->filename, F_OK) == 0);
}
int commonio_lock_nowait(struct commonio_db *db)
{
char file[1024];
char lock[1024];
if (db->locked)
return 1;
snprintf(file, sizeof file, "%s.%ld", db->filename, (long) getpid());
snprintf(lock, sizeof lock, "%s.lock", db->filename);
if (do_lock_file(file, lock)) {
db->locked = 1;
return 1;
}
return 0;
}
int commonio_lock(struct commonio_db *db)
{
int i;
#ifdef HAVE_LCKPWDF
/*
* only if the system libc has a real lckpwdf() - the one from
* lockpw.c calls us and would cause infinite recursion!
*/
if (db->use_lckpwdf) {
/*
* Call lckpwdf() on the first lock.
* If it succeeds, call *_lock() only once
* (no retries, it should always succeed).
*/
if (lock_count == 0) {
if (lckpwdf() == -1)
return 0; /* failure */
}
if (!commonio_lock_nowait(db)) {
ulckpwdf();
return 0; /* failure */
}
lock_count++;
return 1; /* success */
}
#endif
/*
* lckpwdf() not used - do it the old way.
*/
#ifndef LOCK_TRIES
#define LOCK_TRIES 15
#endif
#ifndef LOCK_SLEEP
#define LOCK_SLEEP 1
#endif
for (i = 0; i < LOCK_TRIES; i++) {
if (i > 0)
sleep(LOCK_SLEEP); /* delay between retries */
if (commonio_lock_nowait(db))
return 1; /* success */
/* no unnecessary retries on "permission denied" errors */
if (geteuid() != 0)
return 0;
}
return 0; /* failure */
}
int commonio_unlock(struct commonio_db *db)
{
char lock[1024];
if (db->isopen) {
db->readonly = 1;
if (!commonio_close(db))
return 0;
}
if (db->locked) {
/*
* Unlock in reverse order: remove the lock file,
* then call ulckpwdf() (if used) on last unlock.
*/
db->locked = 0;
snprintf(lock, sizeof lock, "%s.lock", db->filename);
unlink(lock);
#ifdef HAVE_LCKPWDF
if (db->use_lckpwdf && lock_count > 0) {
lock_count--;
if (lock_count == 0)
ulckpwdf();
}
#endif
return 1;
}
return 0;
}
static void add_one_entry(struct commonio_db *db, struct commonio_entry *p)
{
p->next = NULL;
p->prev = db->tail;
if (!db->head)
db->head = p;
if (db->tail)
db->tail->next = p;
db->tail = p;
}
static int name_is_nis(const char *n)
{
return (n[0] == '+' || n[0] == '-');
}
/*
* New entries are inserted before the first NIS entry. Order is preserved
* when db is written out.
*/
#ifndef KEEP_NIS_AT_END
#define KEEP_NIS_AT_END 1
#endif
#if KEEP_NIS_AT_END
/* prototype */
static void add_one_entry_nis (struct commonio_db *, struct commonio_entry *);
static void add_one_entry_nis(struct commonio_db *db, struct commonio_entry *new)
{
struct commonio_entry *p;
for (p = db->head; p; p = p->next) {
if (name_is_nis(p->entry ? db->ops->getname(p->entry) : p->line)) {
new->next = p;
new->prev = p->prev;
if (p->prev)
p->prev->next = new;
else
db->head = new;
p->prev = new;
return;
}
}
add_one_entry(db, new);
}
#endif /* KEEP_NIS_AT_END */
int commonio_open(struct commonio_db *db, int mode)
{
char buf[8192];
char *cp;
char *line;
struct commonio_entry *p;
void *entry;
int flags = mode;
mode &= ~O_CREAT;
if (db->isopen || (mode != O_RDONLY && mode != O_RDWR)) {
errno = EINVAL;
return 0;
}
db->readonly = (mode == O_RDONLY);
if (!db->readonly && !db->locked) {
errno = EACCES;
return 0;
}
db->head = db->tail = db->cursor = NULL;
db->changed = 0;
db->fp = fopen(db->filename, db->readonly ? "r" : "r+");
/*
* If O_CREAT was specified and the file didn't exist, it will be
* created by commonio_close(). We have no entries to read yet. --marekm
*/
if (!db->fp) {
if ((flags & O_CREAT) && errno == ENOENT) {
db->isopen++;
return 1;
}
return 0;
}
while (db->ops->fgets(buf, sizeof buf, db->fp)) {
if ((cp = strrchr(buf, '\n')))
*cp = '\0';
if (!(line = strdup(buf)))
goto cleanup;
if (name_is_nis(line)) {
entry = NULL;
} else if ((entry = db->ops->parse(line))) {
entry = db->ops->dup(entry);
if (!entry)
goto cleanup_line;
}
p = (struct commonio_entry *) malloc(sizeof *p);
if (!p)
goto cleanup_entry;
p->entry = entry;
p->line = line;
p->changed = 0;
add_one_entry(db, p);
}
db->isopen++;
return 1;
cleanup_entry:
if (entry)
db->ops->free(entry);
cleanup_line:
free(line);
cleanup:
free_linked_list(db);
fclose(db->fp);
db->fp = NULL;
errno = ENOMEM;
return 0;
}
static int write_all(const struct commonio_db *db)
{
const struct commonio_entry *p;
void *entry;
for (p = db->head; p; p = p->next) {
if (p->changed) {
entry = p->entry;
if (db->ops->put(entry, db->fp))
return -1;
} else if (p->line) {
if (db->ops->fputs(p->line, db->fp) == EOF)
return -1;
if (putc('\n', db->fp) == EOF)
return -1;
}
}
return 0;
}
int commonio_close(struct commonio_db *db)
{
char buf[1024];
int errors = 0;
struct stat sb;
if (!db->isopen) {
errno = EINVAL;
return 0;
}
db->isopen = 0;
if (!db->changed || db->readonly) {
fclose(db->fp);
db->fp = NULL;
goto success;
}
memset(&sb, 0, sizeof sb);
if (db->fp) {
if (fstat(fileno(db->fp), &sb)) {
fclose(db->fp);
db->fp = NULL;
goto fail;
}
/*
* Create backup file.
*/
snprintf(buf, sizeof buf, "%s-", db->filename);
if (create_backup(buf, db->fp))
errors++;
if (fclose(db->fp))
errors++;
if (errors) {
db->fp = NULL;
goto fail;
}
} else {
/*
* Default permissions for new [g]shadow files.
* (passwd and group always exist...)
*/
sb.st_mode = 0400;
sb.st_uid = 0;
sb.st_gid = 0;
}
snprintf(buf, sizeof buf, "%s+", db->filename);
db->fp = fopen_set_perms(buf, "w", &sb);
if (!db->fp)
goto fail;
if (write_all(db))
errors++;
if (fflush(db->fp))
errors++;
#ifdef HAVE_FSYNC
if (fsync(fileno(db->fp)))
errors++;
#else
sync();
#endif
if (fclose(db->fp))
errors++;
db->fp = NULL;
if (errors) {
unlink(buf);
goto fail;
}
if (rename(buf, db->filename))
goto fail;
success:
free_linked_list(db);
return 1;
fail:
free_linked_list(db);
return 0;
}
static struct commonio_entry * find_entry_by_name(struct commonio_db *db, const char *name)
{
struct commonio_entry *p;
void *ep;
for (p = db->head; p; p = p->next) {
ep = p->entry;
if (ep && strcmp(db->ops->getname(ep), name) == 0)
break;
}
return p;
}
int commonio_update(struct commonio_db *db, const void *entry)
{
struct commonio_entry *p;
void *nentry;
if (!db->isopen || db->readonly) {
errno = EINVAL;
return 0;
}
if (!(nentry = db->ops->dup(entry))) {
errno = ENOMEM;
return 0;
}
p = find_entry_by_name(db, db->ops->getname(entry));
if (p) {
db->ops->free(p->entry);
p->entry = nentry;
p->changed = 1;
db->cursor = p;
db->changed = 1;
return 1;
}
/* not found, new entry */
p = (struct commonio_entry *) malloc(sizeof *p);
if (!p) {
db->ops->free(nentry);
errno = ENOMEM;
return 0;
}
p->entry = nentry;
p->line = NULL;
p->changed = 1;
#if KEEP_NIS_AT_END
add_one_entry_nis(db, p);
#else
add_one_entry(db, p);
#endif
db->changed = 1;
return 1;
}
void commonio_del_entry(struct commonio_db *db, const struct commonio_entry *p)
{
if (p == db->cursor)
db->cursor = p->next;
if (p->prev)
p->prev->next = p->next;
else
db->head = p->next;
if (p->next)
p->next->prev = p->prev;
else
db->tail = p->prev;
db->changed = 1;
}
int commonio_remove(struct commonio_db *db, const char *name)
{
struct commonio_entry *p;
if (!db->isopen || db->readonly) {
errno = EINVAL;
return 0;
}
p = find_entry_by_name(db, name);
if (!p) {
errno = ENOENT;
return 0;
}
commonio_del_entry(db, p);
if (p->line)
free(p->line);
if (p->entry)
db->ops->free(p->entry);
return 1;
}
const void * commonio_locate(struct commonio_db *db, const char *name)
{
struct commonio_entry *p;
if (!db->isopen) {
errno = EINVAL;
return NULL;
}
p = find_entry_by_name(db, name);
if (!p) {
errno = ENOENT;
return NULL;
}
db->cursor = p;
return p->entry;
}
int commonio_rewind(struct commonio_db *db)
{
if (!db->isopen) {
errno = EINVAL;
return 0;
}
db->cursor = NULL;
return 1;
}
const void * commonio_next(struct commonio_db *db)
{
void *entry;
if (!db->isopen) {
errno = EINVAL;
return 0;
}
if (db->cursor == NULL)
db->cursor = db->head;
else
db->cursor = db->cursor->next;
while (db->cursor) {
entry = db->cursor->entry;
if (entry)
return entry;
db->cursor = db->cursor->next;
}
return NULL;
}

112
unix/commonio.h Normal file
View File

@@ -0,0 +1,112 @@
#ifndef _COMMONIO_H
#define _COMMONIO_H
/*
* Linked list entry.
*/
struct commonio_entry {
char *line;
void *entry; /* struct passwd, struct spwd, ... */
struct commonio_entry *prev, *next;
int changed:1;
};
/*
* Operations depending on database type: passwd, group, shadow etc.
*/
struct commonio_ops {
/*
* Make a copy of the object (for example, struct passwd)
* and all strings pointed by it, in malloced memory.
*/
void * (*dup) (const void *);
/*
* free() the object including any strings pointed by it.
*/
void (*free) (void *);
/*
* Return the name of the object (for example, pw_name
* for struct passwd).
*/
const char * (*getname) (const void *);
/*
* Parse a string, return object (in static area -
* should be copied using the dup operation above).
*/
void * (*parse) (const char *);
/*
* Write the object to the file (this calls putpwent()
* for struct passwd, for example).
*/
int (*put) (const void *, FILE *);
/*
* fgets and fputs (can be replaced by versions that
* understand line continuation conventions).
*/
char * (*fgets) (char *, int, FILE *);
int (*fputs) (const char *, FILE *);
};
/*
* Database structure.
*/
struct commonio_db {
/*
* Name of the data file.
*/
char filename[1024];
/*
* Operations from above.
*/
struct commonio_ops *ops;
/*
* Currently open file stream.
*/
FILE *fp;
/*
* Head, tail, current position in linked list.
*/
struct commonio_entry *head, *tail, *cursor;
/*
* Various flags.
*/
int changed:1;
int isopen:1;
int locked:1;
int readonly:1;
int use_lckpwdf:1;
};
int commonio_setname (struct commonio_db *, const char *);
int commonio_present (const struct commonio_db *);
int commonio_lock (struct commonio_db *);
int commonio_lock_nowait (struct commonio_db *);
int commonio_open (struct commonio_db *, int);
const void *commonio_locate (struct commonio_db *, const char *);
int commonio_update (struct commonio_db *, const void *);
int commonio_remove (struct commonio_db *, const char *);
int commonio_rewind (struct commonio_db *);
const void *commonio_next (struct commonio_db *);
int commonio_close (struct commonio_db *);
int commonio_unlock (struct commonio_db *);
void commonio_del_entry (struct commonio_db *, const struct commonio_entry *);
#endif

160
unix/encrypt.c Normal file
View File

@@ -0,0 +1,160 @@
/*****************************************************************************
*
* $Id: encrypt.c,v 1.4 2005/04/12 17:25:42 mbse Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2003
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/*
* Copyright 1990 - 1993, Julianne Frances Haugh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "../config.h"
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
#include "encrypt.h"
#ifdef MD5_CRYPT
extern char *md5_crypt();
#endif
char *pw_encrypt(const char *clear, const char *salt)
{
static char cipher[128];
char *cp;
#ifdef SW_CRYPT
static int count;
#endif
#ifdef MD5_CRYPT
/*
* If the salt string from the password file or from crypt_make_salt()
* begins with the magic string, use the new algorithm.
*/
if (strncmp(salt, "$1$", 3) == 0)
return md5_crypt(clear, salt);
#endif
#ifdef SW_CRYPT
/*
* Copy over the salt. It is always the first two
* characters of the string.
*/
cipher[0] = salt[0];
cipher[1] = salt[1];
cipher[2] = '\0';
/*
* Loop up to ten times on the cleartext password.
* This is because the input limit for passwords is
* 80 characters.
*
* The initial salt is that provided by the user, or the
* one generated above. The subsequent salts are gotten
* from the first two characters of the previous encrypted
* block of characters.
*/
for (count = 0;count < 10;count++) {
cp = crypt (clear, salt);
if (!cp) {
perror("crypt");
exit(1);
}
if (strlen(cp) != 13)
return cp;
strcat (cipher, cp + 2);
salt = cipher + 11 * count + 2;
if (strlen (clear) > 8)
clear += 8;
else
break;
}
#else
cp = crypt (clear, salt);
if (!cp) {
/*
* Single Unix Spec: crypt() may return a null pointer,
* and set errno to indicate an error. The caller doesn't
* expect us to return NULL, so...
*/
perror("crypt");
exit(1);
}
if (strlen(cp) != 13)
return cp; /* nonstandard crypt() in libc, better bail out */
strcpy (cipher, cp);
#ifdef DOUBLESIZE
if (strlen (clear) > 8) {
cp = crypt (clear + 8, salt);
if (!cp) {
perror("crypt");
exit(1);
}
strcat (cipher, cp + 2);
}
#endif /* DOUBLESIZE */
#endif /* SW_CRYPT */
return cipher;
}

9
unix/encrypt.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef _ENCRYPT_H
#define _ENCRYPT_H
char *pw_encrypt(const char *, const char *);
#endif

253
unix/env.c Normal file
View File

@@ -0,0 +1,253 @@
/*****************************************************************************
*
* $Id: env.c,v 1.3 2005/08/30 17:53:35 mbse Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mblogin.h"
#include "xmalloc.h"
/*
* NEWENVP_STEP must be a power of two. This is the number
* of (char *) pointers to allocate at a time, to avoid using
* realloc() too often.
*/
#define NEWENVP_STEP 16
size_t newenvc = 0;
char **newenvp = NULL;
extern char **environ;
static const char *forbid[] = {
"_RLD_=",
"BASH_ENV=", /* GNU creeping featurism strikes again... */
"ENV=",
"HOME=",
"IFS=",
"KRB_CONF=",
"LD_", /* anything with the LD_ prefix */
"LIBPATH=",
"MAIL=",
"NLSPATH=",
"PATH=",
"SHELL=",
"SHLIB_PATH=",
(char *) 0
};
/* these are allowed, but with no slashes inside
(to work around security problems in GNU gettext) */
static const char *noslash[] = {
"LANG=",
"LANGUAGE=",
"LC_", /* anything with the LC_ prefix */
(char *) 0
};
/*
* initenv() must be called once before using addenv().
*/
void initenv(void)
{
newenvp = (char **)xmalloc(NEWENVP_STEP * sizeof(char *));
*newenvp = NULL;
}
void addenv(const char *string, const char *value)
{
char *cp, *newstring;
size_t i;
size_t n;
if (value) {
newstring = xmalloc(strlen(string) + strlen(value) + 2);
snprintf(newstring, strlen(string) + strlen(value) + 2, "%s=%s", string, value);
} else {
newstring = xstrdup(string);
}
/*
* Search for a '=' character within the string and if none is found
* just ignore the whole string.
*/
cp = strchr(newstring, '=');
if (!cp) {
free(newstring);
return;
}
n = (size_t)(cp - newstring);
for (i = 0; i < newenvc; i++) {
if (strncmp(newstring, newenvp[i], n) == 0 &&
(newenvp[i][n] == '=' || newenvp[i][n] == '\0'))
break;
}
if (i < newenvc) {
free(newenvp[i]);
newenvp[i] = newstring;
return;
}
newenvp[newenvc++] = newstring;
/*
* Check whether newenvc is a multiple of NEWENVP_STEP.
* If so we have to resize the vector.
* the expression (newenvc & (NEWENVP_STEP - 1)) == 0
* is equal to (newenvc % NEWENVP_STEP) == 0
* as long as NEWENVP_STEP is a power of 2.
*/
if ((newenvc & (NEWENVP_STEP - 1)) == 0) {
char **__newenvp;
size_t newsize;
/*
* If the resize operation succeds we can
* happily go on, else print a message.
*/
newsize = (newenvc + NEWENVP_STEP) * sizeof(char *);
__newenvp = (char **)realloc(newenvp, newsize);
if (__newenvp) {
/*
* If this is our current environment, update
* environ so that it doesn't point to some
* free memory area (realloc() could move it).
*/
if (environ == newenvp)
environ = __newenvp;
newenvp = __newenvp;
} else {
fprintf(stderr, "Environment overflow\n");
free(newenvp[--newenvc]);
}
}
/*
* The last entry of newenvp must be NULL
*/
newenvp[newenvc] = NULL;
}
/*
* set_env - copy command line arguments into the environment
*/
void set_env(int argc, char * const *argv)
{
int noname = 1;
char variable[1024];
char *cp;
for ( ; argc > 0; argc--, argv++) {
if (strlen(*argv) >= sizeof variable)
continue; /* ignore long entries */
if (! (cp = strchr (*argv, '='))) {
snprintf(variable, sizeof variable, "L%d", noname++);
addenv(variable, *argv);
} else {
const char **p;
for (p = forbid; *p; p++)
if (strncmp(*argv, *p, strlen(*p)) == 0)
break;
if (*p) {
strncpy(variable, *argv, cp - *argv);
variable[cp - *argv] = '\0';
printf("You may not change $%s\n", variable);
continue;
}
addenv(*argv, NULL);
}
}
}
/*
* sanitize_env - remove some nasty environment variables
* If you fall into a total paranoia, you should call this
* function for any root-setuid program or anything the user
* might change the environment with. 99% useless as almost
* all modern Unixes will handle setuid executables properly,
* but... I feel better with that silly precaution. -j.
*/
void sanitize_env(void)
{
char **envp = environ;
const char **bad;
char **cur;
char **move;
for (cur = envp; *cur; cur++) {
for (bad = forbid; *bad; bad++) {
if (strncmp(*cur, *bad, strlen(*bad)) == 0) {
for (move = cur; *move; move++)
*move = *(move + 1);
cur--;
break;
}
}
}
for (cur = envp; *cur; cur++) {
for (bad = noslash; *bad; bad++) {
if (strncmp(*cur, *bad, strlen(*bad)) != 0)
continue;
if (!strchr(*cur, '/'))
continue; /* OK */
for (move = cur; *move; move++)
*move = *(move + 1);
cur--;
break;
}
}
}

12
unix/env.h Normal file
View File

@@ -0,0 +1,12 @@
/* $Id: env.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _ENV_H
#define _ENV_H
void initenv(void);
void addenv(const char *, const char *);
void set_env(int, char * const *);
void sanitize_env(void);
#endif

339
unix/getdef.c Normal file
View File

@@ -0,0 +1,339 @@
/*****************************************************************************
*
* $Id: getdef.c,v 1.4 2005/08/30 17:53:35 mbse Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <syslog.h>
#include <sys/param.h>
#include <pwd.h>
#include "getdef.h"
/*
* A configuration item definition.
*/
struct itemdef {
const char *name; /* name of the item */
char *value; /* value given, or NULL if no value */
};
/*
* This list *must* be sorted by the "name" member.
* It doesn't hurt that there are extra entries here
* that are not known by the system this is running
* on. Missing entries here gives a nasty message to
* new bbs users.
*/
#define NUMDEFS (sizeof(def_table)/sizeof(def_table[0]))
static struct itemdef def_table[] = {
{ "ALLOW_MBSE", NULL },
{ "ASK_NEWUSER", NULL },
{ "DEFAULT_HOME", NULL },
{ "ENV_HZ", NULL },
{ "ENV_PATH" , NULL },
{ "ENV_TZ", NULL },
{ "ERASECHAR", NULL },
{ "FAIL_DELAY", NULL },
{ "ISSUE_FILE", NULL },
{ "KILLCHAR", NULL },
{ "LASTLOG_ENAB", NULL },
{ "LOGIN_RETRIES", NULL },
{ "LOGIN_TIMEOUT", NULL },
{ "LOG_OK_LOGINS", NULL },
{ "LOG_UNKFAIL_ENAB", NULL },
{ "MD5_CRYPT_ENAB", NULL },
{ "NEWUSER_ACCOUNT", NULL },
{ "NOLOGINS_FILE", NULL },
{ "TTYGROUP", NULL },
{ "TTYPERM", NULL },
{ "ULIMIT", NULL },
{ "UMASK", NULL },
{ "USERGROUPS_ENAB", NULL },
};
static int def_loaded = 0; /* are defs already loaded? */
/* local function prototypes */
static struct itemdef *def_find (const char *);
/*
* getdef_str - get string value from table of definitions.
*
* Return point to static data for specified item, or NULL if item is not
* defined. First time invoked, will load definitions from the file.
*/
char *getdef_str(const char *item)
{
struct itemdef *d;
if (!def_loaded)
def_load();
return ((d = def_find(item)) == NULL ? (char *)NULL : d->value);
}
/*
* getdef_bool - get boolean value from table of definitions.
*
* Return TRUE if specified item is defined as "yes", else FALSE.
*/
int getdef_bool(const char *item)
{
struct itemdef *d;
if (!def_loaded)
def_load();
if ((d = def_find(item)) == NULL || d->value == NULL)
return 0;
return (strcmp(d->value, "yes") == 0);
}
/*
* getdef_num - get numerical value from table of definitions
*
* Returns numeric value of specified item, else the "dflt" value if
* the item is not defined. Octal (leading "0") and hex (leading "0x")
* values are handled.
*/
int getdef_num(const char *item, int dflt)
{
struct itemdef *d;
if (!def_loaded)
def_load();
if ((d = def_find(item)) == NULL || d->value == NULL)
return dflt;
return (int) strtol(d->value, (char **)NULL, 0);
}
/*
* getdef_long - get long integer value from table of definitions
*
* Returns numeric value of specified item, else the "dflt" value if
* the item is not defined. Octal (leading "0") and hex (leading "0x")
* values are handled.
*/
long getdef_long(const char *item, long dflt)
{
struct itemdef *d;
if (!def_loaded)
def_load();
if ((d = def_find(item)) == NULL || d->value == NULL)
return dflt;
return strtol(d->value, (char **)NULL, 0);
}
/*
* def_find - locate named item in table
*
* Search through a sorted table of configurable items to locate the
* specified configuration option.
*/
static struct itemdef *def_find(const char *name)
{
int min, max, curr, n;
/*
* Invariant - desired item in range [min:max].
*/
min = 0;
max = NUMDEFS-1;
/*
* Binary search into the table. Relies on the items being
* sorted by name.
*/
while (min <= max) {
curr = (min+max)/2;
if (! (n = strcmp(def_table[curr].name, name)))
return &def_table[curr];
if (n < 0)
min = curr+1;
else
max = curr-1;
}
/*
* Item was never found.
*/
fprintf(stderr, "getdef(): configuration error - unknown item '%s' (notify administrator)\r\n", name);
syslog(LOG_CRIT, "getdef(): unknown configuration item `%s'", name);
return (struct itemdef *) NULL;
}
/*
* def_load - load configuration table
*
* Loads the user-configured options from the default configuration file
*/
void def_load(void)
{
int i;
FILE *fp;
struct itemdef *d;
char buf[BUFSIZ], def_fname[PATH_MAX], *name, *value, *s;
struct passwd *pw;
/*
* Get MBSE BBS root directory
*/
if ((pw = getpwnam("mbse")) == NULL) {
syslog(LOG_CRIT, "cannot find user `mbse' in password file");
return;
}
snprintf(def_fname, PATH_MAX, "%s/etc/login.defs", pw->pw_dir);
/*
* Open the configuration definitions file.
*/
if ((fp = fopen(def_fname, "r")) == NULL) {
syslog(LOG_CRIT, "cannot open login definitions %s [%m]", def_fname);
return;
}
/*
* Go through all of the lines in the file.
*/
while (fgets(buf, sizeof(buf), fp) != NULL) {
/*
* Trim trailing whitespace.
*/
for (i = strlen(buf)-1 ; i >= 0 ; --i) {
if (!isspace(buf[i]))
break;
}
buf[++i] = '\0';
/*
* Break the line into two fields.
*/
name = buf + strspn(buf, " \t"); /* first nonwhite */
if (*name == '\0' || *name == '#')
continue; /* comment or empty */
s = name + strcspn(name, " \t"); /* end of field */
if (*s == '\0')
continue; /* only 1 field?? */
*s++ = '\0';
value = s + strspn(s, " \"\t"); /* next nonwhite */
*(value + strcspn(value, "\"")) = '\0';
/*
* Locate the slot to save the value. If this parameter
* is unknown then "def_find" will print an err message.
*/
if ((d = def_find(name)) == NULL)
continue;
/*
* Save off the value.
*/
if ((d->value = strdup(value)) == NULL) {
fprintf(stderr, "getdef: Could not allocate space for config info.\n");
syslog(LOG_ERR, "getdef: could not allocate space for config info");
break;
}
}
(void) fclose(fp);
/*
* Set the initialized flag.
*/
++def_loaded;
}
#ifdef CKDEFS
int main(int argc, char **argv)
{
int i;
char *cp;
struct itemdef *d;
def_load ();
for (i = 0 ; i < NUMDEFS ; ++i) {
if ((d = def_find(def_table[i].name)) == NULL)
printf("error - lookup '%s' failed\n", def_table[i].name);
else
printf("%4d %-24s %s\n", i+1, d->name, d->value);
}
for (i = 1;i < argc;i++) {
if (cp = getdef_str (argv[1]))
printf ("%s `%s'\n", argv[1], cp);
else
printf ("%s not found\n", argv[1]);
}
exit(0);
}
#endif

13
unix/getdef.h Normal file
View File

@@ -0,0 +1,13 @@
/* $Id: getdef.h,v 1.2 2002/01/11 21:07:04 mbroek Exp $ */
#ifndef _GETDEF_H
#define _GETDEF_H
int getdef_bool(const char *);
long getdef_long(const char *, long);
int getdef_num(const char *, int);
char *getdef_str(const char *);
void def_load (void);
#endif /* _GETDEF_H */

67
unix/limits.c Normal file
View File

@@ -0,0 +1,67 @@
/*****************************************************************************
*
* $Id: limits.c,v 1.2 2003/08/15 20:05:36 mbroek Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/*
* Separated from setup.c. --marekm
* Resource limits thanks to Cristian Gafton.
*/
#include "../config.h"
#include "mblogin.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include "limits.h"
void setup_limits(const struct passwd *info)
{
const struct group *grp;
mode_t oldmask;
/*
* if not root, and uid == gid, and username is the same as primary
* group name, set umask group bits to be the same as owner bits
* (examples: 022 -> 002, 077 -> 007).
*/
if (info->pw_uid != 0 && info->pw_uid == info->pw_gid) {
grp = getgrgid(info->pw_gid);
if (grp && (strcmp(info->pw_name, grp->gr_name) == 0)) {
oldmask = umask(0777);
umask((oldmask & ~070) | ((oldmask >> 3) & 070));
}
}
}

9
unix/limits.h Normal file
View File

@@ -0,0 +1,9 @@
/* $Id: limits.h,v 1.2 2002/01/06 13:24:24 mbroek Exp $ */
#ifndef _LIMITS_H_H
#define _LIMITS_H_H
void setup_limits(const struct passwd *);
#endif

97
unix/log.c Normal file
View File

@@ -0,0 +1,97 @@
/*****************************************************************************
*
* $Id: log.c,v 1.2 2003/08/15 20:05:36 mbroek Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#include <fcntl.h>
#include <time.h>
#include "mblogin.h"
#include <utmp.h>
#include "log.h"
/*
* dolastlog - create lastlog entry
*
* A "last login" entry is created for the user being logged in. The
* UID is extracted from the global (struct passwd) entry and the
* TTY information is gotten from the (struct utmp).
*/
void dolastlog(struct lastlog *ll, const struct passwd *pw, const char *line, const char *host)
{
int fd;
off_t offset;
struct lastlog newlog;
/*
* If the file does not exist, don't create it.
*/
if ((fd = open(LASTLOG_FILE, O_RDWR)) == -1)
return;
/*
* The file is indexed by UID number. Seek to the record
* for this UID. Negative UID's will create problems, but ...
*/
offset = (unsigned long) pw->pw_uid * sizeof newlog;
if (lseek(fd, offset, SEEK_SET) != offset) {
close(fd);
return;
}
/*
* Read the old entry so we can tell the user when they last
* logged in. Then construct the new entry and write it out
* the way we read the old one in.
*/
if (read(fd, (char *) &newlog, sizeof newlog) != sizeof newlog)
memzero(&newlog, sizeof newlog);
if (ll)
*ll = newlog;
time(&newlog.ll_time);
strncpy(newlog.ll_line, line, sizeof newlog.ll_line);
#ifdef HAVE_LL_HOST
strncpy(newlog.ll_host, host, sizeof newlog.ll_host);
#endif
if (lseek(fd, offset, SEEK_SET) == offset)
write(fd, (char *) &newlog, sizeof newlog);
close(fd);
}

8
unix/log.h Normal file
View File

@@ -0,0 +1,8 @@
/* $Id: log.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _LOG_LOG_H
#define _LOG_LOG_H
void dolastlog(struct lastlog *, const struct passwd *, const char *, const char *);
#endif

146
unix/login.defs.in Normal file
View File

@@ -0,0 +1,146 @@
#
# $MBSE_ROOT/etc/login.defs - Configuration control definitions for mblogin.
#
# $Id: login.defs.in,v 1.3 2004/11/28 18:23:13 mbse Exp $
# Three items must be defined: MAIL_DIR, ENV_SUPATH, and ENV_PATH.
# If unspecified, some arbitrary (and possibly incorrect) value will
# be assumed. All other items are optional - if not specified then
# the described action or option will be inhibited.
#
# Comment lines (lines beginning with "#") and blank lines are ignored.
#
#
# Allow user "mbse" to login and get a shell. You better leave this to "no"
# and install ssh if you want to login using a shell.
#
ALLOW_MBSE no
#
# Ask a user when his username is not found if he wants to register as new
# user. If not, the user has to use the special account to start mbnewusr.
# If no, it is not bbs user friendly,
# If yes, usernames may be easy guessed, but most bbses do it like this.
#
ASK_NEWUSER yes
#
# The newuser account name, defaults to "bbs". If you change this change it
# in the password files, change it in mbsetup and in this file. Better
# leave this unchanged.
#
NEWUSER_ACCOUNT bbs
#
# Delay in seconds before being allowed another attempt after a login failure
#
FAIL_DELAY 3
#
# Enable display of unknown usernames when login failures are recorded.
#
LOG_UNKFAIL_ENAB no
#
# Enable logging of successful logins
#
LOG_OK_LOGINS no
#
# Enable logging of lastlog login time info.
#
LASTLOG_ENAB yes
#
# If defined, this file will be output before each login prompt.
# Should not be needed, mgetty and getty will do this already.
#
ISSUE_FILE @prefix@/etc/issue
#
# If defined, name of file whose presence which will inhibit non-root
# logins. The contents of this file should be a message indicating
# why logins are inhibited.
#
NOLOGINS_FILE /etc/nologin
#
# If defined, an HZ environment parameter spec.
#
# for Linux/x86
ENV_HZ HZ=100
# For Linux/Alpha...
#ENV_HZ HZ=1024
#
# *REQUIRED* The default PATH settings, for superuser and normal users.
#
# (they are minimal, add the rest in the shell startup files)
ENV_PATH PATH=/usr/local/bin:/bin:/usr/bin:@prefix@/bin
#
# Terminal permissions
#
# TTYGROUP Login tty will be assigned this group ownership.
# TTYPERM Login tty will be set to this permission.
#
# If you have a "write" program which is "setgid" to a special group
# which owns the terminals, define TTYGROUP to the group number and
# TTYPERM to 0620. Otherwise leave TTYGROUP commented out and assign
# TTYPERM to either 622 or 600.
#
TTYGROUP tty
TTYPERM 0620
#
# Login configuration initializations:
#
# ERASECHAR Terminal ERASE character ('\010' = backspace).
# KILLCHAR Terminal KILL character ('\025' = CTRL/U).
# UMASK Default "umask" value.
# ULIMIT Default "ulimit" value.
#
# The ERASECHAR and KILLCHAR are used only on System V machines.
# The ULIMIT is used only if the system supports it.
# (now it works with setrlimit too; ulimit is in 512-byte units)
#
# Prefix these values with "0" to get octal, "0x" to get hexadecimal.
#
ERASECHAR 0177
KILLCHAR 025
UMASK 007
#
# Max number of login retries if password is bad
#
LOGIN_RETRIES 5
#
# Max time in seconds for login
#
LOGIN_TIMEOUT 60
#
# Only works if compiled with MD5_CRYPT defined:
# If set to "yes", new passwords will be encrypted using the MD5-based
# algorithm compatible with the one used by recent releases of FreeBSD.
# It supports passwords of unlimited length and longer salt strings.
# Set to "no" if you need to copy encrypted passwords to other systems
# which don't understand the new algorithm. Default is "no".
#
MD5_CRYPT_ENAB yes
#
# Should login be allowed if we can't cd to the home directory?
# Default in no.
#
DEFAULT_HOME no
#
# Enable setting of the umask group bits to be the same as owner bits
# (examples: 022 -> 002, 077 -> 007) for non-root users, if the uid is
# the same as gid, and username is the same as the primary group name.
#
USERGROUPS_ENAB yes

168
unix/loginprompt.c Normal file
View File

@@ -0,0 +1,168 @@
/*****************************************************************************
*
* $Id: loginprompt.c,v 1.3 2005/08/30 17:53:35 mbse Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include "mblogin.h"
#include "getdef.h"
#include "xmalloc.h"
#include "env.h"
#include "loginprompt.h"
void login_exit(int sig)
{
exit(1);
}
/*
* login_prompt - prompt the user for their login name
*
* login_prompt() displays the standard login prompt. If ISSUE_FILE
* is set in login.defs, this file is displayed before the prompt.
*/
void login_prompt(const char *prompt, char *name, int namesize)
{
char buf[1024];
#define MAX_ENV 32
char *envp[MAX_ENV];
int envc;
char *cp;
int i;
FILE *fp;
RETSIGTYPE (*sigquit)(int);
#ifdef SIGTSTP
RETSIGTYPE (*sigtstp)(int);
#endif
/*
* There is a small chance that a QUIT character will be part of
* some random noise during a prompt. Deal with this by exiting
* instead of core dumping. If SIGTSTP is defined, do the same
* thing for that signal.
*/
sigquit = signal(SIGQUIT, login_exit);
#ifdef SIGTSTP
sigtstp = signal(SIGTSTP, login_exit);
#endif
/*
* See if the user has configured the issue file to
* be displayed and display it before the prompt.
*/
if (prompt) {
cp = getdef_str("ISSUE_FILE");
if (cp && (fp = fopen(cp, "r"))) {
while ((i = getc(fp)) != EOF)
putc(i, stdout);
fclose(fp);
}
gethostname(buf, sizeof buf);
printf(prompt, buf);
fflush(stdout);
}
/*
* Read the user's response. The trailing newline will be
* removed.
*/
memzero(buf, sizeof buf);
if (fgets(buf, sizeof buf, stdin) != buf)
exit(1);
cp = strchr(buf, '\n');
if (!cp)
exit(1);
*cp = '\0'; /* remove \n [ must be there ] */
/*
* Skip leading whitespace. This makes " username" work right.
* Then copy the rest (up to the end or the first "non-graphic"
* character into the username.
*/
for (cp = buf;*cp == ' ' || *cp == '\t';cp++)
;
// for (i = 0; i < namesize - 1 && isgraph(*cp); name[i++] = *cp++);
/*
* Allow double names for Fidonet login style.
*/
for (i = 0; i < namesize - 1 && isprint(*cp); name[i++] = *cp++);
while (isgraph(*cp))
cp++;
if (*cp)
cp++;
name[i] = '\0';
/*
* This is a disaster, at best. The user may have entered extra
* environmental variables at the prompt. There are several ways
* to do this, and I just take the easy way out.
*/
if (*cp != '\0') { /* process new variables */
char *nvar;
int count = 1;
for (envc = 0; envc < MAX_ENV; envc++) {
nvar = strtok(envc ? (char *)0 : cp, " \t,");
if (!nvar)
break;
if (strchr(nvar, '=')) {
envp[envc] = nvar;
} else {
envp[envc] = xmalloc(strlen(nvar) + 32);
snprintf(envp[envc], strlen(nvar) + 32, "L%d=%s", count++, nvar);
}
}
set_env(envc, envp);
}
/*
* Set the SIGQUIT handler back to its original value
*/
signal(SIGQUIT, sigquit);
#ifdef SIGTSTP
signal(SIGTSTP, sigtstp);
#endif
}

9
unix/loginprompt.h Normal file
View File

@@ -0,0 +1,9 @@
/* $Id: loginprompt.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _LOGINPROMPT_H
#define _LOGINPROMPT_H
void login_exit(int);
void login_prompt(const char *, char *, int);
#endif

848
unix/mblogin.c Normal file
View File

@@ -0,0 +1,848 @@
/*****************************************************************************
*
* $Id: mblogin.c,v 1.9 2007/08/26 15:05:33 mbse Exp $
* Purpose ...............: Login program for MBSE BBS.
* Shadow Suite (c) ......: Julianne Frances Haugh
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include "mblogin.h"
#include "../lib/users.h"
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <syslog.h>
#include <pwd.h>
#include <grp.h>
#if defined(SHADOW_PASSWORD)
#include <shadow.h>
#endif
#if defined(__NetBSD__)
#undef HAVE_UTMPX_H
#endif
#if HAVE_UTMPX_H
#include <utmpx.h>
#endif
#include <utmp.h>
#include <signal.h>
#include <unistd.h>
#include <ctype.h>
#include "getdef.h"
#ifdef SVR4_SI86_EUA
#include <sys/proc.h>
#include <sys/sysi86.h>
#endif
#ifdef UT_ADDR
#include <netdb.h>
#endif
#include "env.h"
#include "chowntty.h"
#include "basename.h"
#include "shell.h"
#include "pwdcheck.h"
#include "pwauth.h"
#include "loginprompt.h"
#include "utmp.h"
#include "limits.h"
#include "setupenv.h"
#include "sub.h"
#include "log.h"
#include "setugid.h"
/*
* Login parameters
*/
#define LOGIN_DELAY 3
#define LOGIN_TIMEOUT 300
#define LOGIN_RETRIES 10
/*
* Needed for MkLinux DR1/2/2.1 - J.
*/
#ifndef LASTLOG_FILE
#define LASTLOG_FILE "/var/log/lastlog"
#endif
const char *hostname = "";
struct passwd pwent, *pw;
#if HAVE_UTMPX_H
struct utmpx utxent, failent;
struct utmp utent;
#else
struct utmp utent, failent;
#endif
struct lastlog lastlog;
static int preauth_flag = 0;
/*
* Global variables.
*/
static int hflg = 0;
static int pflg = 0;
static char *Prog;
static int amroot;
static int timeout;
/*
* External identifiers.
*/
extern char **newenvp;
extern size_t newenvc;
extern int optind;
extern char *optarg;
extern char **environ;
#ifndef ALARM
#define ALARM 60
#endif
#ifndef RETRIES
#define RETRIES 3
#endif
#define NO_SHADOW "no shadow password for `%s'%s\n"
#define BAD_PASSWD "invalid password for `%s'%s\n"
#define BAD_DIALUP "invalid dialup password for `%s' on `%s'\n"
#define BAD_ROOT_LOGIN "ILLEGAL ROOT LOGIN%s\n"
#define BAD_GROUP "user `%s' not in group bbs\n"
#define ROOT_LOGIN "ROOT LOGIN%s\n"
#define FAILURE_CNT "exceeded failure limit for `%s'%s\n"
#define REG_LOGIN "`%s' logged in%s\n"
#define LOGIN_REFUSED "LOGIN `%s' REFUSED%s\n"
#define REENABLED2 \
"login `%s' re-enabled after temporary lockout (%d failures).\n"
#define MANY_FAILS "REPEATED login failures%s\n"
/* local function prototypes */
static void usage(void);
static void setup_tty(void);
static void check_flags(int, char * const *);
static void check_nologin(void);
static void init_env(void);
static RETSIGTYPE alarm_handler(int);
int main(int, char **);
/*
* usage - print login command usage and exit
*
* login [ name ]
* login -a hostname (for NetBSD)
* login -r hostname (for rlogind)
* login -h hostname (for telnetd, etc.)
* login -f name (for pre-authenticated login: datakit, xterm, etc.)
*/
static void
usage(void)
{
fprintf(stderr, _("usage: %s [-p] [name]\n"), Prog);
if (!amroot)
exit(1);
fprintf(stderr, _(" %s [-p] [-h host] [-f name]\n"), Prog);
exit(1);
}
static void setup_tty(void)
{
TERMIO termio;
GTTY(0, &termio); /* get terminal characteristics */
/*
* Add your favorite terminal modes here ...
*/
termio.c_lflag |= ISIG|ICANON|ECHO|ECHOE;
termio.c_iflag |= ICRNL;
#if defined(ECHOKE) && defined(ECHOCTL)
termio.c_lflag |= ECHOKE|ECHOCTL;
#endif
#if defined(ECHOPRT) && defined(NOFLSH) && defined(TOSTOP)
termio.c_lflag &= ~(ECHOPRT|NOFLSH|TOSTOP);
#endif
#ifdef ONLCR
termio.c_oflag |= ONLCR;
#endif
#ifdef SUN4
/*
* Terminal setup for SunOS 4.1 courtesy of Steve Allen
* at UCO/Lick.
*/
termio.c_cc[VEOF] = '\04';
termio.c_cflag &= ~CSIZE;
termio.c_cflag |= (PARENB|CS7);
termio.c_lflag |= (ISIG|ICANON|ECHO|IEXTEN);
termio.c_iflag |= (BRKINT|IGNPAR|ISTRIP|IMAXBEL|ICRNL|IXON);
termio.c_iflag &= ~IXANY;
termio.c_oflag |= (XTABS|OPOST|ONLCR);
#endif
/* leave these values unchanged if not specified in login.defs */
termio.c_cc[VERASE] = getdef_num("ERASECHAR", termio.c_cc[VERASE]);
termio.c_cc[VKILL] = getdef_num("KILLCHAR", termio.c_cc[VKILL]);
/*
* ttymon invocation prefers this, but these settings won't come into
* effect after the first username login
*/
STTY(0, &termio);
}
static void check_flags(int argc, char * const *argv)
{
int arg;
/*
* Check the flags for proper form. Every argument starting with
* "-" must be exactly two characters long. This closes all the
* clever rlogin, telnet, and getty holes.
*/
for (arg = 1; arg < argc; arg++) {
if (argv[arg][0] == '-' && strlen(argv[arg]) > 2)
usage();
}
}
static void check_nologin(void)
{
char *fname;
/*
* Check to see if system is turned off for non-root users.
* This would be useful to prevent users from logging in
* during system maintenance. We make sure the message comes
* out for root so she knows to remove the file if she's
* forgotten about it ...
*/
fname = getdef_str("NOLOGINS_FILE");
if (access(fname, F_OK) == 0) {
FILE *nlfp;
int c;
/*
* Cat the file if it can be opened, otherwise just
* print a default message
*/
if ((nlfp = fopen (fname, "r"))) {
while ((c = getc (nlfp)) != EOF) {
if (c == '\n')
putchar ('\r');
putchar (c);
}
fflush (stdout);
fclose (nlfp);
} else
printf("\nSystem closed for routine maintenance\n");
free(fname);
closelog();
exit(0);
}
free(fname);
}
static void init_env(void)
{
char *cp, *tmp;
if ((tmp = getenv("LANG"))) {
addenv("LANG", tmp);
}
/*
* Add the timezone environmental variable so that time functions
* work correctly.
*/
if ((tmp = getenv("TZ"))) {
addenv("TZ", tmp);
}
/*
* Add the clock frequency so that profiling commands work
* correctly.
*/
if ((tmp = getenv("HZ"))) {
addenv("HZ", tmp);
} else if ((cp = getdef_str("ENV_HZ"))) {
addenv(cp, NULL);
}
}
static RETSIGTYPE alarm_handler(int sig)
{
fprintf(stderr, "\nLogin timed out after %d seconds.\n", timeout);
exit(0);
}
/*
* login - create a new login session for a user
*
* login is typically called by getty as the second step of a
* new user session. getty is responsible for setting the line
* characteristics to a reasonable set of values and getting
* the name of the user to be logged in. login may also be
* called to create a new user session on a pty for a variety
* of reasons, such as X servers or network logins.
*/
int main(int argc, char **argv)
{
char username[37];
char tty[BUFSIZ];
char userfile[PATH_MAX];
FILE *ufp;
int reason = PW_LOGIN;
int delay;
int retries;
int failed;
int flag;
int subroot = 0;
int is_console = 0;
int FoundName;
const char *cp;
char *tmp;
char fromhost[512];
struct passwd *pwd;
char **envp = environ;
static char temp_pw[2];
static char temp_shell[] = "/bin/sh";
#ifdef SHADOW_PASSWORD
struct spwd *spwd=NULL;
#endif
#if defined(DES_RPC) || defined(KERBEROS)
/* from pwauth.c */
extern char *clear_pass;
extern int wipe_clear_pass;
/*
* We may need the password later, don't want pw_auth() to wipe it
* (we do it ourselves when it is no longer needed). --marekm
*/
wipe_clear_pass = 0;
#endif
/*
* Some quick initialization.
*/
sanitize_env();
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
initenv();
username[0] = '\0';
amroot = (getuid() == 0);
Prog = Basename(argv[0]);
check_flags(argc, argv);
while ((flag = getopt(argc, argv, "a:d:h:p")) != EOF) {
switch (flag) {
case 'p':
pflg++;
break;
#ifdef __NetBSD__
case 'a':
#endif
case 'h':
hflg++;
hostname = optarg;
reason = PW_TELNET;
break;
case 'd':
/* "-d device" ignored for compatibility */
break;
default:
usage();
}
}
/*
* Allow authentication bypass only if real UID is zero.
*/
if (hflg && !amroot) {
fprintf(stderr, _("%s: permission denied\n"), Prog);
exit(1);
}
if (!isatty(0) || !isatty(1) || !isatty(2))
exit(1); /* must be a terminal */
if (hflg) {
/*
* Only show this before a prompt from telnetd
*/
printf("\nMBSE BBS v%s (Release: %s)\n", VERSION, ReleaseDate);
printf("%s\n\n", COPYRIGHT);
}
/*
* Be picky if run by normal users (possible if installed setuid
* root), but not if run by root. This way it still allows logins
* even if your getty is broken, or if something corrupts utmp,
* but users must "exec login" which will use the existing utmp
* entry (will not overwrite remote hostname). --marekm
*/
checkutmp(!amroot);
STRFCPY(tty, utent.ut_line);
if (hflg) {
#ifdef UT_ADDR
struct hostent *he;
/*
* Fill in the ut_addr field (remote login IP address).
* XXX - login from util-linux does it, but this is not
* the right place to do it. The program that starts
* login (telnetd, rlogind) knows the IP address, so it
* should create the utmp entry and fill in ut_addr.
* gethostbyname() is not 100% reliable (the remote host
* may be unknown, etc.). --marekm
*/
if ((he = gethostbyname(hostname))) {
utent.ut_addr = *((int32_t *)(he->h_addr_list[0]));
#endif
#ifdef UT_HOST
strncpy(utent.ut_host, hostname, sizeof(utent.ut_host));
#endif
#if HAVE_UTMPX_H
strncpy(utxent.ut_host, hostname, sizeof(utxent.ut_host));
#endif
/*
* Add remote hostname to the environment. I think
* (not sure) I saw it once on Irix. --marekm
*/
addenv("REMOTEHOST", hostname);
}
#ifdef __linux__
/* workaround for init/getty leaving junk in ut_host at least in some
version of RedHat. --marekm */
else if (amroot)
memzero(utent.ut_host, sizeof utent.ut_host);
#endif
openlog("mblogin", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
setup_tty();
umask(getdef_num("UMASK", 007));
if (pflg)
while (*envp) /* add inherited environment, */
addenv(*envp++, NULL); /* some variables change later */
/* preserve TERM from getty */
if (!pflg && (tmp = getenv("TERM")))
addenv("TERM", tmp);
/* preserver CONNECT messages from mgetty */
if ((tmp = getenv("CONNECT")))
addenv("CONNECT", tmp);
if ((tmp = getenv("CALLER_ID")))
addenv("CALLER_ID", tmp);
/* get the mbse environment */
pw = getpwnam("mbse");
addenv("MBSE_ROOT", pw->pw_dir);
snprintf(userfile, PATH_MAX, "%s/etc/users.data", pw->pw_dir);
check_nologin();
init_env();
if (optind < argc) { /* get the user name */
#ifdef SVR4
/*
* The "-h" option can't be used with a command-line username,
* because telnetd invokes us as: login -h host TERM=...
*/
if (! hflg)
#endif
{
STRFCPY(username, argv[optind]);
strzero(argv[optind]);
++optind;
}
}
#ifdef SVR4
/*
* check whether ttymon has done the prompt for us already
*/
{
char *ttymon_prompt;
if ((ttymon_prompt = getenv("TTYPROMPT")) != NULL && (*ttymon_prompt != 0)) {
/* read name, without prompt */
login_prompt((char *)0, username, sizeof username);
}
}
#endif /* SVR4 */
if (optind < argc) /* now set command line variables */
set_env(argc - optind, &argv[optind]);
if (hflg)
cp = hostname;
else
#ifdef UT_HOST
if (utent.ut_host[0])
cp = utent.ut_host;
else
#endif
#if HAVE_UTMPX_H
if (utxent.ut_host[0])
cp = utxent.ut_host;
else
#endif
cp = "";
if (*cp)
snprintf(fromhost, sizeof fromhost, _(" on `%s' from `%s'"), tty, cp);
else
snprintf(fromhost, sizeof fromhost, _(" on `%s'"), tty);
top:
/* only allow ALARM sec. for login */
signal(SIGALRM, alarm_handler);
timeout = getdef_num("LOGIN_TIMEOUT", ALARM);
if (timeout > 0)
alarm(timeout);
environ = newenvp; /* make new environment active */
delay = getdef_num("FAIL_DELAY", 1);
retries = getdef_num("LOGIN_RETRIES", RETRIES);
while (1) { /* repeatedly get login/password pairs */
failed = 0; /* haven't failed authentication yet */
if (! username[0]) { /* need to get a login id */
if (subroot) {
closelog ();
exit (1);
}
preauth_flag = 0;
login_prompt(_("login: "), username, sizeof username);
continue;
}
/*
* Here we try usernames on unix names and Fidonet style
* names that are stored in the bbs userdatabase.
* The name "bbs" is for new users, don't check the bbs userfile.
* If allowed from login.defs accept the name "mbse".
*/
FoundName = 0;
if (strcmp(username, getdef_str("NEWUSER_ACCOUNT")) == 0) {
FoundName = 1;
}
if ((getdef_bool("ALLOW_MBSE") != 0) && (strcmp(username, "mbse") == 0)) {
FoundName = 1;
}
if (! FoundName) {
if ((ufp = fopen(userfile, "r"))) {
fread(&usrconfighdr, sizeof(usrconfighdr), 1, ufp);
while (fread(&usrconfig, usrconfighdr.recsize, 1, ufp) == 1) {
if ((strcasecmp(usrconfig.sUserName, username) == 0) ||
(strcasecmp(usrconfig.sHandle, username) == 0) ||
(strcmp(usrconfig.Name, username) == 0)) {
FoundName = 1;
STRFCPY(username, usrconfig.Name);
break;
}
}
fclose(ufp);
}
}
if (!FoundName) {
if (getdef_bool("ASK_NEWUSER") != 0) {
/*
* User entered none excisting name, offer him/her the choice
* to register as a new user.
*/
login_prompt(_("Do you want to register as new user? [y/N]: "), username, sizeof username);
if ((username[0] && (toupper(username[0]) == 'Y'))) {
FoundName = 1;
preauth_flag = 0;
STRFCPY(username, getdef_str("NEWUSER_ACCOUNT"));
syslog(LOG_WARNING, "unknown user wants to register");
}
}
}
if ((! (pwd = getpwnam(username))) || (FoundName == 0)) {
pwent.pw_name = username;
strcpy(temp_pw, "!");
pwent.pw_passwd = temp_pw;
pwent.pw_shell = temp_shell;
preauth_flag = 0;
failed = 1;
} else {
pwent = *pwd;
}
#ifdef SHADOW_PASSWORD
spwd = NULL;
if (pwd && strcmp(pwd->pw_passwd, SHADOW_PASSWD_STRING) == 0) {
spwd = getspnam(username);
if (spwd)
pwent.pw_passwd = spwd->sp_pwdp;
else
syslog(LOG_WARNING, NO_SHADOW, username, fromhost);
}
#endif /* SHADOWPWD */
/*
* If the encrypted password begins with a "!", the account
* is locked and the user cannot login, even if they have
* been "pre-authenticated."
*/
if (pwent.pw_passwd[0] == '!' || pwent.pw_passwd[0] == '*')
failed = 1;
/*
* The -r and -f flags provide a name which has already
* been authenticated by some server.
*/
if (preauth_flag)
goto auth_ok;
if (pw_auth(pwent.pw_passwd, username, reason, (char *) 0) == 0)
goto auth_ok;
/*
* Don't log unknown usernames - I mistyped the password for
* username at least once... Should probably use LOG_AUTHPRIV
* for those who really want to log them. --marekm
*/
syslog(LOG_WARNING, BAD_PASSWD, (pwd || getdef_bool("LOG_UNKFAIL_ENAB")) ? username : "UNKNOWN", fromhost);
failed = 1;
auth_ok:
/*
* This is the point where all authenticated users
* wind up. If you reach this far, your password has
* been authenticated and so on.
*/
#if defined(RADIUS) && !(defined(DES_RPC) || defined(KERBEROS))
if (clear_pass) {
strzero(clear_pass);
clear_pass = NULL;
}
#endif
if (! failed && pwent.pw_name && pwent.pw_uid == 0 && ! is_console) {
syslog(LOG_CRIT, BAD_ROOT_LOGIN, fromhost);
failed = 1;
}
#ifdef LOGIN_ACCESS
if (!failed && !login_access(username, *hostname ? hostname : tty)) {
syslog(LOG_WARNING, LOGIN_REFUSED, username, fromhost);
failed = 1;
}
#endif
if (! failed)
break;
memzero(username, sizeof username);
if (--retries <= 0)
syslog(LOG_CRIT, MANY_FAILS, fromhost);
#if 1
/*
* If this was a passwordless account and we get here,
* login was denied (securetty, faillog, etc.). There
* was no password prompt, so do it now (will always
* fail - the bad guys won't see that the passwordless
* account exists at all). --marekm
*/
if (pwent.pw_passwd[0] == '\0')
pw_auth("!", username, reason, (char *) 0);
#endif
/*
* Wait a while (a la SVR4 /usr/bin/login) before attempting
* to login the user again. If the earlier alarm occurs
* before the sleep() below completes, login will exit.
*/
if (delay > 0)
sleep(delay);
puts(_("Login incorrect"));
} /* while (1) */
(void) alarm (0); /* turn off alarm clock */
if (getenv("IFS")) /* don't export user IFS ... */
addenv("IFS= \t\n", NULL); /* ... instead, set a safe IFS */
setutmp(username, tty, hostname); /* make entry in utmp & wtmp files */
if (pwent.pw_shell[0] == '*') { /* subsystem root */
subsystem (&pwent); /* figure out what to execute */
subroot++; /* say i was here again */
endpwent (); /* close all of the file which were */
endgrent (); /* open in the original rooted file */
#ifdef SHADOW_PASSWORD
endspent (); /* system. they will be re-opened */
#endif
#ifdef SHADOWGRP
endsgent (); /* in the new rooted file system */
#endif
goto top; /* go do all this all over again */
}
if (getdef_bool("LASTLOG_ENAB")) /* give last login and log this one */
dolastlog(&lastlog, &pwent, utent.ut_line, hostname);
#ifdef SVR4_SI86_EUA
sysi86(SI86LIMUSER, EUA_ADD_USER); /* how do we test for fail? */
#endif
#ifdef AGING
/*
* Have to do this while we still have root privileges, otherwise
* we don't have access to /etc/shadow. expire() closes password
* files, and changes to the user in the child before executing
* the passwd program. --marekm
*/
#ifdef SHADOW_PASSWORD
if (spwd) { /* check for age of password */
if (expire (&pwent, spwd)) {
pwd = getpwnam(username);
spwd = getspnam(username);
if (pwd)
pwent = *pwd;
}
}
#else
#ifdef ATT_AGE
if (pwent.pw_age && pwent.pw_age[0]) {
if (expire (&pwent)) {
pwd = getpwnam(username);
if (pwd)
pwent = *pwd;
}
}
#endif /* ATT_AGE */
#endif /* SHADOWPWD */
#endif /* AGING */
setup_limits(&pwent); /* nice, ulimit etc. */
chown_tty(tty, &pwent);
if (setup_uid_gid(&pwent, is_console))
exit(1);
#ifdef KERBEROS
if (clear_pass)
login_kerberos(username, clear_pass);
#endif
#ifdef DES_RPC
if (clear_pass)
login_desrpc(clear_pass);
#endif
#if defined(DES_RPC) || defined(KERBEROS)
if (clear_pass)
strzero(clear_pass);
#endif
setup_env(&pwent); /* set env vars, cd to the home dir */
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
addenv("HUSHLOGIN=TRUE", NULL);
signal(SIGQUIT, SIG_DFL); /* default quit signal */
signal(SIGTERM, SIG_DFL); /* default terminate signal */
signal(SIGALRM, SIG_DFL); /* default alarm signal */
signal(SIGHUP, SIG_DFL); /* added this. --marekm */
signal(SIGINT, SIG_DFL); /* default interrupt signal */
endpwent(); /* stop access to password file */
endgrent(); /* stop access to group file */
#ifdef SHADOW_PASSWORD
endspent(); /* stop access to shadow passwd file */
#endif
#ifdef SHADOWGRP
endsgent(); /* stop access to shadow group file */
#endif
if (pwent.pw_uid == 0)
syslog(LOG_NOTICE, ROOT_LOGIN, fromhost);
else
syslog(LOG_INFO, REG_LOGIN, username, fromhost);
closelog();
shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
/*NOTREACHED*/
return 0;
}

248
unix/mblogin.h Normal file
View File

@@ -0,0 +1,248 @@
/* $Id: mblogin.h,v 1.3 2003/12/23 18:33:42 mbroek Exp $ */
#ifndef _MBLOGIN_H
#define _MBLOGIN_H
#define ReleaseDate __DATE__
#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c))
/* Take care of NLS matters. */
#if HAVE_LOCALE_H
# include <locale.h>
#endif
#if !HAVE_SETLOCALE
# define setlocale(Category, Locale) /* empty */
#endif
#define gettext_noop(String) (String)
/* #define gettext_def(String) "#define String" */
#if ENABLE_NLS
# include <libintl.h>
# define _(Text) gettext (Text)
#else
# undef bindtextdomain
# define bindtextdomain(Domain, Directory) /* empty */
# undef textdomain
# define textdomain(Domain) /* empty */
# define _(Text) Text
#endif
#ifndef P_
# ifdef PROTOTYPES
# define P_(x) x
# else
# define P_(x) ()
# endif
#endif
#if STDC_HEADERS
# include <stdlib.h>
# include <string.h>
#else /* not STDC_HEADERS */
# ifndef HAVE_STRCHR
# define strchr index
# define strrchr rindex
# endif
char *strchr(), *strrchr(), *strtok();
# ifndef HAVE_MEMCPY
# define memcpy(d, s, n) bcopy((s), (d), (n))
# endif
#endif /* not STDC_HEADERS */
#include <sys/stat.h>
#include <sys/types.h>
#if HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else /* not TIME_WITH_SYS_TIME */
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif /* not TIME_WITH_SYS_TIME */
#ifdef HAVE_MEMSET
# define memzero(ptr, size) memset((void *)(ptr), 0, (size))
#else
# define memzero(ptr, size) bzero((char *)(ptr), (size))
#endif
#define strzero(s) memzero(s, strlen(s)) /* warning: evaluates twice */
#ifdef HAVE_DIRENT_H /* DIR_SYSV */
# include <dirent.h>
# define DIRECT dirent
#else
# ifdef HAVE_SYS_NDIR_H /* DIR_XENIX */
# include <sys/ndir.h>
# endif
# ifdef HAVE_SYS_DIR_H /* DIR_??? */
# include <sys/dir.h>
# endif
# ifdef HAVE_NDIR_H /* DIR_BSD */
# include <ndir.h>
# endif
# define DIRECT direct
#endif
#ifdef SHADOWPWD
/*
* Possible cases:
* - /usr/include/shadow.h exists and includes the shadow group stuff.
* - /usr/include/shadow.h exists, but we use our own gshadow.h.
* - /usr/include/shadow.h doesn't exist, use our own shadow.h and gshadow.h.
*/
#if HAVE_SHADOW_H
#include <shadow.h>
#if defined(SHADOWGRP) && !defined(GSHADOW)
#include "gshadow_.h"
#endif
#else /* not HAVE_SHADOW_H */
#include "shadow_.h"
#ifdef SHADOWGRP
#include "gshadow_.h"
#endif
#endif /* not HAVE_SHADOW_H */
#endif /* SHADOWPWD */
#include <limits.h>
#ifndef NGROUPS_MAX
#ifdef NGROUPS
#define NGROUPS_MAX NGROUPS
#else
#define NGROUPS_MAX 64
#endif
#endif
#ifndef F_OK
# define F_OK 0
# define X_OK 1
# define W_OK 2
# define R_OK 4
#endif
#if HAVE_TERMIOS_H
# include <termios.h>
# define STTY(fd, termio) tcsetattr(fd, TCSANOW, termio)
# define GTTY(fd, termio) tcgetattr(fd, termio)
# define TERMIO struct termios
# define USE_TERMIOS
#else /* assumed HAVE_TERMIO_H */
# include <sys/ioctl.h>
# include <termio.h>
# define STTY(fd, termio) ioctl(fd, TCSETA, termio)
# define GTTY(fd, termio) ioctl(fd, TCGETA, termio)
# define TEMRIO struct termio
# define USE_TERMIO
#endif
/*
* Password aging constants
*
* DAY - seconds / day
* WEEK - seconds / week
* SCALE - seconds / aging unit
*/
/* Solaris defines this in shadow.h */
#ifndef DAY
#define DAY (24L*3600L)
#endif
#define WEEK (7*DAY)
#ifdef ITI_AGING
#define SCALE 1
#else
#define SCALE DAY
#endif
/* Copy string pointed by B to array A with size checking. It was originally
* in lmain.c but is _very_ useful elsewhere. Some setuid root programs with
* very sloppy coding used to assume that BUFSIZ will always be enough... */
/* danger - side effects */
#define STRFCPY(A,B) \
(strncpy((A), (B), sizeof(A) - 1), (A)[sizeof(A) - 1] = '\0')
/* get rid of a few ugly repeated #ifdefs in pwent.c and grent.c */
/* XXX - this is ugly too, configure should test it and not check for
any hardcoded system names, if possible. --marekm */
#if defined(SVR4) || defined(AIX) || defined(__linux__)
#define SETXXENT_TYPE void
#define SETXXENT_RET(x) return
#define SETXXENT_TEST(x) x; if (0) /* compiler should optimize this away */
#else
#define SETXXENT_TYPE int
#define SETXXENT_RET(x) return(x)
#define SETXXENT_TEST(x) if (x)
#endif
#ifndef PASSWD_FILE
#define PASSWD_FILE "/etc/passwd"
#endif
#ifndef GROUP_FILE
#define GROUP_FILE "/etc/group"
#endif
#ifdef SHADOWPWD
#ifndef SHADOW_FILE
#define SHADOW_FILE "/etc/shadow"
#endif
#endif
#ifdef SHADOWGRP
#ifndef SGROUP_FILE
#define SGROUP_FILE "/etc/gshadow"
#endif
#endif
#define PASSWD_PAG_FILE PASSWD_FILE ".pag"
#define GROUP_PAG_FILE GROUP_FILE ".pag"
#define SHADOW_PAG_FILE SHADOW_FILE ".pag"
#define SGROUP_PAG_FILE SGROUP_FILE ".pag"
#ifndef NULL
#define NULL ((void *) 0)
#endif
#ifdef sun /* hacks for compiling on SunOS */
# ifndef SOLARIS
extern int fputs();
extern char *strdup();
extern char *strerror();
# endif
#endif
/*
* string to use for the pw_passwd field in /etc/passwd when using
* shadow passwords - most systems use "x" but there are a few
* exceptions, so it can be changed here if necessary. --marekm
*/
#ifndef SHADOW_PASSWD_STRING
#define SHADOW_PASSWD_STRING "x"
#endif
#ifdef PAM_STRERROR_NEEDS_TWO_ARGS /* Linux-PAM 0.59+ */
#define PAM_STRERROR(pamh, err) pam_strerror(pamh, err)
#else
#define PAM_STRERROR(pamh, err) pam_strerror(err)
#endif
#endif

1163
unix/mbpasswd.c Normal file

File diff suppressed because it is too large Load Diff

47
unix/mbpasswd.h Normal file
View File

@@ -0,0 +1,47 @@
#ifndef _MBPASSWD_H
#define _MBPASSWD_H
/* $Id: mbpasswd.h,v 1.4 2005/08/27 12:06:49 mbse Exp $ */
/* danger - side effects */
#define STRFCPY(A,B) \
(strncpy((A), (B), sizeof(A) - 1), (A)[sizeof(A) - 1] = '\0')
/*
* exit status values
*/
#define E_SUCCESS 0 /* success */
#define E_NOPERM 1 /* permission denied */
#define E_USAGE 2 /* invalid combination of options */
#define E_FAILURE 3 /* unexpected failure, nothing done */
#define E_MISSING 4 /* unexpected failure, passwd file missing */
#define E_PWDBUSY 5 /* passwd file busy, try again later */
#define E_BAD_ARG 6 /* invalid argument to option */
/*
* Function prototypes
*/
struct passwd *get_my_pwent(void);
static int new_password (const struct passwd *, char *);
void pwd_init(void);
char *crypt_make_salt(void);
char *pw_encrypt(const char *, const char *);
int i64c(int);
char *l64a(long);
#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
static void fail_exit(int);
static void oom(void);
static void update_noshadow(int);
#endif
#ifdef SHADOW_PASSWORD
struct spwd *pwd_to_spwd(const struct passwd *);
static void update_shadow(void);
#endif
char *Basename(char *);
#endif

518
unix/mbuseradd.c Normal file
View File

@@ -0,0 +1,518 @@
/*****************************************************************************
*
* $Id: mbuseradd.c,v 1.24 2007/05/28 10:40:24 mbse Exp $
* Purpose ...............: setuid root version of useradd
*
*****************************************************************************
* Copyright (C) 1997-2007
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <sys/types.h>
#include <grp.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/param.h>
#include <syslog.h>
#include <time.h>
#if (defined(__FreeBSD__) && __FreeBSD_version >= 600000)
#define FreeBSD_sysctl 1
#endif
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(FreeBSD_sysctl)
#include <sys/sysctl.h>
#endif
#include "xmalloc.h"
#include "mbuseradd.h"
/*
* Milliseconds timer, returns 0 on success.
*/
int msleep(int msecs)
{
int rc;
struct timespec req, rem;
rem.tv_sec = 0;
rem.tv_nsec = 0;
req.tv_sec = msecs / 1000;
req.tv_nsec = (msecs % 1000) * 1000000;
while (1) {
rc = nanosleep(&req, &rem);
if (rc == 0)
break;
if ((errno == EINVAL) || (errno == EFAULT))
break;
/*
* Error was EINTR, run timer again to complete.
*/
req.tv_sec = rem.tv_sec;
req.tv_nsec = rem.tv_nsec;
rem.tv_sec = 0;
rem.tv_nsec = 0;
}
return rc;
}
int execute(char **args, char *in, char *out, char *err)
{
char buf[PATH_MAX];
int i, pid, status = 0, rc = 0;
memset(&buf, 0, sizeof(buf));
for (i = 0; i < 16; i++) {
if (args[i])
snprintf(buf + strlen(buf), PATH_MAX - strlen(buf), " %s", args[i]);
else
break;
}
syslog(LOG_WARNING, "Execute:%s", buf);
fflush(stdout);
fflush(stderr);
if ((pid = fork()) == 0) {
msleep(150);
if (in) {
close(0);
if (open(in, O_RDONLY) != 0) {
syslog(LOG_WARNING, "Reopen of stdin to %s failed", in);
_exit(-1);
}
}
if (out) {
close(1);
if (open(out, O_WRONLY | O_APPEND | O_CREAT,0600) != 1) {
syslog(LOG_WARNING, "Reopen of stdout to %s failed", out);
_exit(-1);
}
}
if (err) {
close(2);
if (open(err, O_WRONLY | O_APPEND | O_CREAT,0600) != 2) {
syslog(LOG_WARNING, "Reopen of stderr to %s failed", err);
_exit(-1);
}
}
rc = execv(args[0],args);
syslog(LOG_WARNING, "Exec \"%s\" returned %d", args[0], rc);
_exit(-1);
}
do {
rc = wait(&status);
} while (((rc > 0) && (rc != pid)) || ((rc == -1) && (errno == EINTR)));
return 0;
}
void makedir(char *path, mode_t mode, uid_t owner, gid_t group)
{
if (mkdir(path, mode) != 0) {
syslog(LOG_WARNING, "Can't create directory %s:%s", path, strerror(errno));
exit(2);
}
if ((chown(path, owner, group)) == -1) {
syslog(LOG_WARNING, "Unable to change ownership of %s", path);
exit(2);
}
}
/*
* Internal version of basename to make this better portable.
*/
char *Basename(char *str)
{
char *cp = strrchr(str, '/');
return cp ? cp+1 : str;
}
/*
* Function will create the users name in the passwd file
* Note that this function must run setuid root!
*/
int main(int argc, char *argv[])
{
char *temp, *shell, *homedir, *args[16], *parent;
int i;
struct passwd *pwent, *pwuser;
struct group *gr;
pid_t ppid;
#if defined(__OpenBSD__)
#define ARG_SIZE 60
static char **s, buf[ARG_SIZE];
size_t siz = 100;
char **p;
int mib[4];
#elif defined(__NetBSD__) || defined(FreeBSD_sysctl)
static char **s;
size_t siz = 100;
int mib[4];
#else
FILE *fp;
#endif
if (argc != 5)
Help();
/*
* First simple check for argument overflow
*/
for (i = 1; i < 5; i++) {
if (strlen(argv[i]) > 80) {
fprintf(stderr, "mbuseradd: Argument %d is too long\n", i);
exit(1);
}
}
/*
* Check calling username
*/
ppid = getuid();
pwent = getpwuid(ppid);
if (!pwent) {
fprintf(stderr, "mbuseradd: Cannot determine your user name.\n");
exit(1);
}
if (strcmp(pwent->pw_name, (char *)"mbse") && strcmp(pwent->pw_name, (char *)"bbs")) {
fprintf(stderr, "mbuseradd: only users `mbse' and `bbs' may do this.\n");
exit(1);
}
/*
* Get my groupname, this must be "bbs", other users may not
* use this program, not even root.
*/
gr = getgrgid(pwent->pw_gid);
if (!gr) {
fprintf(stderr, "mbuseradd: Cannot determine group name.\n");
exit(1);
}
if (strcmp(gr->gr_name, (char *)"bbs")) {
fprintf(stderr, "mbuseradd: You are not a member of group `bbs'.\n");
exit(1);
}
/*
* Find out the name of our parent.
*/
temp = calloc(PATH_MAX, sizeof(char));
ppid = getppid();
#if defined(__OpenBSD__)
/*
* Systems that use sysctl to get process information
*/
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
mib[2] = ppid;
mib[3] = KERN_PROC_ARGV;
if ((s = realloc(s, siz)) == NULL) {
fprintf(stderr, "mbuseradd: no memory\n");
exit(1);
}
if (sysctl(mib, 4, s, &siz, NULL, 0) == -1) {
perror("");
fprintf(stderr, "mbuseradd: sysctl call failed\n");
exit(1);
}
buf[0] = '\0';
for (p = s; *p != NULL; p++) {
if (p != s)
strlcat(buf, " ", sizeof(buf));
strlcat(buf, *p, sizeof(buf));
}
parent = xstrcpy(buf);
#elif defined(__NetBSD__)
/*
* Systems that use sysctl to get process information
*/
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
mib[2] = ppid;
mib[3] = KERN_PROC_ARGV;
if ((s = realloc(s, siz)) == NULL) {
fprintf(stderr, "mbuseradd: no memory\n");
exit(1);
}
if (sysctl(mib, 4, s, &siz, NULL, 0) == -1) {
perror("");
fprintf(stderr, "mbuseradd: sysctl call failed\n");
exit(1);
}
parent = xstrcpy((char *)s);
#elif defined(FreeBSD_sysctl)
/*
* For FreeBSD 6.0 and later.
*/
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_ARGS;
mib[3] = ppid;
if ((s = realloc(s, siz)) == NULL) {
fprintf(stderr, "mbuseradd: no memory\n");
exit(1);
}
if (sysctl(mib, 4, s, &siz, NULL, 0) == -1) {
perror("");
fprintf(stderr, "mbuseradd: sysctl call failed\n");
exit(1);
}
parent = xstrcpy((char *)s);
#else
/*
* Systems with /proc filesystem like Linux, old FreeBSD
*/
snprintf(temp, PATH_MAX, "/proc/%d/cmdline", ppid);
if ((fp = fopen(temp, "r")) == NULL) {
fprintf(stderr, "mbuseradd: can't read %s\n", temp);
exit(1);
}
fgets(temp, PATH_MAX-1, fp);
fclose(fp);
parent = xstrcpy(Basename(temp));
#endif
if (strcmp((char *)"-mbnewusr", parent)) {
fprintf(stderr, "mbuseradd: illegal parent \"%s\"\n", parent);
free(temp);
free(parent);
exit(1);
}
memset(args, 0, sizeof(args));
shell = calloc(PATH_MAX, sizeof(char));
homedir = calloc(PATH_MAX, sizeof(char));
if (setuid(0) == -1 || setgid(1) == -1) {
perror("");
fprintf(stderr, "mbuseradd: Unable to setuid(root) or setgid(root)\n");
fprintf(stderr, "Make sure that this program is set to -rwsr-sr-x\n");
fprintf(stderr, "Owner must be root and group root\n");
exit(1);
}
umask(0000);
/*
* We don't log into MBSE BBS logfiles but to the system logfiles,
* because we are modifying system files not belonging to MBSE BBS.
*/
openlog("mbuseradd", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
syslog(LOG_WARNING, "mbuseradd %s %s %s %s", argv[1], argv[2], argv[3], argv[4]);
/*
* Build command to add user entry to the /etc/passwd and /etc/shadow
* files. We use the systems own useradd program.
*/
#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__)
if ((access("/usr/bin/useradd", R_OK)) == 0)
args[0] = (char *)"/usr/bin/useradd";
else if ((access("/bin/useradd", R_OK)) == 0)
args[0] = (char *)"/bin/useradd";
else if ((access("/usr/sbin/useradd", R_OK)) == 0)
args[0] = (char *)"/usr/sbin/useradd";
else if ((access("/sbin/useradd", R_OK)) == 0)
args[0] = (char *)"/sbin/useradd";
else {
syslog(LOG_WARNING, "Can't find useradd");
exit(1);
}
#elif __FreeBSD__
if ((access("/usr/sbin/pw", X_OK)) == 0)
args[0] = (char *)"/usr/sbin/pw";
else if ((access("/sbin/pw", X_OK)) == 0)
args[0] = (char *)"/sbin/pw";
else {
syslog(LOG_WARNING, "Can't find pw");
exit(1);
}
#else
#error "Don't know how to add a user on this OS"
#endif
snprintf(shell, PATH_MAX, "%s/bin/mbsebbs", getenv("MBSE_ROOT"));
snprintf(homedir, PATH_MAX, "%s/%s", argv[4], argv[2]);
#if defined(__linux__)
args[1] = (char *)"-c";
args[2] = argv[3];
args[3] = (char *)"-d";
args[4] = homedir;
args[5] = (char *)"-g";
args[6] = argv[1];
args[7] = (char *)"-s";
args[8] = shell;
args[9] = argv[2];
args[10] = NULL;
#elif defined(__NetBSD__) || defined(__OpenBSD__)
args[1] = (char *)"-c";
args[2] = argv[3];
args[3] = (char *)"-d";
args[4] = homedir;
args[5] = (char *)"-g";
args[6] = argv[1];
args[7] = (char *)"-s";
args[8] = shell;
args[9] = (char *)"-m";
args[10] = argv[2];
args[11] = NULL;
#elif defined(__FreeBSD__)
args[1] = (char *)"useradd";
args[2] = argv[2];
args[3] = (char *)"-c";
args[4] = argv[3];
args[5] = (char *)"-d";
args[6] = homedir;
args[7] = (char *)"-g";
args[8] = argv[1];
args[9] = (char *)"-s";
args[10] = shell;
args[11] = NULL;
#else
#error "Don't know how to add a user on this OS"
#endif
if (execute(args, (char *)"/dev/tty", (char *)"/dev/tty", (char *)"/dev/tty") != 0) {
syslog(LOG_WARNING, "Failed to create unix account");
exit(1);
}
syslog(LOG_WARNING, "Created Unix account");
/*
* Now create directories and files for this user.
*/
if ((pwent = getpwnam((char *)"mbse")) == NULL) {
syslog(LOG_WARNING, "Can't get password entry for \"mbse\"");
exit(2);
}
/*
*
* Check bbs users base home directory
*/
if ((access(argv[4], R_OK)) != 0) {
syslog(LOG_WARNING, "No bbs base homedirectory, creating..");
makedir(argv[4], 0770, pwent->pw_uid, pwent->pw_gid);
}
/*
* Now create users home directory. Check for an existing directory,
* some systems have already created a home directory. If one is found
* it is removed to create a fresh one.
*/
if ((access(homedir, R_OK)) == 0) {
if ((access("/bin/rm", X_OK)) == 0)
args[0] = (char *)"/bin/rm";
else if ((access("/usr/bin/rm", X_OK)) == 0)
args[0] = (char *)"/usr/bin/rm";
else {
syslog(LOG_WARNING, "Can't find rm");
exit(2);
}
args[1] = (char *)"-Rf";
args[2] = homedir;
args[3] = NULL;
i = execute(args, (char *)"/dev/tty", (char *)"/dev/tty", (char *)"/dev/tty");
if (i != 0) {
syslog(LOG_WARNING, "Unable remove old home directory");
exit(2);
}
}
/*
* Create users home directory.
*/
if ((pwuser = getpwnam(argv[2])) == NULL) {
syslog(LOG_WARNING, "Can't get passwd entry for %s", argv[2]);
exit(2);
}
makedir(homedir, 0770, pwuser->pw_uid, pwent->pw_gid);
/*
* Create Maildir and subdirs for Qmail.
*/
snprintf(temp, PATH_MAX, "%s/%s/Maildir", argv[4], argv[2]);
makedir(temp, 0700, pwuser->pw_uid, pwent->pw_gid);
snprintf(temp, PATH_MAX, "%s/%s/Maildir/cur", argv[4], argv[2]);
makedir(temp, 0700, pwuser->pw_uid, pwent->pw_gid);
snprintf(temp, PATH_MAX, "%s/%s/Maildir/new", argv[4], argv[2]);
makedir(temp, 0700, pwuser->pw_uid, pwent->pw_gid);
snprintf(temp, PATH_MAX, "%s/%s/Maildir/tmp", argv[4], argv[2]);
makedir(temp, 0700, pwuser->pw_uid, pwent->pw_gid);
#ifdef _VPOPMAIL_PATH
snprintf(temp, PATH_MAX, "%s/vadduser", _VPOPMAIL_PATH);
args[0] = temp;
args[1] = argv[2];
args[2] = argv[2];
args[3] = NULL;
if (execute(args, (char *)"/dev/tty", (char *)"/dev/tty", (char *)"/dev/tty") != 0) {
syslog(LOG_WARNING, "Failed to create vpopmail account");
} else {
syslog(LOG_WARNING, "Created vpopmail account");
}
#endif
free(shell);
free(temp);
free(homedir);
syslog(LOG_WARNING, "Added system account for user\"%s\"", argv[2]);
exit(0);
}
void Help()
{
fprintf(stderr, "\nmbuseradd commandline:\n\n");
fprintf(stderr, "mbuseradd [gid] [name] [comment] [usersdir]\n");
exit(1);
}

10
unix/mbuseradd.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef _MBUSERADD_H
#define _MBUSERADD_H
int execute(char **, char *, char *, char *);
void makedir(char *, mode_t, uid_t, gid_t);
void Help(void);
#endif

72
unix/myname.c Normal file
View File

@@ -0,0 +1,72 @@
/*****************************************************************************
*
* File ..................: mbuseradd/myname.c
* Purpose ...............: MBSE BBS Shadow Password Suite
* Last modification date : 25-Jul-2000
* Original Source .......: Shadow Password Suite
* Original Copyrioght ...: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2000
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/*
* myname.c - determine the current username and get the passwd entry
*
* Copyright (C) 1996 Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>
*
* This code may be freely used, modified and distributed for any purpose.
* There is no warranty, if it breaks you have to keep both pieces, etc.
* If you improve it, please send me your changes. Thanks!
*/
#include "../config.h"
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
struct passwd *get_my_pwent(void)
{
struct passwd *pw;
const char *cp = getlogin();
uid_t ruid = getuid();
/*
* Try getlogin() first - if it fails or returns a non-existent
* username, or a username which doesn't match the real UID, fall
* back to getpwuid(getuid()). This should work reasonably with
* usernames longer than the utmp limit (8 characters), as well as
* shared UIDs - but not both at the same time...
*
* XXX - when running from su, will return the current user (not
* the original user, like getlogin() does). Does this matter?
*/
if (cp && *cp && (pw = getpwnam(cp)) && pw->pw_uid == ruid)
return pw;
return getpwuid(ruid);
}

7
unix/myname.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef _MYNAME_H
#define _MYNAME_H
struct passwd *get_my_pwent(void);
#endif

73
unix/putpwent.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "../config.h"
#ifndef HAVE_PUTPWENT
#include <stdio.h>
#include <pwd.h>
#include "putpwent.h"
/*
* putpwent - Output a (struct passwd) in character format
*
* putpwent() writes out a (struct passwd) in the format it appears
* in in flat ASCII files.
*
* (Author: Dr. Micheal Newberry)
*/
int putpwent(const struct passwd *p, FILE *f)
{
int status;
#if defined(SUN) || defined(BSD) || defined(SUN4)
status = fprintf (f, "%s:%s:%d:%d:%s,%s:%s:%s\n",
p->pw_name, p->pw_passwd, p->pw_uid, p->pw_gid,
p->pw_gecos, p->pw_comment, p->pw_dir, p->pw_shell) == EOF;
#else
status = fprintf (f, "%s:%s", p->pw_name, p->pw_passwd) == EOF;
#ifdef ATT_AGE
if (p->pw_age && p->pw_age[0])
status |= fprintf (f, ",%s", p->pw_age) == EOF;
#endif
status |= fprintf (f, ":%d:%d:%s", p->pw_uid, p->pw_gid,
p->pw_gecos) == EOF;
#ifdef ATT_COMMENT
if (p->pw_comment && p->pw_comment[0])
status |= fprintf (f, ",%s", p->pw_comment) == EOF;
#endif
status |= fprintf (f, ":%s:%s\n", p->pw_dir, p->pw_shell) == EOF;
#endif
return status;
}
#endif

14
unix/putpwent.h Normal file
View File

@@ -0,0 +1,14 @@
#include "../config.h"
#ifndef HAVE_PUTPWENT
#ifndef _PUTPWENT_H
#define _PUTPWENT_H
int putpwent(const struct passwd *, FILE *);
#endif
#endif

348
unix/pw_util.c Normal file
View File

@@ -0,0 +1,348 @@
/*****************************************************************************
*
* $Id: pw_util.c,v 1.11 2004/12/28 15:30:53 mbse Exp $
* Purpose ...............: FreeBSD/NetBSD password utilities.
* Remark ................: Taken from FreeBSD and modified for MBSE BBS.
*
*****************************************************************************
* Copyright (C) 1997-2002
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/*
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#include "../config.h"
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <syslog.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pw_util.h"
char *tempname;
static int lockfd;
void pw_init()
{
struct rlimit rlim;
/* Unlimited resource limits. */
rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY;
(void)setrlimit(RLIMIT_CPU, &rlim);
(void)setrlimit(RLIMIT_FSIZE, &rlim);
(void)setrlimit(RLIMIT_STACK, &rlim);
(void)setrlimit(RLIMIT_DATA, &rlim);
(void)setrlimit(RLIMIT_RSS, &rlim);
/* Don't drop core (not really necessary, but GP's). */
rlim.rlim_cur = rlim.rlim_max = 0;
(void)setrlimit(RLIMIT_CORE, &rlim);
/* Turn off signals. */
(void)signal(SIGALRM, SIG_IGN);
(void)signal(SIGHUP, SIG_IGN);
(void)signal(SIGINT, SIG_IGN);
(void)signal(SIGPIPE, SIG_IGN);
(void)signal(SIGQUIT, SIG_IGN);
(void)signal(SIGTERM, SIG_IGN);
/* Create with exact permissions. */
(void)umask(0);
}
int pw_lock()
{
/*
* If the master password file doesn't exist, the system is hosed.
* Might as well try to build one. Set the close-on-exec bit so
* that users can't get at the encrypted passwords while editing.
* Open should allow flock'ing the file; see 4.4BSD. XXX
*/
for (;;) {
struct stat st;
lockfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
if (lockfd < 0 || fcntl(lockfd, F_SETFD, 1) == -1) {
syslog(LOG_ERR, "%s", _PATH_MASTERPASSWD);
fprintf(stderr, "%s: %s\n", strerror(errno), _PATH_MASTERPASSWD);
exit(1);
}
if (flock(lockfd, LOCK_EX|LOCK_NB)) {
syslog(LOG_ERR, "the password db file is busy");
fprintf(stderr, "the password db file is busy\n");
exit(1);
}
/*
* If the password file was replaced while we were trying to
* get the lock, our hardlink count will be 0 and we have to
* close and retry.
*/
if (fstat(lockfd, &st) < 0) {
syslog(LOG_ERR, "fstat() failed");
fprintf(stderr, "%s: %s\n", strerror(errno), "fstat() failed");
exit(1);
}
if (st.st_nlink != 0)
break;
close(lockfd);
lockfd = -1;
}
return (lockfd);
}
int pw_tmp()
{
static char path[MAXPATHLEN] = _PATH_MASTERPASSWD;
int fd;
char *p;
if ((p = strrchr(path, '/')))
++p;
else
p = path;
strcpy(p, "pw.XXXXXX");
if ((fd = mkstemp(path)) == -1) {
syslog(LOG_ERR, "%s", path);
fprintf(stderr, "%s: %s\n", strerror(errno), path);
exit(1);
}
tempname = path;
return (fd);
}
int pw_mkdb(char *username)
{
int pstat;
pid_t pid;
(void)fflush(stderr);
if (!(pid = fork())) {
if(!username) {
syslog(LOG_WARNING, "rebuilding the database...");
execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
} else {
syslog(LOG_WARNING, "updating the database for %s...", username);
#if defined(__FreeBSD__) || defined(__OpenBSD__)
execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-u", username, tempname, NULL);
#elif defined(__NetBSD__)
execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
#else
#error "Not FreeBSD, OpenBSD or NetBSD - don't know what to do"
#endif
}
pw_error((char *)_PATH_PWD_MKDB, 1, 1);
}
pid = waitpid(pid, &pstat, 0);
if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
return (0);
syslog(LOG_WARNING, "done");
return (1);
}
void pw_error(char *name, int errn, int eval)
{
#ifdef YP
extern int _use_yp;
#endif /* YP */
if (errn)
syslog(LOG_WARNING, name);
#ifdef YP
if (_use_yp)
syslog(LOG_WARNING, "NIS information unchanged");
else
#endif /* YP */
syslog(LOG_WARNING, "%s: unchanged", _PATH_MASTERPASSWD);
(void)unlink(tempname);
exit(eval);
}
void pw_copy(int ffd, int tfd, struct passwd *pw)
{
FILE *from, *to;
int done;
char *p, buf[8192];
char uidstr[20];
char gidstr[20];
char chgstr[20];
char expstr[20];
snprintf(uidstr, sizeof(uidstr), "%d", pw->pw_uid);
snprintf(gidstr, sizeof(gidstr), "%d", pw->pw_gid);
snprintf(chgstr, sizeof(chgstr), "%ld", (long)pw->pw_change);
snprintf(expstr, sizeof(expstr), "%ld", (long)pw->pw_expire);
if (!(from = fdopen(ffd, "r")))
pw_error((char *)_PATH_MASTERPASSWD, 1, 1);
if (!(to = fdopen(tfd, "w")))
pw_error(tempname, 1, 1);
for (done = 0; fgets(buf, sizeof(buf), from);) {
if (!strchr(buf, '\n')) {
syslog(LOG_WARNING, "%s: line too long", _PATH_MASTERPASSWD);
pw_error(NULL, 0, 1);
}
if (done) {
(void)fprintf(to, "%s", buf);
if (ferror(to))
goto err;
continue;
}
for (p = buf; *p != '\n'; p++)
if (*p != ' ' && *p != '\t')
break;
if (*p == '#' || *p == '\n') {
(void)fprintf(to, "%s", buf);
if (ferror(to))
goto err;
continue;
}
if (!(p = strchr(buf, ':'))) {
syslog(LOG_WARNING, "%s: corrupted entry", _PATH_MASTERPASSWD);
pw_error(NULL, 0, 1);
}
*p = '\0';
if (strcmp(buf, pw->pw_name)) {
*p = ':';
(void)fprintf(to, "%s", buf);
if (ferror(to))
goto err;
continue;
}
#if defined(__FreeBSD__)
(void)fprintf(to, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
pw->pw_name, pw->pw_passwd,
pw->pw_fields & _PWF_UID ? uidstr : "",
pw->pw_fields & _PWF_GID ? gidstr : "",
pw->pw_class,
pw->pw_fields & _PWF_CHANGE ? chgstr : "",
pw->pw_fields & _PWF_EXPIRE ? expstr : "",
pw->pw_gecos, pw->pw_dir, pw->pw_shell);
#elif defined(__NetBSD__) || defined(__OpenBSD__)
(void)fprintf(to, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
pw->pw_name, pw->pw_passwd,
uidstr, gidstr,
pw->pw_class,
chgstr, expstr,
pw->pw_gecos, pw->pw_dir, pw->pw_shell);
#else
#error "Not FreeBSD, OpenBSD or NetBSD - don't know what to do"
#endif
done = 1;
if (ferror(to))
goto err;
}
if (!done) {
#ifdef YP
/* Ultra paranoid: shouldn't happen. */
if (getuid()) {
syslog(LOG_WARNING, "%s: not found in %s -- permission denied",
pw->pw_name, _PATH_MASTERPASSWD);
pw_error(NULL, 0, 1);
} else
#endif /* YP */
#if defined(__FreeBSD__)
(void)fprintf(to, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
pw->pw_name, pw->pw_passwd,
pw->pw_fields & _PWF_UID ? uidstr : "",
pw->pw_fields & _PWF_GID ? gidstr : "",
pw->pw_class,
pw->pw_fields & _PWF_CHANGE ? chgstr : "",
pw->pw_fields & _PWF_EXPIRE ? expstr : "",
pw->pw_gecos, pw->pw_dir, pw->pw_shell);
#elif defined(__NetBSD__) || defined(__OpenBSD__)
(void)fprintf(to, "%s:%s:%s:%s:%s:%s:%s:%s:%s:%s\n",
pw->pw_name, pw->pw_passwd,
uidstr, gidstr,
pw->pw_class,
chgstr, expstr,
pw->pw_gecos, pw->pw_dir, pw->pw_shell);
#else
#error "Not FreeBSD, OpenBSD or NetBSD - don't know what to do"
#endif
}
if (ferror(to))
err: pw_error(NULL, 1, 1);
(void)fclose(to);
}
#endif

52
unix/pw_util.h Normal file
View File

@@ -0,0 +1,52 @@
/* $Id: pw_util.h,v 1.3 2004/12/28 15:30:53 mbse Exp $
*
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)pw_util.h 8.2 (Berkeley) 4/1/94
*/
#ifndef _PW_UTIL_H
#define _PW_UTIL_H
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
void pw_error __P((char *, int, int));
void pw_init __P((void));
int pw_lock __P((void));
int pw_mkdb __P((char *));
int pw_tmp __P((void));
void pw_copy __P((int, int, struct passwd *));
#endif
#endif

135
unix/pwauth.c Normal file
View File

@@ -0,0 +1,135 @@
/*****************************************************************************
*
* $Id: pwauth.c,v 1.4 2003/08/15 20:05:36 mbroek Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2002
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include "mblogin.h"
#include "pwauth.h"
#include "getdef.h"
#include "encrypt.h"
/* standard password prompt by default */
static const char *PROMPT = gettext_noop("Password: ");
int wipe_clear_pass = 1;
char *clear_pass = NULL;
/*
* pw_auth gets the user's cleartext password and encrypts it
* using the salt in the encrypted password. The results are
* compared.
*/
int pw_auth(const char *cipher, const char *user, int reason, const char *input)
{
char prompt[1024];
char *clear = NULL;
const char *cp;
int retval;
/*
* There are programs for adding and deleting authentication data.
*/
if (reason == PW_ADD || reason == PW_DELETE)
return 0;
/*
* There are even programs for changing the user name ...
*/
if (reason == PW_CHANGE && input != (char *) 0)
return 0;
/*
* WARNING:
*
* When we change a password and we are root, we don't prompt.
* This is so root can change any password without having to
* know it. This is a policy decision that might have to be
* revisited.
*/
if (reason == PW_CHANGE && getuid () == 0)
return 0;
/*
* WARNING:
*
* When we are logging in a user with no ciphertext password,
* we don't prompt for the password or anything. In reality
* the user could just hit <ENTER>, so it doesn't really
* matter.
*/
if (cipher == (char *) 0 || *cipher == '\0')
return 0;
/*
* Prompt for the password as required. FTPD and REXECD both
* get the cleartext password for us.
*/
if (reason != PW_FTP && reason != PW_REXEC && !input) {
cp = PROMPT;
snprintf(prompt, sizeof prompt, cp, user);
clear = getpass(prompt);
if (!clear) {
static char c[1];
c[0] = '\0';
clear = c;
}
input = clear;
}
/*
* Convert the cleartext password into a ciphertext string.
* If the two match, the return value will be zero, which is
* SUCCESS. Otherwise we see if SKEY is being used and check
* the results there as well.
*/
retval = strcmp(pw_encrypt(input, cipher), cipher);
/*
* Things like RADIUS authentication may need the password -
* if the external variable wipe_clear_pass is zero, we will
* not wipe it (the caller should wipe clear_pass when it is
* no longer needed). --marekm
*/
clear_pass = clear;
if (wipe_clear_pass && clear && *clear)
strzero(clear);
return retval;
}

31
unix/pwauth.h Normal file
View File

@@ -0,0 +1,31 @@
/* $Id: pwauth.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _PWAUTH_H
#define _PWAUTH_H
int pw_auth(const char *program,const char *user,int flag,const char *input);
/*
* Local access
*/
#define PW_SU 1
#define PW_LOGIN 2
/*
* Administrative functions
*/
#define PW_ADD 101
#define PW_CHANGE 102
#define PW_DELETE 103
/*
* Network access
*/
#define PW_TELNET 201
#define PW_RLOGIN 202
#define PW_FTP 203
#define PW_REXEC 204
#endif

98
unix/pwdcheck.c Normal file
View File

@@ -0,0 +1,98 @@
/*****************************************************************************
*
* $Id: pwdcheck.c,v 1.2 2003/08/15 20:05:36 mbroek Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyrioght ...: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <stdio.h>
#include "mblogin.h"
#include <pwd.h>
#include <syslog.h>
#include "pwauth.h"
#include "pwdcheck.h"
#ifdef HAVE_SHADOW_H
#include <shadow.h>
#endif
#ifdef USE_PAM
// #include "pam_defs.h"
#endif
#define WRONGPWD2 "incorrect password for `%s'"
void passwd_check(const char *user, const char *passwd, const char *progname)
{
#ifdef USE_PAM
pam_handle_t *pamh = NULL;
int retcode;
struct pam_conv conv = { misc_conv, NULL };
if (pam_start(progname, user, &conv, &pamh)) {
bailout:
SYSLOG((LOG_WARN, WRONGPWD2, user));
sleep(1);
fprintf(stderr, "Incorrect password for %s.\n", user);
exit(1);
}
if (pam_authenticate(pamh, 0))
goto bailout;
retcode = pam_acct_mgmt(pamh, 0);
if (retcode == PAM_NEW_AUTHTOK_REQD) {
retcode = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
} else if (retcode)
goto bailout;
if (pam_setcred(pamh, 0))
goto bailout;
/* no need to establish a session; this isn't a session-oriented
* activity... */
#else /* !USE_PAM */
#ifdef SHADOW_PASSWORD
struct spwd *sp;
if ((sp = getspnam(user)))
passwd = sp->sp_pwdp;
endspent();
#endif
if (pw_auth(passwd, user, PW_LOGIN, (char *) 0) != 0) {
syslog(LOG_WARNING, WRONGPWD2, user);
sleep(1);
fprintf(stderr, "Incorrect password for %s.\n", user);
exit(1);
}
#endif /* !USE_PAM */
}

8
unix/pwdcheck.h Normal file
View File

@@ -0,0 +1,8 @@
/* $Id: pwdcheck.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _PWDCHECK_H
#define _PWDCHECK_H
void passwd_check(const char *, const char *, const char *);
#endif

249
unix/pwio.c Normal file
View File

@@ -0,0 +1,249 @@
/*****************************************************************************
*
* $Id: pwio.c,v 1.5 2004/12/28 15:30:53 mbse Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2002
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "sgetpwent.h"
#include "commonio.h"
#ifndef HAVE_PUTPWENT
#include "putpwent.h"
#endif
#include "pwio.h"
struct passwd *__pw_dup(const struct passwd *pwent)
{
struct passwd *pw;
if (!(pw = (struct passwd *) malloc(sizeof *pw)))
return NULL;
*pw = *pwent;
if (!(pw->pw_name = strdup(pwent->pw_name)))
return NULL;
if (!(pw->pw_passwd = strdup(pwent->pw_passwd)))
return NULL;
#ifdef ATT_AGE
if (!(pw->pw_age = strdup(pwent->pw_age)))
return NULL;
#endif
#ifdef ATT_COMMENT
if (!(pw->pw_comment = strdup(pwent->pw_comment)))
return NULL;
#endif
if (!(pw->pw_gecos = strdup(pwent->pw_gecos)))
return NULL;
if (!(pw->pw_dir = strdup(pwent->pw_dir)))
return NULL;
if (!(pw->pw_shell = strdup(pwent->pw_shell)))
return NULL;
return pw;
}
static void *passwd_dup(const void *ent)
{
const struct passwd *pw = ent;
return __pw_dup(pw);
}
static void passwd_free(void *ent)
{
struct passwd *pw = ent;
free(pw->pw_name);
free(pw->pw_passwd);
#ifdef ATT_AGE
free(pw->pw_age);
#endif
#ifdef ATT_COMMENT
free(pw->pw_comment);
#endif
free(pw->pw_gecos);
free(pw->pw_dir);
free(pw->pw_shell);
free(pw);
}
static const char *passwd_getname(const void *ent)
{
const struct passwd *pw = ent;
return pw->pw_name;
}
static void *passwd_parse(const char *line)
{
return (void *) sgetpwent(line);
}
static int passwd_put(const void *ent, FILE *file)
{
const struct passwd *pw = ent;
return (putpwent(pw, file) == -1) ? -1 : 0;
}
static struct commonio_ops passwd_ops = {
passwd_dup,
passwd_free,
passwd_getname,
passwd_parse,
passwd_put,
fgets,
fputs
};
static struct commonio_db passwd_db = {
PASSWD_FILE, /* filename */
&passwd_ops, /* ops */
NULL, /* fp */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
0, /* changed */
0, /* isopen */
0, /* locked */
0, /* readonly */
1 /* use_lckpwdf */
};
int pw_name(const char *filename)
{
return commonio_setname(&passwd_db, filename);
}
#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
int pw_lock(void)
{
return commonio_lock(&passwd_db);
}
#endif
int pw_open(int mode)
{
return commonio_open(&passwd_db, mode);
}
const struct passwd *pw_locate(const char *name)
{
return commonio_locate(&passwd_db, name);
}
int pw_update(const struct passwd *pw)
{
return commonio_update(&passwd_db, (const void *) pw);
}
int pw_remove(const char *name)
{
return commonio_remove(&passwd_db, name);
}
int pw_rewind(void)
{
return commonio_rewind(&passwd_db);
}
const struct passwd *pw_next(void)
{
return commonio_next(&passwd_db);
}
int pw_close(void)
{
return commonio_close(&passwd_db);
}
int pw_unlock(void)
{
return commonio_unlock(&passwd_db);
}
struct commonio_entry *__pw_get_head(void)
{
return passwd_db.head;
}
void __pw_del_entry(const struct commonio_entry *ent)
{
commonio_del_entry(&passwd_db, ent);
}
#endif

33
unix/pwio.h Normal file
View File

@@ -0,0 +1,33 @@
/* $Id: pwio.h,v 1.3 2004/12/28 15:30:53 mbse Exp $ */
#ifndef _PWIO_H
#define _PWIO_H
#if !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
#ifndef PASSWD_FILE
#define PASSWD_FILE "/etc/passwd"
#endif
#ifndef GROUP_FILE
#define GROUP_FILE "/etc/group"
#endif
struct passwd *__pw_dup (const struct passwd *);
void __pw_set_changed (void);
int pw_close (void);
const struct passwd *pw_locate (const char *);
int pw_lock (void);
int pw_lock_first (void);
int pw_name (const char *);
const struct passwd *pw_next (void);
int pw_open (int);
int pw_remove (const char *);
int pw_rewind (void);
int pw_unlock (void);
int pw_update (const struct passwd *);
#endif
#endif

157
unix/rad64.c Normal file
View File

@@ -0,0 +1,157 @@
/*****************************************************************************
*
* File ..................: mbuseradd/rad64c.c
* Purpose ...............: MBSE BBS Shadow Password Suite
* Last modification date : 25-Sep-2000
* Original Source .......: Shadow Password Suite
* Original Copyrioght ...: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2000
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/*
* Copyright 1989 - 1992, Julianne Frances Haugh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "../config.h"
#include "rad64.h"
#ifndef HAVE_C64I
/*
* c64i - convert a radix 64 character to an integer
*/
int c64i(char c)
{
if (c == '.')
return (0);
if (c == '/')
return (1);
if (c >= '0' && c <= '9')
return (c - '0' + 2);
if (c >= 'A' && c <= 'Z')
return (c - 'A' + 12);
if (c >= 'a' && c <= 'z')
return (c - 'a' + 38);
else
return (-1);
}
/*
* i64c - convert an integer to a radix 64 character
*/
int i64c(int i)
{
if (i <= 0)
return ('.');
if (i == 1)
return ('/');
if (i >= 2 && i < 12)
return ('0' - 2 + i);
if (i >= 12 && i < 38)
return ('A' - 12 + i);
if (i >= 38 && i < 63)
return ('a' - 38 + i);
return ('z');
}
#endif
#ifndef HAVE_A64L
/*
* l64a - convert a long to a string of radix 64 characters
*/
char *l64a(long l)
{
static char buf[8];
int i = 0;
if (l < 0L)
return ((char *) 0);
do {
buf[i++] = i64c ((int) (l % 64));
buf[i] = '\0';
} while (l /= 64L, l > 0 && i < 6);
return (buf);
}
/*
* a64l - convert a radix 64 string to a long integer
*/
long a64l(const char *s)
{
int i;
long value;
long shift = 0;
for (i = 0, value = 0L;i < 6 && *s;s++) {
value += (c64i (*s) << shift);
shift += 6;
}
return (value);
}
#endif /* !HAVE_A64L */

15
unix/rad64.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef _RAD64_H
#define _RAD64_H
#ifndef HAVE_C64I
int c64i(char);
int i64c(int);
#endif
#ifndef HAVE_A64L
char *l64a(long);
long a64l(const char *);
#endif
#endif

101
unix/salt.c Normal file
View File

@@ -0,0 +1,101 @@
/*****************************************************************************
*
* $Id: salt.c,v 1.2 2003/08/15 20:05:36 mbroek Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyrioght ...: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/*
* salt.c - generate a random salt string for crypt()
*
* Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
* public domain.
*/
#include "../config.h"
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#ifdef TIME_WITH_SYS_TIME
#include <time.h>
#endif
#include <sys/time.h>
#include "rad64.h"
#if 1
#include "getdef.h"
/*
* Generate 8 base64 ASCII characters of random salt. If MD5_CRYPT_ENAB
* in /etc/login.defs is "yes", the salt string will be prefixed by "$1$"
* (magic) and pw_encrypt() will execute the MD5-based FreeBSD-compatible
* version of crypt() instead of the standard one.
*/
char *crypt_make_salt(void)
{
struct timeval tv;
static char result[40];
result[0] = '\0';
if (getdef_bool("MD5_CRYPT_ENAB")) {
strcpy(result, "$1$"); /* magic for the new MD5 crypt() */
}
/*
* Generate 8 chars of salt, the old crypt() will use only first 2.
*/
gettimeofday(&tv, (struct timezone *) 0);
strcat(result, l64a(tv.tv_usec));
strcat(result, l64a(tv.tv_sec + getpid() + clock()));
if (strlen(result) > 3 + 8) /* magic+salt */
result[11] = '\0';
return result;
}
#else
/*
* This is the old style random salt generator...
*/
char *crypt_make_salt(void)
{
time_t now;
static unsigned long x;
static char result[3];
now = time(NULL);
x += now + getpid() + clock();
result[0] = i64c(((x >> 18) ^ (x >> 6)) & 077);
result[1] = i64c(((x >> 12) ^ x) & 077);
result[2] = '\0';
return result;
}
#endif

9
unix/salt.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef _SALT_H
#define _SALT_H
char *crypt_make_salt(void);
#endif

120
unix/setugid.c Normal file
View File

@@ -0,0 +1,120 @@
/*****************************************************************************
*
* $Id: setugid.c,v 1.3 2003/08/15 20:05:36 mbroek Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/*
* Separated from setup.c. --marekm
*/
#include "../config.h"
#include <stdio.h>
#include <syslog.h>
#include "mblogin.h"
#include <pwd.h>
#include <grp.h>
#include "getdef.h"
#include "setugid.h"
/*
* setup_uid_gid() split in two functions for PAM support -
* pam_setcred() needs to be called after initgroups(), but
* before setuid().
*/
int setup_groups(const struct passwd *info)
{
/*
* Set the real group ID to the primary group ID in the password
* file.
*/
if (setgid (info->pw_gid) == -1) {
perror("setgid");
syslog(LOG_ERR, "bad group ID `%d' for user `%s': %m\n", info->pw_gid, info->pw_name);
closelog();
return -1;
}
#ifdef HAVE_INITGROUPS
/*
* For systems which support multiple concurrent groups, go get
* the group set from the /etc/group file.
*/
if (initgroups(info->pw_name, info->pw_gid) == -1) {
perror("initgroups");
syslog(LOG_ERR, "initgroups failed for user `%s': %m\n", info->pw_name);
closelog();
return -1;
}
#endif
return 0;
}
int change_uid(const struct passwd *info)
{
/*
* Set the real UID to the UID value in the password file.
*/
#ifndef BSD
if (setuid(info->pw_uid))
#else
if (setreuid(info->pw_uid, info->pw_uid))
#endif
{
perror("setuid");
syslog(LOG_ERR, "bad user ID `%d' for user `%s': %m\n", (int) info->pw_uid, info->pw_name);
closelog();
return -1;
}
return 0;
}
/*
* setup_uid_gid() performs the following steps -
*
* set the group ID to the value from the password file entry
* set the supplementary group IDs
*
* Returns 0 on success, or -1 on failure.
*/
int setup_uid_gid(const struct passwd *info, int is_console)
{
if (setup_groups(info) < 0)
return -1;
if (change_uid(info) < 0)
return -1;
return 0;
}

10
unix/setugid.h Normal file
View File

@@ -0,0 +1,10 @@
/* $Id: setugid.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _SETUGID_H
#define _SETUGID_H
int setup_groups(const struct passwd *);
int change_uid(const struct passwd *);
int setup_uid_gid(const struct passwd *, int);
#endif

111
unix/setupenv.c Normal file
View File

@@ -0,0 +1,111 @@
/*****************************************************************************
*
* $Id: setupenv.c,v 1.2 2003/08/15 20:05:36 mbroek Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/*
* Separated from setup.c. --marekm
*/
#include "../config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <ctype.h>
#include <syslog.h>
#include "mblogin.h"
#include <pwd.h>
#include "getdef.h"
#include "xmalloc.h"
#include "env.h"
#include "setupenv.h"
/*
* change to the user's home directory
* set the HOME, SHELL, MAIL, PATH, and LOGNAME or USER environmental
* variables.
*/
void setup_env(struct passwd *info)
{
char *cp;
/*
* Change the current working directory to be the home directory
* of the user. It is a fatal error for this process to be unable
* to change to that directory. There is no "default" home
* directory.
*
* We no longer do it as root - should work better on NFS-mounted
* home directories.
*/
if (chdir(info->pw_dir) == -1) {
static char temp_pw_dir[] = "/";
if (!getdef_bool("DEFAULT_HOME") || chdir("/") == -1) {
fprintf(stderr, _("Unable to cd to \"%s\"\n"), info->pw_dir);
syslog(LOG_WARNING, "unable to cd to `%s' for user `%s'\n", info->pw_dir, info->pw_name);
closelog();
exit (1);
}
puts(_("No directory, logging in with HOME=/"));
info->pw_dir = temp_pw_dir;
}
/*
* Create the HOME environmental variable and export it.
*/
addenv("HOME", info->pw_dir);
/*
* Create the SHELL environmental variable and export it.
*/
if (info->pw_shell == (char *) 0 || ! *info->pw_shell) {
static char temp_pw_shell[] = "/bin/sh";
info->pw_shell = temp_pw_shell;
}
addenv("SHELL", info->pw_shell);
/*
* Create the PATH environmental variable and export it.
*/
cp = getdef_str("ENV_PATH");
addenv(cp ? cp : "PATH=/bin:/usr/bin", NULL);
/*
* Export the user name. For BSD derived systems, it's "USER", for
* all others it's "LOGNAME". We set both of them.
*/
addenv("USER", info->pw_name);
addenv("LOGNAME", info->pw_name);
}

8
unix/setupenv.h Normal file
View File

@@ -0,0 +1,8 @@
/* $Id: setupenv.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _SETUPENV_H
#define _SETUPENV_H
void setup_env(struct passwd *);
#endif

167
unix/sgetpwent.c Normal file
View File

@@ -0,0 +1,167 @@
/*****************************************************************************
*
* File ..................: mbuseradd/sgetpwent.c
* Purpose ...............: MBSE BBS Shadow Password Suite
* Last modification date : 07-Feb-2001
* Original Source .......: Shadow Password Suite
* Original Copyrioght ...: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/*
* Copyright 1989 - 1994, Julianne Frances Haugh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Julianne F. Haugh nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "../config.h"
#include <stdlib.h>
#include <pwd.h>
#include <string.h>
#include "sgetpwent.h"
#define NFIELDS 7
/*
* sgetpwent - convert a string to a (struct passwd)
*
* sgetpwent() parses a string into the parts required for a password
* structure. Strict checking is made for the UID and GID fields and
* presence of the correct number of colons. Any failing tests result
* in a NULL pointer being returned.
*
* NOTE: This function uses hard-coded string scanning functions for
* performance reasons. I am going to come up with some conditional
* compilation glarp to improve on this in the future.
*/
struct passwd * sgetpwent(const char *buf)
{
static struct passwd pwent;
static char pwdbuf[1024];
register int i;
register char *cp;
char *ep;
char *fields[NFIELDS];
/*
* Copy the string to a static buffer so the pointers into
* the password structure remain valid.
*/
if (strlen(buf) >= sizeof pwdbuf)
return 0;
strcpy(pwdbuf, buf);
/*
* Save a pointer to the start of each colon separated
* field. The fields are converted into NUL terminated strings.
*/
for (cp = pwdbuf, i = 0;i < NFIELDS && cp;i++) {
fields[i] = cp;
while (*cp && *cp != ':')
++cp;
if (*cp)
*cp++ = '\0';
else
cp = 0;
}
/*
* There must be exactly NFIELDS colon separated fields or
* the entry is invalid. Also, the UID and GID must be non-blank.
*/
if (i != NFIELDS || *fields[2] == '\0' || *fields[3] == '\0')
return 0;
/*
* Each of the fields is converted the appropriate data type
* and the result assigned to the password structure. If the
* UID or GID does not convert to an integer value, a NULL
* pointer is returned.
*/
pwent.pw_name = fields[0];
pwent.pw_passwd = fields[1];
if (fields[2][0] == '\0' ||
((pwent.pw_uid = strtol (fields[2], &ep, 10)) == 0 && *ep)) {
return 0;
}
if (fields[3][0] == '\0' ||
((pwent.pw_gid = strtol (fields[3], &ep, 10)) == 0 && *ep)) {
return 0;
}
#ifdef ATT_AGE
cp = pwent.pw_passwd;
while (*cp && *cp != ',')
++cp;
if (*cp) {
*cp++ = '\0';
pwent.pw_age = cp;
} else {
cp = 0;
pwent.pw_age = "";
}
#endif
pwent.pw_gecos = fields[4];
#ifdef ATT_COMMENT
pwent.pw_comment = "";
#endif
pwent.pw_dir = fields[5];
pwent.pw_shell = fields[6];
return &pwent;
}

7
unix/sgetpwent.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef _SGETPWENT_H
#define _SGETPWENT_H
struct passwd * sgetpwent(const char *);
#endif

226
unix/shadowio.c Normal file
View File

@@ -0,0 +1,226 @@
/*****************************************************************************
*
* File ..................: mbuseradd/shadowio.c
* Purpose ...............: MBSE BBS Shadow Password Suite
* Last modification date : 09-Aug-2001
* Original Source .......: Shadow Password Suite
* Original Copyrioght ...: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#ifdef SHADOW_PASSWORD
#include <string.h>
#include <stdlib.h>
#include <shadow.h>
#include <stdio.h>
#include "commonio.h"
#include "shadowio.h"
struct spwd *__spw_dup(const struct spwd *spent)
{
struct spwd *sp;
if (!(sp = (struct spwd *) malloc(sizeof *sp)))
return NULL;
*sp = *spent;
if (!(sp->sp_namp = strdup(spent->sp_namp)))
return NULL;
if (!(sp->sp_pwdp = strdup(spent->sp_pwdp)))
return NULL;
return sp;
}
static void * shadow_dup(const void *ent)
{
const struct spwd *sp = ent;
return __spw_dup(sp);
}
static void shadow_free(void *ent)
{
struct spwd *sp = ent;
free(sp->sp_namp);
free(sp->sp_pwdp);
free(sp);
}
static const char * shadow_getname(const void *ent)
{
const struct spwd *sp = ent;
return sp->sp_namp;
}
static void * shadow_parse(const char *line)
{
return (void *) sgetspent(line);
}
static int shadow_put(const void *ent, FILE *file)
{
const struct spwd *sp = ent;
return (putspent(sp, file) == -1) ? -1 : 0;
}
static struct commonio_ops shadow_ops = {
shadow_dup,
shadow_free,
shadow_getname,
shadow_parse,
shadow_put,
fgets,
fputs
};
static struct commonio_db shadow_db = {
SHADOW_FILE, /* filename */
&shadow_ops, /* ops */
NULL, /* fp */
NULL, /* head */
NULL, /* tail */
NULL, /* cursor */
0, /* changed */
0, /* isopen */
0, /* locked */
0, /* readonly */
1 /* use_lckpwdf */
};
int spw_name(const char *filename)
{
return commonio_setname(&shadow_db, filename);
}
int spw_file_present(void)
{
return commonio_present(&shadow_db);
}
int spw_lock(void)
{
return commonio_lock(&shadow_db);
}
int spw_open(int mode)
{
return commonio_open(&shadow_db, mode);
}
const struct spwd * spw_locate(const char *name)
{
return commonio_locate(&shadow_db, name);
}
int spw_update(const struct spwd *sp)
{
return commonio_update(&shadow_db, (const void *) sp);
}
int spw_remove(const char *name)
{
return commonio_remove(&shadow_db, name);
}
int spw_rewind(void)
{
return commonio_rewind(&shadow_db);
}
const struct spwd * spw_next(void)
{
return commonio_next(&shadow_db);
}
int spw_close(void)
{
return commonio_close(&shadow_db);
}
int spw_unlock(void)
{
return commonio_unlock(&shadow_db);
}
struct commonio_entry * __spw_get_head(void)
{
return shadow_db.head;
}
void __spw_del_entry(const struct commonio_entry *ent)
{
commonio_del_entry(&shadow_db, ent);
}
#endif

33
unix/shadowio.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef _SHADOWIO_H
#define _SHADOWIO_H
#ifdef SHADOW_PASSWORD
#ifndef SHADOW_FILE
#define SHADOW_FILE "/etc/shadow"
#endif
#ifdef SHADOWGRP
#ifndef SGROUP_FILE
#define SGROUP_FILE "/etc/gshadow"
#endif
#endif
#endif
struct spwd *__spw_dup (const struct spwd *);
void __spw_set_changed (void);
int spw_close (void);
int spw_file_present (void);
const struct spwd *spw_locate (const char *);
int spw_lock (void);
int spw_name (const char *);
const struct spwd *spw_next (void);
int spw_open (int);
int spw_remove (const char *);
int spw_rewind (void);
int spw_unlock (void);
int spw_update (const struct spwd *);
#endif

128
unix/shell.c Normal file
View File

@@ -0,0 +1,128 @@
/*****************************************************************************
*
* $Id: shell.c,v 1.2 2003/08/15 20:05:36 mbroek Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <stdio.h>
#include <errno.h>
#include "mblogin.h"
#include "basename.h"
#include "shell.h"
extern char **newenvp;
extern size_t newenvc;
/*
* shell - execute the named program
*
* shell begins by trying to figure out what argv[0] is going to
* be for the named process. The user may pass in that argument,
* or it will be the last pathname component of the file with a
* '-' prepended. The first attempt is to just execute the named
* file. If the errno comes back "ENOEXEC", the file is assumed
* at first glance to be a shell script. The first two characters
* must be "#!", in which case "/bin/sh" is executed to process
* the file. If all that fails, give up in disgust ...
*/
void shell(const char *file, const char *arg)
{
char arg0[1024];
int err;
if (file == (char *) 0)
exit (1);
/*
* The argv[0]'th entry is usually the path name, but
* for various reasons the invoker may want to override
* that. So, we determine the 0'th entry only if they
* don't want to tell us what it is themselves.
*/
if (arg == (char *) 0) {
snprintf(arg0, sizeof arg0, "-%s", Basename((char *) file));
arg = arg0;
}
#ifdef DEBUG
printf (_("Executing shell %s\n"), file);
#endif
/*
* First we try the direct approach. The system should be
* able to figure out what we are up to without too much
* grief.
*/
execle (file, arg, (char *) 0, newenvp);
err = errno;
/* Linux handles #! in the kernel, and bash doesn't make
sense of "#!" so it wouldn't work anyway... --marekm */
#ifndef __linux__
/*
* It is perfectly OK to have a shell script for a login
* shell, and this code attempts to support that. It
* relies on the standard shell being able to make sense
* of the "#!" magic number.
*/
if (err == ENOEXEC) {
FILE *fp;
if ((fp = fopen (file, "r"))) {
if (getc (fp) == '#' && getc (fp) == '!') {
fclose (fp);
execle ("/bin/sh", "sh",
file, (char *) 0, newenvp);
err = errno;
} else {
fclose (fp);
}
}
}
#endif
/*
* Obviously something is really wrong - I can't figure out
* how to execute this stupid shell, so I might as well give
* up in disgust ...
*/
snprintf(arg0, sizeof arg0, "Cannot execute %s", file);
errno = err;
perror(arg0);
exit(1);
}

8
unix/shell.h Normal file
View File

@@ -0,0 +1,8 @@
/* $Id: shell.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _SHELL_H
#define _SHELL_H
void shell(const char *, const char *);
#endif

80
unix/sub.c Normal file
View File

@@ -0,0 +1,80 @@
/*****************************************************************************
*
* $Id: sub.c,v 1.2 2003/08/15 20:05:36 mbroek Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2001
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include <stdio.h>
#include <sys/types.h>
#include <syslog.h>
#include "mblogin.h"
#include <pwd.h>
#include "sub.h"
#define BAD_SUBROOT2 "invalid root `%s' for user `%s'\n"
#define NO_SUBROOT2 "no subsystem root `%s' for user `%s'\n"
/*
* subsystem - change to subsystem root
*
* A subsystem login is indicated by the presense of a "*" as
* the first character of the login shell. The given home
* directory will be used as the root of a new filesystem which
* the user is actually logged into.
*/
void subsystem(const struct passwd *pw)
{
/*
* The new root directory must begin with a "/" character.
*/
if (pw->pw_dir[0] != '/') {
printf("Invalid root directory \"%s\"\n", pw->pw_dir);
syslog(LOG_WARNING, BAD_SUBROOT2, pw->pw_dir, pw->pw_name);
closelog();
exit (1);
}
/*
* The directory must be accessible and the current process
* must be able to change into it.
*/
if (chdir (pw->pw_dir) || chroot (pw->pw_dir)) {
printf("Can't change root directory to \"%s\"\n", pw->pw_dir);
syslog(LOG_WARNING, NO_SUBROOT2, pw->pw_dir, pw->pw_name);
closelog();
exit (1);
}
}

8
unix/sub.h Normal file
View File

@@ -0,0 +1,8 @@
/* $Id: sub.h,v 1.1 2002/01/05 13:57:10 mbroek Exp $ */
#ifndef _SUB_H
#define _SUB_H
void subsystem(const struct passwd *);
#endif

503
unix/utmp.c Normal file
View File

@@ -0,0 +1,503 @@
/*****************************************************************************
*
* $Id: utmp.c,v 1.7 2004/12/28 15:30:53 mbse Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyright ....: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2002
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include "mblogin.h"
#include <utmp.h>
#if HAVE_UTMPX_H
#include <utmpx.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_LIBUTIL_H
#include <libutil.h>
#endif
#if HAVE_UTIL_H
#include <util.h>
#endif
#include <fcntl.h>
#include <stdio.h>
#include "utmp.h"
#if defined(__NetBSD__)
#undef LOGIN_PROCESS
#undef HAVE_UTMPX_H
#endif
#if HAVE_UTMPX_H
extern struct utmpx utxent;
#endif
extern struct utmp utent;
#define NO_UTENT \
"No utmp entry. You must exec \"login\" from the lowest level \"sh\""
#define NO_TTY \
"Unable to determine your tty name."
/*
* checkutmp - see if utmp file is correct for this process
*
* System V is very picky about the contents of the utmp file
* and requires that a slot for the current process exist.
* The utmp file is scanned for an entry with the same process
* ID. If no entry exists the process exits with a message.
*
* The "picky" flag is for network and other logins that may
* use special flags. It allows the pid checks to be overridden.
* This means that getty should never invoke login with any
* command line flags.
*/
#if defined(__linux__) /* XXX */
void checkutmp(int picky)
{
char *line;
struct utmp *ut;
pid_t pid = getpid();
setutent();
/* First, try to find a valid utmp entry for this process. */
while ((ut = getutent()))
if (ut->ut_pid == pid && ut->ut_line[0] && ut->ut_id[0] &&
(ut->ut_type==LOGIN_PROCESS || ut->ut_type==USER_PROCESS))
break;
/* If there is one, just use it, otherwise create a new one. */
if (ut) {
utent = *ut;
} else {
if (picky) {
puts(NO_UTENT);
exit(1);
}
line = ttyname(0);
if (!line) {
puts(NO_TTY);
exit(1);
}
if (strncmp(line, "/dev/", 5) == 0)
line += 5;
memset((void *) &utent, 0, sizeof utent);
utent.ut_type = LOGIN_PROCESS;
utent.ut_pid = pid;
strncpy(utent.ut_line, line, sizeof utent.ut_line);
/* XXX - assumes /dev/tty?? */
strncpy(utent.ut_id, utent.ut_line + 3, sizeof utent.ut_id);
strcpy(utent.ut_user, "LOGIN");
time(&utent.ut_time);
}
}
#elif defined(LOGIN_PROCESS)
void checkutmp(int picky)
{
char *line;
struct utmp *ut;
#if HAVE_UTMPX_H
struct utmpx *utx;
#endif
pid_t pid = getpid();
#if HAVE_UTMPX_H
setutxent();
#endif
setutent();
if (picky) {
#if HAVE_UTMPX_H
while ((utx = getutxent()))
if (utx->ut_pid == pid)
break;
if (utx)
utxent = *utx;
#endif
while ((ut = getutent()))
if (ut->ut_pid == pid)
break;
if (ut)
utent = *ut;
#if HAVE_UTMPX_H
endutxent();
#endif
endutent();
if (!ut) {
puts(NO_UTENT);
exit(1);
}
#ifndef UNIXPC
/*
* If there is no ut_line value in this record, fill
* it in by getting the TTY name and stuffing it in
* the structure. The UNIX/PC is broken in this regard
* and needs help ...
*/
if (utent.ut_line[0] == '\0')
#endif /* !UNIXPC */
{
if (!(line = ttyname(0))) {
puts(NO_TTY);
exit(1);
}
if (strncmp(line, "/dev/", 5) == 0)
line += 5;
strncpy(utent.ut_line, line, sizeof utent.ut_line);
#if HAVE_UTMPX_H
strncpy(utxent.ut_line, line, sizeof utxent.ut_line);
#endif
}
} else {
if (!(line = ttyname(0))) {
puts(NO_TTY);
exit(1);
}
if (strncmp(line, "/dev/", 5) == 0)
line += 5;
strncpy (utent.ut_line, line, sizeof utent.ut_line);
if ((ut = getutline(&utent)))
strncpy(utent.ut_id, ut->ut_id, sizeof ut->ut_id);
strcpy(utent.ut_user, "LOGIN");
utent.ut_pid = getpid();
utent.ut_type = LOGIN_PROCESS;
time(&utent.ut_time);
#if HAVE_UTMPX_H
strncpy(utxent.ut_line, line, sizeof utxent.ut_line);
if ((utx = getutxline(&utxent)))
strncpy(utxent.ut_id, utx->ut_id, sizeof utxent.ut_id);
strcpy(utxent.ut_user, "LOGIN");
utxent.ut_pid = utent.ut_pid;
utxent.ut_type = utent.ut_type;
gettimeofday((struct timeval *) &utxent.ut_tv, NULL);
utent.ut_time = utxent.ut_tv.tv_sec;
#endif
}
}
#else /* !USG */
/*
* Also used for FreeBSD
*/
void checkutmp(int picky)
{
char *line;
/*
* Hand-craft a new utmp entry.
*/
memzero(&utent, sizeof utent);
if (! (line = ttyname (0))) {
puts (NO_TTY);
exit (1);
}
if (strncmp (line, "/dev/", 5) == 0)
line += 5;
(void) strncpy (utent.ut_line, line, sizeof utent.ut_line);
(void) time (&utent.ut_time);
}
#endif /* !USG */
/*
* Some systems already have updwtmp() and possibly updwtmpx(). Others
* don't, so we re-implement these functions if necessary. --marekm
*/
#ifndef HAVE_UPDWTMP
void updwtmp(const char *filename, const struct utmp *ut)
{
int fd;
fd = open(filename, O_APPEND | O_WRONLY, 0);
if (fd >= 0) {
write(fd, (const char *) ut, sizeof(*ut));
close(fd);
}
}
#endif /* ! HAVE_UPDWTMP */
#ifdef HAVE_UTMPX_H
#ifndef HAVE_UPDWTMPX
static void updwtmpx(const char *filename, const struct utmpx *utx)
{
int fd;
fd = open(filename, O_APPEND | O_WRONLY, 0);
if (fd >= 0) {
write(fd, (const char *) utx, sizeof(*utx));
close(fd);
}
}
#endif /* ! HAVE_UPDWTMPX */
#endif /* ! HAVE_UTMPX_H */
/*
* setutmp - put a USER_PROCESS entry in the utmp file
*
* setutmp changes the type of the current utmp entry to
* USER_PROCESS. the wtmp file will be updated as well.
*/
#if defined(__linux__) /* XXX */
void setutmp(const char *name, const char *line, const char *host)
{
utent.ut_type = USER_PROCESS;
strncpy(utent.ut_user, name, sizeof utent.ut_user);
time(&utent.ut_time);
/* other fields already filled in by checkutmp above */
setutent();
pututline(&utent);
endutent();
updwtmp(_WTMP_FILE, &utent);
}
#elif HAVE_UTMPX_H
void setutmp(const char *name, const char *line, const char *host)
{
struct utmp *utmp, utline;
struct utmpx *utmpx, utxline;
pid_t pid = getpid ();
int found_utmpx = 0, found_utmp = 0;
printf("setutmp HAVE_UTMP_H\n");
/*
* The canonical device name doesn't include "/dev/"; skip it
* if it is already there.
*/
if (strncmp (line, "/dev/", 5) == 0)
line += 5;
/*
* Update utmpx. We create an empty entry in case there is
* no matching entry in the utmpx file.
*/
setutxent ();
setutent ();
while (utmpx = getutxent ()) {
if (utmpx->ut_pid == pid) {
found_utmpx = 1;
break;
}
}
while (utmp = getutent ()) {
if (utmp->ut_pid == pid) {
found_utmp = 1;
break;
}
}
/*
* If the entry matching `pid' cannot be found, create a new
* entry with the device name in it.
*/
if (! found_utmpx) {
memset ((void *) &utxline, 0, sizeof utxline);
strncpy (utxline.ut_line, line, sizeof utxline.ut_line);
utxline.ut_pid = getpid ();
} else {
utxline = *utmpx;
if (strncmp (utxline.ut_line, "/dev/", 5) == 0) {
memmove (utxline.ut_line, utxline.ut_line + 5,
sizeof utxline.ut_line - 5);
utxline.ut_line[sizeof utxline.ut_line - 5] = '\0';
}
}
if (! found_utmp) {
memset ((void *) &utline, 0, sizeof utline);
strncpy (utline.ut_line, utxline.ut_line,
sizeof utline.ut_line);
utline.ut_pid = utxline.ut_pid;
} else {
utline = *utmp;
if (strncmp (utline.ut_line, "/dev/", 5) == 0) {
memmove (utline.ut_line, utline.ut_line + 5,
sizeof utline.ut_line - 5);
utline.ut_line[sizeof utline.ut_line - 5] = '\0';
}
}
/*
* Fill in the fields in the utmpx entry and write it out. Do
* the utmp entry at the same time to make sure things don't
* get messed up.
*/
strncpy (utxline.ut_user, name, sizeof utxline.ut_user);
strncpy (utline.ut_user, name, sizeof utline.ut_user);
utline.ut_type = utxline.ut_type = USER_PROCESS;
gettimeofday(&utxline.ut_tv, NULL);
utline.ut_time = utxline.ut_tv.tv_sec;
strncpy(utxline.ut_host, host ? host : "", sizeof utxline.ut_host);
pututxline (&utxline);
pututline (&utline);
updwtmpx(_WTMP_FILE "x", &utxline);
updwtmp(_WTMP_FILE, &utline);
utxent = utxline;
utent = utline;
}
#elif __FreeBSD__ || __NetBSD__ || __OpenBSD__
/*
* FreeBSD/NetBSD/OpenBSD version, simple and mean.
*/
void setutmp(const char *name, const char *line, const char *host)
{
struct utmp utmp;
memset(&utmp, 0, sizeof(utmp));
strncpy(utmp.ut_line, line, (int) sizeof utmp.ut_line);
strncpy(utmp.ut_name, name, sizeof utent.ut_name);
strncpy(utmp.ut_host, host, sizeof utent.ut_host);
(void) time (&utmp.ut_time);
login(&utmp);
utent = utmp;
}
#else /* !SVR4 */
void setutmp(const char *name, const char *line)
{
struct utmp utmp;
int fd;
int found = 0;
if ((fd = open(_UTMP_FILE, O_RDWR)) < 0)
return;
#if !defined(SUN) && !defined(BSD) && !defined(SUN4) /* XXX */
while (!found && read(fd, (char *)&utmp, sizeof utmp) == sizeof utmp) {
if (! strncmp (line, utmp.ut_line, (int) sizeof utmp.ut_line))
found++;
}
#endif
if (! found) {
/*
* This is a brand-new entry. Clear it out and fill it in
* later.
*/
memzero(&utmp, sizeof utmp);
strncpy(utmp.ut_line, line, (int) sizeof utmp.ut_line);
}
/*
* Fill in the parts of the UTMP entry. BSD has just the name,
* while System V has the name, PID and a type.
*/
strncpy(utmp.ut_user, name, sizeof utent.ut_user);
#ifdef USER_PROCESS
utmp.ut_type = USER_PROCESS;
utmp.ut_pid = getpid ();
#endif
/*
* Put in the current time (common to everyone)
*/
(void) time (&utmp.ut_time);
#ifdef UT_HOST
/*
* Update the host name field for systems with networking support
*/
(void) strncpy (utmp.ut_host, utent.ut_host, (int) sizeof utmp.ut_host);
#endif
/*
* Locate the correct position in the UTMP file for this
* entry.
*/
#ifdef HAVE_TTYSLOT
(void) lseek (fd, (off_t) (sizeof utmp) * ttyslot (), SEEK_SET);
#else
if (found) /* Back up a splot */
lseek (fd, (off_t) - sizeof utmp, SEEK_CUR);
else /* Otherwise, go to the end of the file */
lseek (fd, (off_t) 0, SEEK_END);
#endif
/*
* Scribble out the new entry and close the file. We're done
* with UTMP, next we do WTMP (which is real easy, put it on
* the end of the file.
*/
(void) write (fd, (char *) &utmp, sizeof utmp);
(void) close (fd);
updwtmp(_WTMP_FILE, &utmp);
utent = utmp;
}
#endif /* SVR4 */

29
unix/utmp.h Normal file
View File

@@ -0,0 +1,29 @@
/* $Id: utmp.h,v 1.4 2004/12/28 15:30:53 mbse Exp $ */
#ifndef _UTMP_HH
#define _UTMP_HH
void checkutmp(int);
#ifndef HAVE_UPDWTMP
void updwtmp(const char *, const struct utmp *);
#endif /* ! HAVE_UPDWTMP */
#ifdef HAVE_UTMPX_H
#ifndef HAVE_UPDWTMPX
static void updwtmpx(const char *, const struct utmpx *);
#endif /* ! HAVE_UPDWTMPX */
#endif /* ! HAVE_UTMPX_H */
#if defined(__linux__) /* XXX */
void setutmp(const char *, const char *, const char *);
#elif HAVE_UTMPX_H
void setutmp(const char *, const char *, const char *);
#elif __FreeBSD__ || __NetBSD__ || __OpenBSD__
void setutmp(const char *, const char *, const char *);
#else /* !SVR4 */
void setutmp(const char *, const char *);
#endif
#endif

83
unix/xmalloc.c Normal file
View File

@@ -0,0 +1,83 @@
/*****************************************************************************
*
* $Id: xmalloc.c,v 1.3 2005/08/27 12:06:49 mbse Exp $
* Purpose ...............: MBSE BBS Shadow Password Suite
* Original Source .......: Shadow Password Suite
* Original Copyrioght ...: Julianne Frances Haugh and others.
*
*****************************************************************************
* Copyright (C) 1997-2005
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* MBSE BBS is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
/* Replacements for malloc and strdup with error checking. Too trivial
to be worth copyrighting :-). I did that because a lot of code used
malloc and strdup without checking for NULL pointer, and I like some
message better than a core dump... --marekm
Yeh, but. Remember that bailing out might leave the system in some
bizarre state. You really want to put in error checking, then add
some back-out failure recovery code. -- jfh */
#include "../config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xmalloc.h"
char *xmalloc(size_t size)
{
char *ptr;
ptr = malloc(size);
if (!ptr && size) {
fprintf(stderr, "malloc(%d) failed\n", (int) size);
exit(13);
}
return ptr;
}
char *xstrdup(const char *str)
{
return strcpy(xmalloc(strlen(str) + 1), str);
}
char *xstrcpy(char *src)
{
char *tmp;
if (src == NULL)
return(NULL);
tmp = xmalloc(strlen(src)+1);
strcpy(tmp, src);
return tmp;
}

11
unix/xmalloc.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef _XMALLOC_H
#define _XMALLOC_H
/* $Id: xmalloc.h,v 1.2 2005/08/27 12:06:49 mbse Exp $ */
char *xmalloc(size_t);
char *xstrdup(const char *);
char *xstrcpy(char *);
#endif