NetBSD/usr.sbin/rpc.pcnfsd/pcnfsd_misc.c

588 lines
12 KiB
C
Raw Normal View History

1998-07-27 19:11:06 +04:00
/* $NetBSD: pcnfsd_misc.c,v 1.5 1998/07/27 15:14:05 mycroft Exp $ */
1995-07-26 02:20:13 +04:00
1995-07-24 08:02:44 +04:00
/* RE_SID: @(%)/usr/dosnfs/shades_SCCS/unix/pcnfsd/v2/src/SCCS/s.pcnfsd_misc.c 1.5 92/01/24 19:59:13 SMI */
/*
**=====================================================================
** Copyright (c) 1986,1987,1988,1989,1990,1991 by Sun Microsystems, Inc.
** @(#)pcnfsd_misc.c 1.5 1/24/92
**=====================================================================
*/
/*
**=====================================================================
** I N C L U D E F I L E S E C T I O N *
** *
** If your port requires different include files, add a suitable *
** #define in the customization section, and make the inclusion or *
** exclusion of the files conditional on this. *
**=====================================================================
*/
#include <sys/file.h>
#include <sys/ioctl.h>
1997-10-25 17:45:55 +04:00
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
1995-07-24 08:02:44 +04:00
#include <errno.h>
1997-10-25 17:45:55 +04:00
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
1995-07-24 08:02:44 +04:00
#include <string.h>
1997-10-25 17:45:55 +04:00
#include <unistd.h>
1995-07-24 08:02:44 +04:00
#ifdef ISC_2_0
#include <sys/fcntl.h>
#endif
#ifdef SHADOW_SUPPORT
#include <shadow.h>
#endif
#ifdef WTMP
1997-10-25 17:45:55 +04:00
int wtmp_enabled = 1;
1995-07-24 08:02:44 +04:00
#endif
1997-10-25 17:45:55 +04:00
#include "common.h"
#include "pcnfsd.h"
#include "extern.h"
1995-07-24 08:02:44 +04:00
/*
**---------------------------------------------------------------------
1997-10-25 17:45:55 +04:00
** Other #define's
1995-07-24 08:02:44 +04:00
**---------------------------------------------------------------------
*/
#define zchar 0x5b
1997-10-25 17:45:55 +04:00
char tempstr[256];
char *mapfont __P((char, char, char));
void myhandler __P((int));
void start_watchdog __P((int));
void stop_watchdog __P((void));
1995-07-24 08:02:44 +04:00
/*
**=====================================================================
1997-10-25 17:45:55 +04:00
** C O D E S E C T I O N *
**=====================================================================
1995-07-24 08:02:44 +04:00
*/
/*
**---------------------------------------------------------------------
1997-10-25 17:45:55 +04:00
** Support procedures
1995-07-24 08:02:44 +04:00
**---------------------------------------------------------------------
*/
void
scramble(s1, s2)
1997-10-25 17:45:55 +04:00
char *s1;
char *s2;
1995-07-24 08:02:44 +04:00
{
1997-10-25 17:45:55 +04:00
while (*s1) {
*s2++ = (*s1 ^ zchar) & 0x7f;
s1++;
}
1995-07-24 08:02:44 +04:00
*s2 = 0;
}
1997-10-25 17:45:55 +04:00
struct passwd *
1995-07-24 08:02:44 +04:00
get_password(usrnam)
1997-10-25 17:45:55 +04:00
char *usrnam;
1995-07-24 08:02:44 +04:00
{
1997-10-25 17:45:55 +04:00
struct passwd *p;
static struct passwd localp;
1998-07-27 19:11:06 +04:00
__aconst char *pswd, *ushell;
1995-07-24 08:02:44 +04:00
#ifdef SHADOW_SUPPORT
1997-10-25 17:45:55 +04:00
struct spwd *sp;
int shadowfile;
1995-07-24 08:02:44 +04:00
#endif
#ifdef SHADOW_SUPPORT
1997-10-25 17:45:55 +04:00
/*
**--------------------------------------------------------------
** Check the existence of SHADOW. If it is there, then we are
** running a two-password-file system.
**--------------------------------------------------------------
*/
1995-07-24 08:02:44 +04:00
if (access(SHADOW, 0))
1997-10-25 17:45:55 +04:00
shadowfile = 0; /* SHADOW is not there */
1995-07-24 08:02:44 +04:00
else
1997-10-25 17:45:55 +04:00
shadowfile = 1;
1995-07-24 08:02:44 +04:00
setpwent();
if (shadowfile)
1997-10-25 17:45:55 +04:00
(void) setspent(); /* Setting the shadow password file */
if ((p = getpwnam(usrnam)) == (struct passwd *) NULL ||
(shadowfile && (sp = getspnam(usrnam)) == (struct spwd *) NULL))
return ((struct passwd *) NULL);
if (shadowfile) {
pswd = sp->sp_pwdp;
(void) endspent();
} else
pswd = p->pw_passwd;
1995-07-24 08:02:44 +04:00
#else
p = getpwnam(usrnam);
1997-10-25 17:45:55 +04:00
if (p == (struct passwd *) NULL)
return ((struct passwd *) NULL);
1995-07-24 08:02:44 +04:00
pswd = p->pw_passwd;
#endif
#ifdef ISC_2_0
1997-10-25 17:45:55 +04:00
/* *----------------------------------------------------------- * We
* may have an 'x' in which case look in /etc/shadow ..
* *----------------------------------------------------------- */
if (((strlen(pswd)) == 1) && pswd[0] == 'x') {
struct spwd *shadow = getspnam(usrnam);
if (!shadow)
return ((struct passwd *) NULL);
pswd = shadow->sp_pwdp;
}
1995-07-24 08:02:44 +04:00
#endif
localp = *p;
localp.pw_passwd = pswd;
#ifdef USE_GETUSERSHELL
setusershell();
1997-10-25 17:45:55 +04:00
while (ushell = getusershell()) {
if (!strcmp(ushell, localp.pw_shell)) {
1995-07-24 08:02:44 +04:00
ok = 1;
break;
}
}
endusershell();
1997-10-25 17:45:55 +04:00
if (!ok)
return ((struct passwd *) NULL);
1995-07-24 08:02:44 +04:00
#else
/*
1997-10-25 17:45:55 +04:00
* the best we can do is to ensure that the shell ends in "sh"
*/
1995-07-24 08:02:44 +04:00
ushell = localp.pw_shell;
1997-10-25 17:45:55 +04:00
if (strlen(ushell) < 2)
return ((struct passwd *) NULL);
1995-07-24 08:02:44 +04:00
ushell += strlen(ushell) - 2;
1997-10-25 17:45:55 +04:00
if (strcmp(ushell, "sh"))
return ((struct passwd *) NULL);
1995-07-24 08:02:44 +04:00
#endif
return (&localp);
}
1997-10-25 17:45:55 +04:00
1995-07-24 08:02:44 +04:00
/*
**---------------------------------------------------------------------
1997-10-25 17:45:55 +04:00
** Print support procedures
1995-07-24 08:02:44 +04:00
**---------------------------------------------------------------------
*/
1997-10-25 17:45:55 +04:00
char *
1995-07-24 08:02:44 +04:00
mapfont(f, i, b)
1997-10-25 17:45:55 +04:00
char f;
char i;
char b;
1995-07-24 08:02:44 +04:00
{
1997-10-25 17:45:55 +04:00
static char fontname[64];
1995-07-24 08:02:44 +04:00
fontname[0] = 0; /* clear it out */
switch (f) {
case 'c':
1997-10-25 17:45:55 +04:00
(void) strcpy(fontname, "Courier");
1995-07-24 08:02:44 +04:00
break;
case 'h':
1997-10-25 17:45:55 +04:00
(void) strcpy(fontname, "Helvetica");
1995-07-24 08:02:44 +04:00
break;
case 't':
1997-10-25 17:45:55 +04:00
(void) strcpy(fontname, "Times");
1995-07-24 08:02:44 +04:00
break;
default:
1997-10-25 17:45:55 +04:00
(void) strcpy(fontname, "Times-Roman");
goto finis;
1995-07-24 08:02:44 +04:00
}
if (i != 'o' && b != 'b') { /* no bold or oblique */
if (f == 't') /* special case Times */
1997-10-25 17:45:55 +04:00
(void) strcat(fontname, "-Roman");
1995-07-24 08:02:44 +04:00
goto finis;
}
1997-10-25 17:45:55 +04:00
(void) strcat(fontname, "-");
1995-07-24 08:02:44 +04:00
if (b == 'b')
1997-10-25 17:45:55 +04:00
(void) strcat(fontname, "Bold");
1995-07-24 08:02:44 +04:00
if (i == 'o') /* o-blique */
1997-10-25 17:45:55 +04:00
(void) strcat(fontname, f == 't' ? "Italic" : "Oblique");
1995-07-24 08:02:44 +04:00
finis: return (&fontname[0]);
}
/*
1997-10-25 17:45:55 +04:00
* run_ps630 performs the Diablo 630 emulation filtering process. ps630
* was broken in certain Sun releases: it would not accept point size or
* font changes. If your version is fixed, undefine the symbol
* PS630_IS_BROKEN and rebuild pc-nfsd.
*/
1995-07-24 08:02:44 +04:00
/* #define PS630_IS_BROKEN 1 */
void
run_ps630(f, opts)
1997-10-25 17:45:55 +04:00
char *f;
char *opts;
1995-07-24 08:02:44 +04:00
{
1997-10-25 17:45:55 +04:00
char temp_file[256];
char commbuf[256];
int i;
1995-07-24 08:02:44 +04:00
1997-10-25 17:45:55 +04:00
(void) strcpy(temp_file, f);
(void) strcat(temp_file, "X"); /* intermediate file name */
1995-07-24 08:02:44 +04:00
#ifndef PS630_IS_BROKEN
1997-10-25 17:45:55 +04:00
(void) sprintf(commbuf, "ps630 -s %c%c -p %s -f ",
opts[2], opts[3], temp_file);
(void) strcat(commbuf, mapfont(opts[4], opts[5], opts[6]));
(void) strcat(commbuf, " -F ");
(void) strcat(commbuf, mapfont(opts[7], opts[8], opts[9]));
(void) strcat(commbuf, " ");
(void) strcat(commbuf, f);
#else /* PS630_IS_BROKEN */
/*
* The pitch and font features of ps630 appear to be broken at
* this time.
*/
(void) sprintf(commbuf, "ps630 -p %s %s", temp_file, f);
#endif /* PS630_IS_BROKEN */
if ((i = system(commbuf)) != 0) {
1995-07-24 08:02:44 +04:00
/*
* Under (un)certain conditions, ps630 may return -1 even
* if it worked. Hence the commenting out of this error
* report.
*/
/* (void)fprintf(stderr, "\n\nrun_ps630 rc = %d\n", i) */ ;
/* exit(1); */
}
if (rename(temp_file, f)) {
perror("run_ps630: rename");
exit(1);
}
return;
}
1997-10-25 17:45:55 +04:00
1995-07-24 08:02:44 +04:00
/*
**---------------------------------------------------------------------
1997-10-25 17:45:55 +04:00
** WTMP update support
1995-07-24 08:02:44 +04:00
**---------------------------------------------------------------------
*/
#ifdef WTMP
#include <utmp.h>
#ifndef _PATH_WTMP
#define _PATH_WTMP "/usr/adm/wtmp"
#endif
void
wlogin(name, req)
1997-10-25 17:45:55 +04:00
char *name;
1995-07-24 08:02:44 +04:00
struct svc_req *req;
{
struct sockaddr_in *who;
struct hostent *hp;
1997-10-25 17:45:55 +04:00
char *host;
1995-07-24 08:02:44 +04:00
struct utmp ut;
1997-10-25 17:45:55 +04:00
int fd;
1995-07-24 08:02:44 +04:00
1997-10-25 17:45:55 +04:00
if (!wtmp_enabled)
1995-07-24 08:02:44 +04:00
return;
1997-10-25 17:45:55 +04:00
/* Get network address of client. */
1995-07-24 08:02:44 +04:00
who = &req->rq_xprt->xp_raddr;
1997-10-25 17:45:55 +04:00
/* Get name of connected client */
hp = gethostbyaddr((char *) &who->sin_addr,
sizeof(struct in_addr),
who->sin_family);
1995-07-24 08:02:44 +04:00
if (hp && (strlen(hp->h_name) <= sizeof(ut.ut_host))) {
host = hp->h_name;
} else {
host = inet_ntoa(who->sin_addr);
}
(void) strcpy(ut.ut_line, "PC-NFS");
1997-10-25 17:45:55 +04:00
(void) strncpy(ut.ut_name, name, sizeof ut.ut_name);
1995-07-24 08:02:44 +04:00
(void) strncpy(ut.ut_host, host, sizeof ut.ut_host);
1997-10-25 17:45:55 +04:00
ut.ut_time = time((time_t *) 0);
1995-07-24 08:02:44 +04:00
1997-10-25 17:45:55 +04:00
if ((fd = open(_PATH_WTMP, O_WRONLY | O_APPEND, 0)) >= 0) {
(void) write(fd, (char *) &ut, sizeof(struct utmp));
(void) close(fd);
1995-07-24 08:02:44 +04:00
}
}
1997-10-25 17:45:55 +04:00
#endif /* WTMP */
1995-07-24 08:02:44 +04:00
/*
**---------------------------------------------------------------------
1997-10-25 17:45:55 +04:00
** Run-process-as-user procedures
1995-07-24 08:02:44 +04:00
**---------------------------------------------------------------------
*/
#define READER_FD 0
#define WRITER_FD 1
1997-10-25 17:45:55 +04:00
static int child_pid;
1995-07-24 08:02:44 +04:00
1997-10-25 17:45:55 +04:00
static char cached_user[64] = "";
static uid_t cached_uid;
static gid_t cached_gid;
1995-07-24 08:02:44 +04:00
1997-10-25 17:45:55 +04:00
static struct sigaction old_action;
static struct sigaction new_action;
static struct itimerval timer;
1995-07-24 08:02:44 +04:00
1997-10-25 17:45:55 +04:00
int interrupted = 0;
static FILE *pipe_handle;
1995-07-24 08:02:44 +04:00
1997-10-25 17:45:55 +04:00
void
myhandler(dummy)
int dummy;
1995-07-24 08:02:44 +04:00
{
1997-10-25 17:45:55 +04:00
interrupted = 1;
fclose(pipe_handle);
kill(child_pid, SIGKILL);
msg_out("rpc.pcnfsd: su_popen timeout - killed child process");
1995-07-24 08:02:44 +04:00
}
1997-10-25 17:45:55 +04:00
void
start_watchdog(n)
int n;
1995-07-24 08:02:44 +04:00
{
1997-10-25 17:45:55 +04:00
/*
* Setup SIGALRM handler, force interrupt of ongoing syscall
*/
1995-07-24 08:02:44 +04:00
new_action.sa_handler = myhandler;
sigemptyset(&(new_action.sa_mask));
new_action.sa_flags = 0;
#ifdef SA_INTERRUPT
new_action.sa_flags |= SA_INTERRUPT;
#endif
sigaction(SIGALRM, &new_action, &old_action);
1997-10-25 17:45:55 +04:00
/*
* Set interval timer for n seconds
*/
1995-07-24 08:02:44 +04:00
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
timer.it_value.tv_sec = n;
timer.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, NULL);
interrupted = 0;
}
1997-10-25 17:45:55 +04:00
void
stop_watchdog()
1995-07-24 08:02:44 +04:00
{
1997-10-25 17:45:55 +04:00
/*
* Cancel timer
*/
1995-07-24 08:02:44 +04:00
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &timer, NULL);
1997-10-25 17:45:55 +04:00
/*
* restore old signal handling
*/
1995-07-24 08:02:44 +04:00
sigaction(SIGALRM, &old_action, NULL);
}
1997-10-25 17:45:55 +04:00
FILE *
1995-07-24 08:02:44 +04:00
su_popen(user, cmd, maxtime)
1997-10-25 17:45:55 +04:00
char *user;
char *cmd;
int maxtime;
1995-07-24 08:02:44 +04:00
{
1997-10-25 17:45:55 +04:00
int p[2];
int parent_fd, child_fd, pid;
1995-07-24 08:02:44 +04:00
struct passwd *pw;
if (strcmp(cached_user, user)) {
pw = getpwnam(user);
if (!pw)
pw = getpwnam("nobody");
if (pw) {
cached_uid = pw->pw_uid;
cached_gid = pw->pw_gid;
strcpy(cached_user, user);
} else {
cached_uid = (uid_t) (-2);
cached_gid = (gid_t) (-2);
cached_user[0] = '\0';
}
}
if (pipe(p) < 0) {
msg_out("rpc.pcnfsd: unable to create pipe in su_popen");
return (NULL);
}
parent_fd = p[READER_FD];
child_fd = p[WRITER_FD];
if ((pid = fork()) == 0) {
1997-10-25 17:45:55 +04:00
int i;
1995-07-24 08:02:44 +04:00
for (i = 0; i < 10; i++)
if (i != child_fd)
(void) close(i);
if (child_fd != 1) {
(void) dup2(child_fd, 1);
(void) close(child_fd);
}
dup2(1, 2); /* let's get stderr as well */
(void) setgid(cached_gid);
(void) setuid(cached_uid);
(void) execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
_exit(255);
}
if (pid == -1) {
msg_out("rpc.pcnfsd: fork failed");
close(parent_fd);
close(child_fd);
return (NULL);
}
child_pid = pid;
close(child_fd);
start_watchdog(maxtime);
pipe_handle = fdopen(parent_fd, "r");
return (pipe_handle);
}
int
su_pclose(ptr)
1997-10-25 17:45:55 +04:00
FILE *ptr;
1995-07-24 08:02:44 +04:00
{
1997-10-25 17:45:55 +04:00
int pid, status;
1995-07-24 08:02:44 +04:00
stop_watchdog();
fclose(ptr);
if (child_pid == -1)
return (-1);
while ((pid = wait(&status)) != child_pid && pid != -1);
return (pid == -1 ? -1 : status);
}
1997-10-25 17:45:55 +04:00
#if XXX_unused
1995-07-24 08:02:44 +04:00
/*
** The following routine reads a file "/etc/pcnfsd.conf" if present,
** and uses it to replace certain builtin elements, like the
** name of the print spool directory. The configuration file
** Is the usual kind: Comments begin with '#', blank lines are ignored,
** and valid lines are of the form
**
** <keyword><whitespace><value>
**
** The following keywords are recognized:
**
** spooldir
** printer name alias-for command
** wtmp yes|no
*/
void
config_from_file()
{
1997-10-25 17:45:55 +04:00
FILE *fd;
char buff[1024];
char *cp;
char *kw;
char *val;
char *arg1;
char *arg2;
if ((fd = fopen("/etc/pcnfsd.conf", "r")) == NULL)
1995-07-24 08:02:44 +04:00
return;
1997-10-25 17:45:55 +04:00
while (fgets(buff, 1024, fd)) {
1995-07-24 08:02:44 +04:00
cp = strchr(buff, '\n');
*cp = '\0';
cp = strchr(buff, '#');
1997-10-25 17:45:55 +04:00
if (cp)
1995-07-24 08:02:44 +04:00
*cp = '\0';
kw = strtok(buff, " \t");
1997-10-25 17:45:55 +04:00
if (kw == NULL)
1995-07-24 08:02:44 +04:00
continue;
val = strtok(NULL, " \t");
1997-10-25 17:45:55 +04:00
if (val == NULL)
1995-07-24 08:02:44 +04:00
continue;
1997-10-25 17:45:55 +04:00
if (!strcasecmp(kw, "spooldir")) {
1995-07-24 08:02:44 +04:00
strcpy(sp_name, val);
continue;
}
#ifdef WTMP
1997-10-25 17:45:55 +04:00
if (!strcasecmp(kw, "wtmp")) {
1995-07-24 08:02:44 +04:00
/* assume default is YES, just look for negatives */
1997-10-25 17:45:55 +04:00
if (!strcasecmp(val, "no") ||
!strcasecmp(val, "off") ||
!strcasecmp(val, "disable") ||
!strcmp(val, "0"))
1995-07-24 08:02:44 +04:00
wtmp_enabled = 0;;
continue;
}
1997-10-25 17:45:55 +04:00
#endif
if (!strcasecmp(kw, "printer")) {
1995-07-24 08:02:44 +04:00
arg1 = strtok(NULL, " \t");
arg2 = strtok(NULL, "");
1997-10-25 17:45:55 +04:00
(void) add_printer_alias(val, arg1, arg2);
1995-07-24 08:02:44 +04:00
continue;
}
/*
** Add new cases here
*/
}
fclose(fd);
}
1997-10-25 17:45:55 +04:00
#endif /* XXX_unused */
1995-07-24 08:02:44 +04:00
/*
** strembedded - returns true if s1 is embedded (in any case) in s2
*/
1997-10-25 17:45:55 +04:00
int
strembedded(s1, s2)
const char *s1;
const char *s2;
1995-07-24 08:02:44 +04:00
{
1997-10-25 17:45:55 +04:00
while (*s2) {
if (!strcasecmp(s1, s2))
1995-07-24 08:02:44 +04:00
return 1;
s2++;
}
return 0;
}