Compare commits

..

2 Commits

Author SHA1 Message Date
ncpfs archive import
fff159f2db Import ncpfs 2.0.8 2026-04-28 20:39:58 +02:00
ncpfs archive import
c4d2144d0d Import ncpfs 2.0.7 2026-04-28 20:39:58 +02:00
62 changed files with 3751 additions and 437 deletions

BIN
.downloads/ncpfs-2.0.7.tgz Normal file

Binary file not shown.

BIN
.downloads/ncpfs-2.0.8.tgz Normal file

Binary file not shown.

14
Changes
View File

@@ -1,6 +1,20 @@
I only began this file with ncpfs-0.12. If you're interested in older
versions, you can find them on ftp.gwdg.de:/pub/linux/misc/ncpfs/old.
ncpfs-2.0.7 -> ncpfs-2.0.8
- Fixed util/Makefile for easier optimization handling. Thanks to Rik
Faith <faith@cs.unc.edu> for this one
- added nwfstime. You can now set the file server date and time from Linux.
- added the contrib directory. Feel free to add more!
ncpfs-2.0.6 -> ncpfs-2.0.7
- Hopefully removed one security problem in ncpumount.
- Added command line flag to pserver.c
- Heavily reconstructed ncpfs utils. Created the lib/ dir.
- Separated the uid utils in sutil
- Add nwsfind to enable users to use ncpfs safely without setting
the utils setuid root.
ncpfs-2.0.5 -> ncpfs-2.0.6
- Added a short description of a problem that I need help with to the
file BUGS. If you know a bit of the linux networking code, please

2
FAQ
View File

@@ -1,5 +1,5 @@
There is certainly not enough material to call this an FAQ, but some
questions reach me regularly. Probably the documenation is not clear
questions reach me regularly. Probably the documentation is not clear
enough.
-------------------------------------------------------------------------------

View File

@@ -2,7 +2,7 @@
# Makefile for the linux ncp-filesystem routines.
#
VERSION = 2.0.6
VERSION = 2.0.8
# If you are using kerneld to autoload ncp support,
# uncomment this (kerneld is in linux since about 1.3.57):
@@ -11,33 +11,38 @@ VERSION = 2.0.6
# If your system is ELF, either also do a 'make install', or append the util/
# directory where the dynamic library resides to the environment
# variable LD_LIBRARY_PATH
HAVE_ELF=$(shell file `which gcc`|grep ELF >/dev/null && echo -n yes )
HAVE_ELF=$(shell file `whereis gcc|cut -d ' ' -f 2`| \
grep ELF >/dev/null && echo -n yes )
TOPDIR = $(shell pwd)
BINDIR = /usr/local/bin
BINDIR = /usr/bin
SBINDIR = /sbin
INTERM_BINDIR = $(TOPDIR)/bin
SUBDIRS = util ipx-1.0 man
SUBDIRS = lib sutil util ipx-1.0 man
KVERSION=$(shell uname -r | cut -b1-3)
INCLUDES=-I$(TOPDIR)/include
ifeq ($(KVERSION),1.2)
SUBDIRS += kernel-1.2/src
INCLUDES = -I$(TOPDIR)/kernel-1.2
INCLUDES += -I$(TOPDIR)/kernel-1.2
endif
export INCLUDES BINDIR INTERM_BINDIR SBINDIR KERNELD VERSION HAVE_ELF
COPT = -O2
# COPT += -g
CFLAGS = $(COPT) -Wall $(INCLUDES) $(KERNELD) -DNCPFS_VERSION=\"$(VERSION)\"
export INCLUDES BINDIR SBINDIR KERNELD VERSION HAVE_ELF CFLAGS
all:
for i in $(SUBDIRS); do make -C $$i all; done
@if [ "$(HAVE_ELF)" = yes ] ;\
then \
echo ; echo ; echo ;\
echo Please add \'`pwd`/util\' to the environment ; \
echo Please add \'`pwd`/lib\' to the environment ; \
echo variable LD_LIBRARY_PATH by executing ; \
echo ;\
echo export LD_LIBRARY_PATH=\"\$$LD_LIBRARY_PATH:`pwd`/util\" ; \
echo export LD_LIBRARY_PATH=\"\$$LD_LIBRARY_PATH:`pwd`/lib\" ; \
echo ;\
echo or do a \'make install\'. ;\
echo ;\
@@ -49,17 +54,16 @@ dep:
install:
for i in $(SUBDIRS); do make -C $$i install; done
clean:
rm -f `find . -type f -name '*.o' -print`
rm -f `find . -type f -name '*~' -print`
rm -f `find . -type f -name '.depend' -print`
rm -f `find . -type f -name '*.out' -print`
clean_me:
rm -f `find -name '*.out'`
rm -f `find -name '*~'`
rm -f *.tgz
clean: clean_me
for i in $(SUBDIRS); do make -C $$i clean; done
mrproper: clean
rm -fr $(INTERM_BINDIR)/* ncpfs.tgz
make -C util mrproper
make -C ipxdump mrproper
mrproper: clean_me
for i in $(SUBDIRS) ipxdump; do make -C $$i mrproper; done
modules: ncpfs.o

5
TODO
View File

@@ -1,14 +1,11 @@
Here's a list of things I want to do. Feel free to send suggestions,
or even help me ;-).
- Add flags to pserver's command line, so that the print command can
find out the name of user who printed the job.
- do rtt estimation, like tcp does.
- Do better connection management. I imagine to create a ncpd.
- When ncp is done, one can think about mounting several volumes over
- When ncpd is done, one can think about mounting several volumes over
a single NCP connection. This should make the trade-off mentioned in
ncpmount.8 unnecessary.

239
contrib/tknwmsg/nwmsg.c Normal file
View File

@@ -0,0 +1,239 @@
/*
* nwmsg.c
*
* Fetch NetWare broadcast messages and write to the user
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <unistd.h>
#include <syslog.h>
#include <signal.h>
#include <paths.h>
#include <utmp.h>
#include <mntent.h>
#include "ncplib.h"
static int search_utmp(char *user, char *tty);
static char *progname;
void
main(int argc, char *argv[])
{
struct ncp_conn *conn;
char message[256];
char *mount_point;
struct ncp_fs_info info;
struct passwd *pwd;
char tty[256];
char tty_path[256];
FILE *tty_file;
FILE *mtab;
struct mntent *mnt;
long err;
char tknwmsg_command[256];
int error_level;
progname = argv[0];
openlog("nwmsg", LOG_PID, LOG_LPR);
if (argc != 2)
{
fprintf(stderr, "usage: %s mount-point\n",
progname);
exit(1);
}
mount_point = argv[1];
if ((conn = ncp_open_mount(mount_point, &err)) == NULL)
{
com_err(progname, err, "in ncp_open_mount");
exit(1);
}
if (ncp_get_broadcast_message(conn, message) != 0)
{
fprintf(stderr, "%s: could not get broadcast message\n",
progname);
ncp_close(conn);
exit(1);
}
if (strlen(message) == 0)
{
syslog(LOG_DEBUG, "no message");
exit(0);
}
#if 0
syslog(LOG_DEBUG, "message: %s", message);
#endif
info.version = NCP_GET_FS_INFO_VERSION;
if (ioctl(conn->mount_fid, NCP_IOC_GET_FS_INFO, &info) < 0)
{
fprintf(stderr, "%s: could not ioctl on connection: %s\n",
progname, strerror(errno));
ncp_close(conn);
exit(1);
}
ncp_close(conn);
if ((pwd = getpwuid(info.mounted_uid)) == NULL)
{
fprintf(stderr, "%s: user %d not known\n",
progname, info.mounted_uid);
exit(1);
}
if ((mtab = fopen(MOUNTED, "r")) == NULL)
{
fprintf(stderr, "%s: can't open %s\n",
progname, MOUNTED);
exit(1);
}
while ((mnt = getmntent(mtab)) != NULL)
{
if (strcmp(mnt->mnt_dir, mount_point) == 0)
{
break;
}
}
if (mnt == NULL)
{
syslog(LOG_DEBUG, "cannot find mtab entry\n");
}
if (search_utmp(pwd->pw_name, tty) != 0)
{
exit(1);
}
sprintf(tty_path, "/dev/%s", tty);
if ((tty_file = fopen(tty_path, "w")) == NULL)
{
fprintf(stderr, "%s: cannot open %s: %s\n",
progname, tty_path, strerror(errno));
exit(1);
}
fprintf(tty_file,"\r\n\007\007\007Message from NetWare Server: %s\r\n",
mnt->mnt_fsname);
fprintf(tty_file, "%s\r\n", message);
//formulate the full system command for the X notice...
strcat(tknwmsg_command,"/usr/bin/tknwmsg -display :0 ");
strcat(tknwmsg_command,"Message from NetWare Server: ");
strcat(tknwmsg_command,mnt->mnt_fsname);
strcat(tknwmsg_command," ");
strcat(tknwmsg_command,message);
strcat(tknwmsg_command," &");
//execute this system command...
error_level = system(tknwmsg_command);
fclose(tty_file);
fclose(mtab);
return;
}
/* The following routines have been taken from util-linux-2.5's write.c */
/*
* term_chk - check that a terminal exists, and get the message bit
* and the access time
*/
static int
term_chk(char *tty, int *msgsokP, time_t *atimeP, int *showerror)
{
struct stat s;
char path[MAXPATHLEN];
(void)sprintf(path, "/dev/%s", tty);
if (stat(path, &s) < 0) {
if (showerror)
(void)fprintf(stderr,
"write: %s: %s\n", path, strerror(errno));
return(1);
}
*msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0; /* group write bit */
*atimeP = s.st_atime;
return(0);
}
/*
* search_utmp - search utmp for the "best" terminal to write to
*
* Ignores terminals with messages disabled, and of the rest, returns
* the one with the most recent access time. Returns as value the number
* of the user's terminals with messages enabled, or -1 if the user is
* not logged in at all.
*
* Special case for writing to yourself - ignore the terminal you're
* writing from, unless that's the only terminal with messages enabled.
*/
static int
search_utmp(char *user, char *tty)
{
struct utmp u;
time_t bestatime, atime;
int ufd, nloggedttys, nttys, msgsok, user_is_me;
char atty[sizeof(u.ut_line) + 1];
if ((ufd = open(_PATH_UTMP, O_RDONLY)) < 0) {
perror("utmp");
return -1;
}
nloggedttys = nttys = 0;
bestatime = 0;
user_is_me = 0;
while (read(ufd, (char *) &u, sizeof(u)) == sizeof(u))
if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) {
++nloggedttys;
(void)strncpy(atty, u.ut_line, sizeof(u.ut_line));
atty[sizeof(u.ut_line)] = '\0';
if (term_chk(atty, &msgsok, &atime, 0))
continue; /* bad term? skip */
if (!msgsok)
continue; /* skip ttys with msgs off */
if (u.ut_type != USER_PROCESS)
continue; /* it's not a valid entry */
++nttys;
if (atime > bestatime) {
bestatime = atime;
(void)strcpy(tty, atty);
}
}
(void)close(ufd);
if (nloggedttys == 0) {
(void)fprintf(stderr, "write: %s is not logged in\n", user);
return -1;
}
return 0;
}

57
contrib/tknwmsg/tknwmsg Executable file
View File

@@ -0,0 +1,57 @@
#!/usr/bin/wish
#This is a procedure for centering windows...
#
#
proc center {window_to_center} {
update idletasks
set width [expr [winfo reqwidth $window_to_center]]
set height [expr [winfo reqheight $window_to_center]]
if {$width < 400} {set width 400}
set x [expr [winfo screenwidth $window_to_center]/2 - $width/2]
set y [expr [winfo screenheight $window_to_center]/2 - $height/2]
wm geometry $window_to_center $width\x$height+$x+$y
#update idletasks
wm deiconify $window_to_center
}
#
#
#
#
#This is the main() proc...
set argv_exist [string length $argv]
if {$argv_exist <= 0} {puts "syntax: tkmesg string\a";exit}
wm withdraw .
wm title . "Netware Client for Linux"
wm resizable . 0 0
puts "\a"
label .mesg -text $argv
pack .mesg -padx 5 -pady 5
button .ok -text "Ok" -command exit -width 5
pack .ok -padx 5 -pady 5
focus .ok
bind .ok <Return> exit
center .
#beep the users console after the window appears...
set ofd [open /dev/console w]
puts $ofd "\a"
close $ofd

BIN
contrib/tknwmsg/tknwmsg.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,29 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<TITLE></TITLE>
<META NAME="GENERATOR" CONTENT="Mozilla/3.01Gold (X11; I; Linux 2.0.25 i586) [Netscape]">
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EF" VLINK="#51188E" ALINK="#FF0000">
<CENTER><P><FONT SIZE=+3>Tknwmsg</FONT></P></CENTER>
<P>Recieve NetWare broadcasts in a dialog under Linux.</P>
<P>The original source was included in the ncpfs package distributed on
sunsite.unc.edu. The modified source to nwmsg.c and a tcl/tk script can
be downloaded here. The <A HREF="tknwmsg_README">tknwmsg_README</A> is
also available for download.</P>
<P>The only requirements for installation are a system with tcl/tk installed
and X running. The system()&nbsp;command will fail if X is not running.</P>
<P>
<HR WIDTH="100%"></P>
<P><A HREF="mailto:kburto1@umbc.edu">Kevin Burton</A></P>
<P><A HREF="http://www.gl.umbc.edu/~kburto1/kburto1.html">http://www.gl.umbc.edu/~kburto1/kburto1.html</A></P>
</BODY>
</HTML>

View File

@@ -0,0 +1,40 @@
Tknwmsg 1.0 for NCPFS.
Kevin Burton (kburto1@umbc.edu), Copyright 1996
Distributed under GPL (GNU Public License)
-- INTRO --
Tknwmesg is a extension for ncpfs for linux that allows users to recived messages
while under an X console.
Essentially it is an extension for nwmsg that comes with ncpfs. The only
changes are a system() call to a tk script that will run a dialog with an "ok"
button under X.
-- INSTALLATION --
TCL/TK must be installed on your system. If they are not then you will have to
get the source for their installation if you want to run tkmesg.
- Download ncpfs from sunsite.unc.edu
- Run "su" to become root if you are not already root.
- Unpack ncpfs in a temporary directory.
- copy the Tknwmsg nwmsg.c to util/nwmsg.c in your ncpfs directory.
- copy tknwmsg to /usr/bin
- change to your nwmsg directory.
- run "make all;make install" and the new version of tknwmsg will be
installed.
-- USE --
- At least 1 terminal on the local system must be have "mesg y". Else
no GUI dialog will be displayed.
Using mesg y in a .bashrc will not work. The only way that I have
found to do this is to have chmod a+w /dev/ttyp? in Xsession or
$HOME/.xsession. Also it may be necessary to have .bashrc do the
same thing if users are starting and stopping xterms.

View File

@@ -121,6 +121,10 @@ ncp_find_permanent(const struct ncp_conn_spec *spec);
struct sockaddr_ipx *
ncp_find_fileserver(const char *server_name, long *err);
/* Find the address of a server */
struct sockaddr_ipx *
ncp_find_server(const char **server_name, int type, long *err);
/* Detach from a permanent connection or destroy a temporary
connection */
long
@@ -154,6 +158,8 @@ ncp_get_file_server_description_strings(struct ncp_conn *conn,
long
ncp_get_file_server_time(struct ncp_conn *conn, time_t *target);
long
ncp_set_file_server_time(struct ncp_conn *conn, time_t *source);
struct ncp_file_server_info {
__u8 ServerName[48] __attribute__ ((packed));

View File

@@ -1,24 +0,0 @@
CFLAGS = -O2 -Wall
UTILS = ipx_configure ipx_interface ipx_internal_net ipx_route
all: $(UTILS)
clean:
rm -f $(UTILS) *.o rip sap ipxrcv ipxsend
install: $(UTILS)
for i in $(UTILS); \
do \
install --strip $$i /sbin; \
install $$i.8 /usr/man/man8; \
done
install init.ipx /etc/rc.d/init.d/ipx
install -m 0644 config.ipx /etc/sysconfig/ipx
rm -f /etc/rc.d/rc2.d/S15ipx
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc2.d/S15ipx
rm -f /etc/rc.d/rc3.d/S15ipx
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc3.d/S15ipx
rm -f /etc/rc.d/rc5.d/S15ipx
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc5.d/S15ipx
rm -f /etc/rc.d/rc6.d/K55ipx
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc6.d/K55ipx

View File

@@ -1,30 +1,19 @@
CFLAGS = -O2 -Wall
UTILS = $(INTERM_BINDIR)/ipx_configure $(INTERM_BINDIR)/ipx_interface \
$(INTERM_BINDIR)/ipx_internal_net $(INTERM_BINDIR)/ipx_route
UTILS = ipx_configure ipx_interface ipx_internal_net ipx_route
all: $(UTILS)
$(INTERM_BINDIR)/ipx_configure: ipx_configure.o
$(CC) -o $(INTERM_BINDIR)/ipx_configure ipx_configure.o
$(INTERM_BINDIR)/ipx_interface: ipx_interface.o
$(CC) -o $(INTERM_BINDIR)/ipx_interface ipx_interface.o
$(INTERM_BINDIR)/ipx_internal_net: ipx_internal_net.o
$(CC) -o $(INTERM_BINDIR)/ipx_internal_net ipx_internal_net.o
$(INTERM_BINDIR)/ipx_route: ipx_route.o
$(CC) -o $(INTERM_BINDIR)/ipx_route ipx_route.o
dep:
$(CPP) -M $(INCLUDES) *.c > .depend
clean:
rm -f $(UTILS) *.o rip sap ipxrcv ipxsend
mrproper: clean
rm -f .depend
install: $(UTILS)
for i in $(UTILS); \
do \
install $$i $(BINDIR); \
done

76
lib/Makefile Normal file
View File

@@ -0,0 +1,76 @@
#
# Makefile for the linux ncp-filesystem routines.
#
CC = gcc
ifeq ($(HAVE_ELF),yes)
PIC_FLAG = -fPIC
NCP_LIB = libncp.so.1.0
LIB_LINK_COMMAND = gcc -shared -Wl,-soname,libncp.so.1 -o $(NCP_LIB)
INSTALL_LIB = install $(NCP_LIB) -m 755 /lib; \
ln -sf $(NCP_LIB) /lib/libncp.so.1; \
ldconfig
export PIC_FLAG
else
NCP_LIB = libncp.a
LIB_LINK_COMMAND = ar r libncp.a
endif
CFLAGS += $(PIC_FLAG)
default:
make -C ..
all: libcom_err.a ncplib_err.o $(NCP_LIB)
install:
$(INSTALL_LIB)
ncplib.o: ncplib.c ncplib_err.h
$(CC) $(CFLAGS) -finline-functions -c ncplib.c
COM_ERR_CFILES = com_err/com_err.c com_err/error_message.c com_err/et_name.c \
com_err/init_et.c
COM_ERR_OFILES = com_err/com_err.o com_err/error_message.o com_err/et_name.o \
com_err/init_et.o
libcom_err.a: $(COM_ERR_CFILES)
make -C com_err
$(NCP_LIB): ncplib.o ncplib_err.o libcom_err.a
$(LIB_LINK_COMMAND) ncplib.o ncplib_err.o $(COM_ERR_OFILES)
ln -sf libncp.so.1.0 libncp.so.1
ln -sf libncp.so.1 libncp.so
export LD_LIBRARY_PATH=`pwd`:LD_LIBRARY_PATH
ncplib_err.o: ncplib_err.h ncplib_err.c
$(CC) $(CFLAGS) -c ncplib_err.c
ncplib_err.h: ncplib_err.et
com_err/compile_et ncplib_err
ln -sf ../lib/ncplib_err.h ../include/ncplib_err.h
ncplib_err.c: ncplib_err.et
com_err/compile_et ncplib_err
dep: ncplib_err.h
make -C com_err dep
$(CPP) -M $(INCLUDES) *.c > .depend
clean:
make -C com_err clean
rm -f *.o *~ ncplib_err.[ch] ../include/ncplib_err.h
rm -f libncp.*
mrproper: clean
make -C com_err mrproper
rm -f $(UTILS) .depend $(DISTFILE)
#
# include a dependency file if one exists
#
ifeq (.depend,$(wildcard .depend))
include .depend
endif

View File

@@ -5,13 +5,16 @@
OBJECTS = com_err.o error_message.o et_name.o init_et.o
CFLAGS = -Wall -O2 $(PIC_FLAG)
all: $(OBJECTS)
all: ../libcom_err.a
../libcom_err.a: $(OBJECTS)
ar r ../libcom_err.a $(OBJECTS)
dep:
$(CPP) -M $(INCLUDES) *.c > .depend
clean:
rm -f *.o
rm -f *.o ../libcom_err.a
mrproper: clean
rm -f .depend

40
lib/com_err/com_err.h Normal file
View File

@@ -0,0 +1,40 @@
/*
* Header file for common error description library.
*
* Copyright 1988, Student Information Processing Board of the
* Massachusetts Institute of Technology.
*
* For copyright and distribution info, see the documentation supplied
* with this package.
*/
#ifndef __COM_ERR_H
typedef long errcode_t;
#ifdef __STDC__
#include <stdarg.h>
/* ANSI C -- use prototypes etc */
void com_err (const char *, long, const char *, ...);
void com_err_va (const char *whoami, errcode_t code, const char *fmt,
va_list args);
char const *error_message (long);
extern void (*com_err_hook) (const char *, long, const char *, va_list);
void (*set_com_err_hook (void (*) (const char *, long, const char *, va_list)))
(const char *, long, const char *, va_list);
void (*reset_com_err_hook (void)) (const char *, long, const char *, va_list);
int init_error_table(const char * const *msgs, int base, int count);
#else
/* no prototypes */
void com_err ();
void com_err_va ();
char *error_message ();
extern void (*com_err_hook) ();
void (*set_com_err_hook ()) ();
void (*reset_com_err_hook ()) ();
int init_error_table();
#endif
#define __COM_ERR_H
#endif /* ! defined(__COM_ERR_H) */

View File

@@ -161,6 +161,43 @@ ipx_sscanf_node(char *buf, unsigned char node[6])
return 6;
}
static int
ipx_sscanf_saddr(char *buf, struct sockaddr_ipx *target)
{
char *p;
struct sockaddr_ipx addr;
addr.sipx_family = AF_IPX;
addr.sipx_type = NCP_PTYPE;
if (sscanf(buf, "%lx", &addr.sipx_network) != 1)
{
return 1;
}
addr.sipx_network = htonl(addr.sipx_network);
if ((p = strchr(buf, ':')) == NULL)
{
return 1;
}
p += 1;
if (ipx_sscanf_node(p, addr.sipx_node) != 6)
{
return 1;
}
if ((p = strchr(p, ':')) == NULL)
{
return 1;
}
p += 1;
if (sscanf(p, "%hx", &addr.sipx_port) != 1)
{
return 1;
}
addr.sipx_port = htons(addr.sipx_port);
*target = addr;
return 0;
}
void
ipx_assign_node(IPXNode dest, IPXNode src)
{
@@ -222,224 +259,6 @@ ipx_recv(int sock, void *buf, int len, unsigned int flags, int timeout,
timeout, err);
}
static long
ipx_sap_find_nearest(int server_type, struct sockaddr_ipx *result,
char server_name[NCP_BINDERY_NAME_LEN])
{
struct sockaddr_ipx addr;
char data[1024];
int sock;
int opt;
int packets;
int len;
struct sap_server_ident *ident;
if ((sock = socket(AF_IPX,SOCK_DGRAM,PF_IPX)) < 0)
{
if (errno == EINVAL)
{
return NCPL_ET_NO_IPX;
}
return errno;
}
opt=1;
/* Permit broadcast output */
if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST, &opt,sizeof(opt))==-1)
{
goto finished;
}
memzero(addr);
addr.sipx_family = AF_IPX;
addr.sipx_network = htonl(0x0);
addr.sipx_port = htons(0x0);
addr.sipx_type = IPX_SAP_PTYPE;
if(bind(sock,(struct sockaddr*)&addr,sizeof(addr))==-1)
{
if (errno == EADDRNOTAVAIL)
{
errno = NCPL_ET_NO_INTERFACE;
}
goto finished;
}
*(unsigned short *)data = htons(IPX_SAP_NEAREST_QUERY);
*(unsigned short *)&(data[2]) = htons(server_type);
memzero(addr);
addr.sipx_family = AF_IPX;
addr.sipx_port = htons(IPX_SAP_PORT);
addr.sipx_type = IPX_SAP_PTYPE;
addr.sipx_network = htonl(0x0);
ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE);
if (sendto(sock, data, 4, 0,
(struct sockaddr *)&addr, sizeof(addr)) < 0)
{
goto finished;
}
packets = 5;
do
{
long err;
len = ipx_recv(sock, data, 1024, 0, 1, &err);
if (len < 66)
{
packets = packets - 1;
continue;
}
}
while ( (ntohs(*((__u16 *)data)) != IPX_SAP_NEAREST_RESPONSE)
&& (packets > 0));
if (packets == 0)
{
close(sock);
return NCPL_ET_NO_SERVER;
}
ident = (struct sap_server_ident *)(data+2);
result->sipx_family = AF_IPX;
result->sipx_network = ident->server_network;
result->sipx_port = ident->server_port;
ipx_assign_node(result->sipx_node, ident->server_node);
memcpy(server_name, ident->server_name, sizeof(ident->server_name));
errno = 0;
finished:
close(sock);
return errno;
}
static int
ipx_make_reachable(IPXNet network)
{
struct rtentry rt_def;
/* Router */
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rt_def.rt_gateway;
/* Target */
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rt_def.rt_dst;
struct ipx_rip_packet rip;
struct sockaddr_ipx addr;
int addrlen;
int sock;
int opt;
int res=-1;
int i;
int packets;
if (geteuid() != 0)
{
errno = EPERM;
return -1;
}
memzero(rip);
sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX);
if (sock == -1)
{
if (errno == EINVAL)
{
return NCPL_ET_NO_IPX;
}
return errno;
}
opt=1;
/* Permit broadcast output */
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) != 0)
{
goto finished;
}
memzero(addr);
addr.sipx_family = AF_IPX;
addr.sipx_network = htonl(0x0);
addr.sipx_port = htons(0x0);
addr.sipx_type = IPX_RIP_PTYPE;
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0)
{
goto finished;
}
addr.sipx_family = AF_IPX;
addr.sipx_port = htons(IPX_RIP_PORT);
addr.sipx_type = IPX_RIP_PTYPE;
addr.sipx_network = htonl(0x0);
ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE);
rip.operation = htons(IPX_RIP_REQUEST);
rip.rt[0].network = htonl(network);
if (sendto(sock, &rip, sizeof(rip), 0,
(struct sockaddr *)&addr, sizeof(addr)) < 0)
{
goto finished;
}
packets = 3;
do
{
long err;
int len;
if (packets == 0)
{
goto finished;
}
addrlen = sizeof(struct sockaddr_ipx);
len = ipx_recvfrom(sock, &rip, sizeof(rip),0, sr, &addrlen, 1,
&err);
if (len < sizeof(rip))
{
packets = packets - 1;
continue;
}
}
while (ntohs(rip.operation) != IPX_RIP_RESPONSE);
if (rip.rt[0].network != htonl(network))
{
goto finished;
}
rt_def.rt_flags = RTF_GATEWAY;
st->sipx_network = htonl(network);
st->sipx_family = AF_IPX;
sr->sipx_family = AF_IPX;
i = 0;
do
{
res = ioctl(sock, SIOCADDRT, &rt_def);
i++;
}
while ((i < 5) && (res < 0) && (errno == EAGAIN));
finished:
close(sock);
if (res != 0)
{
errno = ENETUNREACH;
}
return res;
}
static int
install_wdog(struct ncp_conn *conn)
{
@@ -780,13 +599,8 @@ ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr_ipx *target,
if ((err = do_ncp_call(conn, sizeof(*h))) != 0)
{
if ( (err != ENETUNREACH)
|| (ipx_make_reachable(htonl(target->sipx_network)) != 0)
|| ((err = do_ncp_call(conn, sizeof(*h))) != 0))
{
close(ncp_sock); close(wdog_sock);
return err;
}
close(ncp_sock); close(wdog_sock);
return err;
}
if (wdog_needed != 0)
@@ -817,103 +631,82 @@ ncp_connect_addr(struct ncp_conn *conn, const struct sockaddr_ipx *target,
static long
ncp_connect_any(struct ncp_conn *conn, int wdog_needed)
{
struct sockaddr_ipx addr;
char name[NCP_BINDERY_NAME_LEN];
struct sockaddr_ipx *addr;
long result;
const char *server = NULL;
long err;
if ((result = ipx_sap_find_nearest(IPX_SAP_FILE_SERVER,
&addr, name)) != 0)
if ((addr = ncp_find_server(&server,NCP_BINDERY_FSERVER,&err)) == NULL)
{
return err;
}
if ((result = ncp_connect_addr(conn, addr, wdog_needed)) != 0)
{
return result;
}
if ((result = ncp_connect_addr(conn, &addr, wdog_needed)) != 0)
{
return result;
}
strcpy(conn->server, name);
strcpy(conn->server, server);
return 0;
}
struct sockaddr_ipx *
ncp_find_fileserver(const char *server_name, long *err)
{
char server[NCP_BINDERY_NAME_LEN];
char nearest[NCP_BINDERY_NAME_LEN];
struct nw_property prop;
struct prop_net_address *n_addr = (struct prop_net_address *)&prop;
struct ncp_conn conn;
return ncp_find_server(&server_name, NCP_BINDERY_FSERVER, err);
}
struct sockaddr_ipx *
ncp_find_server(const char **server_name, int type, long *err)
{
char command[256];
char buf[128];
char server[NCP_BINDERY_NAME_LEN+1];
static struct sockaddr_ipx result;
FILE *p;
int res;
char *n;
initialize_NCPL_error_table();
if (strlen(server_name) >= sizeof(server))
memset(server, 0, sizeof(server));
if (*server_name != NULL)
{
*err = NCPL_ET_NAMETOOLONG;
strncpy(server, *server_name, sizeof(server)-1);
str_upper(server);
}
sprintf(command, "nwsfind -t %d %s", type, server);
p = popen(command, "r");
if (p == NULL)
{
*err = errno;
return NULL;
}
strcpy(server, server_name);
str_upper(server);
fgets(buf, sizeof(buf), p);
if ((*err = ipx_sap_find_nearest(IPX_SAP_FILE_SERVER,
&result, nearest)) != 0)
if (buf[strlen(buf)] - 1 == '\n');
{
buf[strlen(buf)] = '\0';
}
if (((res = pclose(p)) != 0) || (ipx_sscanf_saddr(buf, &result) != 0))
{
*err = (*server_name != NULL)
? NCPL_ET_HOST_UNKNOWN : NCPL_ET_NO_SERVER;
return NULL;
}
/* We have to ask the nearest server for our wanted server */
memzero(conn);
if ((*err = ncp_connect_addr(&conn, &result, 0)) != 0)
if (*server_name == NULL)
{
return NULL;
if ((n = strchr(buf, ' ')) == NULL)
{
*err = NCPL_ET_HOST_UNKNOWN;
return NULL;
}
*server_name = n;
}
/* The following optimization should have been done before
ncp_connect_addr. This would be convenient if there was a
simple way to find out whether there is a route to the
server. Parsing /proc/net/ipx_route is not too nice, so we
just connect to the server and immediately disconnect
again. This way we also find out if the server still has
free connection slots. */
if (strcmp(server, nearest) == 0)
{
/* Our wanted server answered the SAP GNS request, so
use it */
ncp_do_close(&conn);
errno = 0;
return &result;
}
if (ncp_read_property_value(&conn, NCP_BINDERY_FSERVER, server, 1,
"NET_ADDRESS", &prop) != 0)
{
ncp_do_close(&conn);
*err = NCPL_ET_HOST_UNKNOWN;
return NULL;
}
if ((*err = ncp_do_close(&conn)) != 0)
{
return NULL;
}
result.sipx_family = AF_IPX;
result.sipx_network = n_addr->network;
result.sipx_port = n_addr->port;
ipx_assign_node(result.sipx_node, n_addr->node);
/* To make the final server reachable, we connect again. See
above. (When can we rely on all users running ipxd??? :-)) */
memzero(conn);
if ( ((*err = ncp_connect_addr(&conn, &result, 0)) != 0)
|| ((*err = ncp_do_close(&conn)) != 0))
{
return NULL;
}
return &result;
}
@@ -1867,6 +1660,32 @@ ncp_get_file_server_time(struct ncp_conn *conn, time_t *target)
return 0;
}
long
ncp_set_file_server_time(struct ncp_conn *conn, time_t *source)
{
long result;
int year;
struct tm *utime = localtime(source);
year = utime->tm_year;
if (year > 99)
{
year -= 100;
}
ncp_init_request_s(conn, 202);
ncp_add_byte(conn, year);
ncp_add_byte(conn, utime->tm_mon+1);
ncp_add_byte(conn, utime->tm_mday);
ncp_add_byte(conn, utime->tm_hour);
ncp_add_byte(conn, utime->tm_min);
ncp_add_byte(conn, utime->tm_sec);
result = ncp_request(conn, 23);
ncp_unlock_conn(conn);
return result;
}
long
ncp_get_file_server_information(struct ncp_conn *conn,
struct ncp_file_server_info *target)

View File

@@ -90,7 +90,7 @@ option to
.B ncpmount(8), ncpumount(8)
.SH CREDITS
ncopy was written by Brian G. Reid (breid@tim.com) and
Tom C. Henderson (thenderson@tim.com).
Many thanks to Volker Lendecke (lendecke@namu01.gwdg.de) for the ncpfs
and ncplib which made ncopy possible.
ncopy was written by Brian G. Reid (breid@tim.com) and Tom
C. Henderson (thenderson@tim.com). Many thanks to Volker Lendecke
(lendecke@math.uni-goettingen.de) for the ncpfs and ncplib which made
ncopy possible.

View File

@@ -291,5 +291,5 @@ The encryption code was taken from Dr. Dobbs's Journal 11/93. There
Pawel Szczerbina described it in an article on NCP.
The ncpfs code was initially hacked from smbfs by Volker Lendecke
(lendecke@namu01.gwdg.de). smbfs was put together by Paal-Kr. Engstad
(lendecke@math.uni-goettingen.de). smbfs was put together by Paal-Kr. Engstad
(pke@engstad.ingok.hitos.no) and later polished by Volker.

View File

@@ -219,4 +219,4 @@ printed if a printer operator has put in the correct form.
.B nwclient(5), slist(1), pqlist(1), ncpmount(8), ncpumount(8)
.SH CREDITS
nprint was written by Volker Lendecke (lendecke@namu01.gwdg.de)
nprint was written by Volker Lendecke (lendecke@math.uni-goettingen.de)

69
man/nwauth.1 Normal file
View File

@@ -0,0 +1,69 @@
.TH NWAUTH 1 10/27/1996 nwauth nwauth
.SH NAME
nwauth \- Verify username/password
.SH SYNOPSIS
.B nwauth
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
]
.SH DESCRIPTION
.B nwauth
does nothing but logging into a NetWare server. If the login was
successful, an error code of 0 is returned. If the login was not
successful, an error code of 1 is returned. It was designed for
use by other programs who want authenticate users via a NetWare
server.
nwauth
.B always
expects a password on stdin. If the stdin is a tty, then the user is
prompted for a password. Otherwise nwauth simply reads stdin for a
password.
.B nwauth
looks up the file
.I $HOME/.nwclient
to find a file server and a user name. See nwclient(5) for more
information. Please note that the access permissions of .nwclient MUST
be 600, for security reasons.
.SH OPTIONS
.B -h
.RS 3
.B -h
is used to print a short help text.
.RE
.B -S
.I server
.RS 3
.B server
is the name of the server you want to use.
.RE
.B -U
.I user name
.RS 3
If the user name your NetWare administrator gave to you differs
from your unix user-id, you should use
.B -U
to tell the server about your NetWare user name.
.RE
.SH SEE ALSO
.B nwclient(5)
.SH CREDITS
nwauth was written by Volker Lendecke (lendecke@math.uni-goettingen.de)

85
man/nwfstime.1 Normal file
View File

@@ -0,0 +1,85 @@
.TH NWFSTIME 1 12/10/1996 nwfstime nwfstime
.SH NAME
nwfstime \- Display / Set a NetWare server's date and time
.SH SYNOPSIS
.B nwfstime
[
.B -h
] [
.B -S
.I server
] [
.B -U
.I user name
] [
.B -P
.I password
|
.B -n
] [
.B -C
] [
.B -s
]
.SH DESCRIPTION
.B nwfstime
displays a NetWare server's date and time. You can also set a NetWare
server's date and time from the local time.
.SH OPTIONS
.B -h
.RS 3
With -h nwfstime prints a little help text.
.RE
.B -S
.I server
.RS 3
is the name of the server you want to use.
.RE
.B -U
.I user
.RS 3
.B user
is the user name to use for login. To set the server's time, you need
supervisor privileges.
.RE
.B -P
.I password
.RS 3
.B password
is the password to use for login. If neither
.B -n
nor
.B -P
are given, and the user has no open connection to the server, nwfstime
prompts for a password.
.RE
.B -n
.RS 3
.B -n
should be given if no password is required for the login. As you need
supervisor privileges for setting the date and time, this option is
probably not used very often.
.RE
.B -C
.RS 3
By default, passwords are converted to uppercase before they are sent
to the server, because most servers require this. You can turn off
this conversion by
.B -C.
.RE
.B -s
.RS 3
With
.B -s,
nwfstime sets the file server's date and time according to the local
date and time.
.RE

36
man/nwsfind.1 Normal file
View File

@@ -0,0 +1,36 @@
.TH NWSFIND 1 10/27/1996 nwsfind nwsfind
.SH NAME
nwsfind \- Find a NetWare Server
.SH SYNOPSIS
.B nwsfind
[
.B -t
.I type
] [
.I name
]
.SH DESCRIPTION
.B nwsfind
searches for a NetWare server and finds a route to this
server. nwsfind was written to be setuid root. It is called from
within the ncp library, so that it is possible that normal users use
the utilities.
.SH OPTIONS
.B name
.RS 3
If you look for a specific server, you should give nwsfind this
argument. If you omit it, nwsfind looks for the server nearest to you.
.RE
.B -t
.I type
.RS 3
By default nwsfind looks for file servers. In case you want to look up
another server type, you have to specify its numerical type as
.B type.
.RE
.SH CREDITS
nwsfind was written by Volker Lendecke (lendecke@math.uni-goettingen.de)

View File

@@ -102,4 +102,4 @@ this conversion by
.B nwclient(5), nprint(1), slist(1), ncpmount(8), ncpumount(8)
.SH CREDITS
pqlist was written by Volker Lendecke (lendecke@namu01.gwdg.de)
pqlist was written by Volker Lendecke (lendecke@math.uni-goettingen.de)

View File

@@ -1,4 +1,4 @@
.TH PSERVER 1 02/10/1996 pserver pserver
.TH PSERVER 1 10/22/1996 pserver pserver
.SH NAME
pserver \- NetWare print server
.SH SYNOPSIS
@@ -101,6 +101,13 @@ process, and feeds the job file to stdin.
.I command
is the printing command that is executed for each job. The default
command is 'lpr'.
You can insert several flags into the command, preceded by %. These
are replaced with values retrieved from the queue structure for the
print job.
%u: This field will be replaced by the name of the user who posted
this print job.
.RE
.B -j
@@ -139,4 +146,4 @@ diagnostic messages that are printed when a error occurs.
.B nwclient(5), slist(1), pqlist(1), ncpmount(8), ncpumount(8)
.SH CREDITS
pserver was written by Volker Lendecke (lendecke@namu01.gwdg.de)
pserver was written by Volker Lendecke (lendecke@math.uni-goettingen.de)

View File

@@ -40,4 +40,4 @@ List all available Netware servers on your Network, that begin with an "I".
.B ncpmount(8), ncpumount(8), pqlist(1), nprint(1)
.SH CREDITS
slist was written by Volker Lendecke (lendecke@namu01.gwdg.de)
slist was written by Volker Lendecke (lendecke@math.uni-goettingen.de)

View File

@@ -1,7 +1,7 @@
Begin3
Title: ncpfs
Version: 2.0.6
Entered-date: 08. August 1996
Version: 2.0.8
Entered-date: 10. December 1996
Description: With ncpfs you can mount volumes of your netware
server under Linux. You can also print to netware
print queues and spool netware print queues to the
@@ -13,7 +13,7 @@ Author: lendecke@namu01.Num.Math.Uni-Goettingen.de (Volker Lendecke)
Maintained-by: lendecke@namu01.Num.Math.Uni-Goettingen.de (Volker Lendecke)
Primary-site: ftp.gwdg.de:/pub/linux/misc/ncpfs
Alternate-site: sunsite.unc.edu:/pub/Linux/system/Filesystems/ncpfs
~136k ncpfs-2.0.6.tgz
~ 1k ncpfs-2.0.6.lsm
~156k ncpfs-2.0.8.tgz
~ 1k ncpfs-2.0.8.lsm
Copying-policy: GPL
End

42
sutil/Makefile Normal file
View File

@@ -0,0 +1,42 @@
#
# Makefile for the linux ncp-filesystem routines.
#
UTILS = ncpmount ncpumount nwsfind
CC = gcc
default:
make -C ..
all: $(UTILS)
install: all
for i in $(UTILS); \
do install $$i -m 4755 $(BINDIR); done
$(UTILS): %: %.o libncp.a
$(CC) -o $@ $(addsuffix .o,$@) -L. -lncp -L../lib -lcom_err
ncplib.o: ncplib.c ncplib.h
$(CC) $(CFLAGS) -finline-functions -c ncplib.c
libncp.a: ncplib.o ../lib/ncplib_err.o
ar r libncp.a ncplib.o ../lib/ncplib_err.o
dep:
$(CPP) -M $(INCLUDES) *.c > .depend
clean:
rm -f *.o *~ libncp.a $(UTILS)
mrproper: clean
rm -f .depend
#
# include a dependency file if one exists
#
ifeq (.depend,$(wildcard .depend))
include .depend
endif

93
sutil/ipxlib.h Normal file
View File

@@ -0,0 +1,93 @@
/*
* ipxlib.h
*
* Copyright (C) 1995 by Volker Lendecke
*
*/
#ifndef _IPXLIB_H
#define _IPXLIB_H
#include <linux/types.h>
#include <linux/ncp.h>
#include <linux/ncp_fs.h>
#include <linux/ipx.h>
#include <stdio.h>
typedef unsigned long IPXNet;
typedef unsigned short IPXPort;
typedef unsigned char IPXNode[IPX_NODE_LEN];
#define IPX_USER_PTYPE (0x00)
#define IPX_RIP_PTYPE (0x01)
#define IPX_SAP_PTYPE (0x04)
#define IPX_AUTO_PORT (0x0000)
#define IPX_SAP_PORT (0x0452)
#define IPX_RIP_PORT (0x0453)
#define IPX_SAP_GENERAL_QUERY (0x0001)
#define IPX_SAP_GENERAL_RESPONSE (0x0002)
#define IPX_SAP_NEAREST_QUERY (0x0003)
#define IPX_SAP_NEAREST_RESPONSE (0x0004)
#define IPX_SAP_FILE_SERVER (0x0004)
struct sap_query {
unsigned short query_type; /* net order */
unsigned short server_type; /* net order */
};
struct sap_server_ident {
unsigned short server_type __attribute__ ((packed));
char server_name[48] __attribute__ ((packed));
IPXNet server_network __attribute__ ((packed));
IPXNode server_node __attribute__ ((packed));
IPXPort server_port __attribute__ ((packed));
unsigned short intermediate_network __attribute__ ((packed));
};
#define IPX_RIP_REQUEST (0x1)
#define IPX_RIP_RESPONSE (0x2)
struct ipx_rip_packet {
__u16 operation __attribute__ ((packed));
struct ipx_rt_def {
__u32 network __attribute__ ((packed));
__u16 hops __attribute__ ((packed));
__u16 ticks __attribute__ ((packed));
} rt[1] __attribute__ ((packed));
};
#define IPX_BROADCAST_NODE ("\xff\xff\xff\xff\xff\xff")
#define IPX_THIS_NODE ("\0\0\0\0\0\0")
#define IPX_THIS_NET (0)
#ifndef IPX_NODE_LEN
#define IPX_NODE_LEN (6)
#endif
void
ipx_print_node(IPXNode node);
void
ipx_print_network(IPXNet net);
void
ipx_print_port(IPXPort port);
void
ipx_print_saddr(struct sockaddr_ipx* sipx);
void
ipx_fprint_node(FILE *file, IPXNode node);
void
ipx_fprint_network(FILE *file, IPXNet net);
void
ipx_fprint_port(FILE *file, IPXPort port);
void
ipx_fprint_saddr(FILE *file, struct sockaddr_ipx* sipx);
int
ipx_sscanf_node(char *buf, unsigned char node[IPX_NODE_LEN]);
void
ipx_assign_node(IPXNode dest, IPXNode src);
int
ipx_node_equal(IPXNode n1,IPXNode n2);
#endif /* _IPXLIB_H */

1927
sutil/ncplib.c Normal file

File diff suppressed because it is too large Load Diff

198
sutil/ncplib.h Normal file
View File

@@ -0,0 +1,198 @@
/*
* ncplib.h
*
* Copyright (C) 1995, 1996 by Volker Lendecke
*
*/
#ifndef _NCPLIB_H
#define _NCPLIB_H
#include <linux/types.h>
#include <linux/ncp.h>
#include <linux/ncp_fs.h>
#include <linux/ipx.h>
#include <sys/param.h>
#include <stdio.h>
#include <time.h>
#include "ipxlib.h"
#include "com_err.h"
#ifndef memzero
#include <string.h>
#define memzero(object) memset(&(object), 0, sizeof(object))
#endif
void
str_upper(char *name);
enum connect_state {
NOT_CONNECTED = 0,
CONN_PERMANENT,
CONN_TEMPORARY
};
struct ncp_conn {
enum connect_state is_connected;
char server[NCP_BINDERY_NAME_LEN];
char user [NCP_BINDERY_NAME_LEN];
struct ncp_fs_info i;
/* Fields for use with permanent connections */
int mount_fid;
char mount_point[MAXPATHLEN];
/* Fields for use with temporary connections */
int ncp_sock;
int wdog_sock;
int wdog_pid;
__u8 sequence;
int completion;
int conn_status;
int reply_size;
/* Fields used to setup ncp requests */
int current_size;
int has_subfunction;
int verbose;
int ncp_reply_size;
int lock;
char packet[NCP_PACKET_SIZE];
};
struct ncp_conn_spec {
char server[NCP_BINDERY_NAME_LEN];
char user[NCP_BINDERY_NAME_LEN];
uid_t uid;
int login_type; /* NCP_BINDERY_USER / NCP_BINDERY_PSERVER */
char password[NCP_BINDERY_NAME_LEN];
};
struct ncp_property_info {
__u8 property_name[16];
__u8 property_flags;
__u8 property_security;
__u32 search_instance;
__u8 value_available_flag;
__u8 more_properties_flag;
};
/* ncp_initialize is the main entry point for user programs which want
to connect to a NetWare Server. It looks for -S, -U, -P and -n in
the argument list, opens the connection and removes the arguments
from the list. It was designed after the X Windows init
functions. */
struct ncp_conn *
ncp_initialize(int *argc, char **argv,
int login_necessary, long *err);
/* You can login as another object by this procedure. As a first use
pserver comes to mind. */
struct ncp_conn *
ncp_initialize_as(int *argc, char **argv,
int login_necessary, int login_type, long *err);
/* Open a connection */
struct ncp_conn *
ncp_open(struct ncp_conn_spec *spec, long *err);
/* Open a connection on an existing mount point */
struct ncp_conn *
ncp_open_mount(const char *mount_point, long *err);
/* Find a permanent connection that fits the spec, return NULL if
* there is none. */
char *
ncp_find_permanent(const struct ncp_conn_spec *spec);
/* Find the address of a file server */
struct sockaddr_ipx *
ncp_find_fileserver(char *server_name, long *err);
/* Find the address of a server */
struct sockaddr_ipx *
ncp_find_server(char **server_name, int type, long *err);
/* Detach from a permanent connection or destroy a temporary
connection */
long
ncp_close(struct ncp_conn *conn);
/* like getmntent, get_ncp_conn_ent scans /etc/mtab for usable
connections */
struct ncp_conn_ent {
char server[NCP_BINDERY_NAME_LEN];
char user[NCP_BINDERY_NAME_LEN];
uid_t uid;
char mount_point[MAXPATHLEN];
};
struct ncp_conn_ent *
ncp_get_conn_ent(FILE *filep);
#define NWCLIENT (".nwclient")
#define NWC_NOPASSWORD ("-")
/* find an appropriate connection */
struct ncp_conn_spec *
ncp_find_conn_spec(const char *server, const char *user, const char *password,
int login_necessary, uid_t uid, long *err);
long
ncp_get_encryption_key(struct ncp_conn *conn,
char *target);
struct ncp_station_addr {
__u32 NetWork __attribute__ ((packed));
__u8 Node[6] __attribute__ ((packed));
__u16 Socket __attribute__ ((packed));
};
struct ncp_prop_login_control {
__u8 AccountExpireDate[3] __attribute__ ((packed));
__u8 Disabled __attribute__ ((packed));
__u8 PasswordExpireDate[3] __attribute__ ((packed));
__u8 GraceLogins __attribute__ ((packed));
__u16 PasswordExpireInterval __attribute__ ((packed));
__u8 MaxGraceLogins __attribute__ ((packed));
__u8 MinPasswordLength __attribute__ ((packed));
__u16 MaxConnections __attribute__ ((packed));
__u8 ConnectionTimeMask[42] __attribute__ ((packed));
__u8 LastLogin[6] __attribute__ ((packed));
__u8 RestrictionMask __attribute__ ((packed));
__u8 reserved __attribute__ ((packed));
__u32 MaxDiskUsage __attribute__ ((packed));
__u16 BadLoginCount __attribute__ ((packed));
__u32 BadLoginCountDown __attribute__ ((packed));
struct ncp_station_addr LastIntruder __attribute__ ((packed));
};
long
ncp_read_property_value(struct ncp_conn *conn,
int object_type, const char *object_name,
int segment, const char *prop_name,
struct nw_property *target);
#define NCP_GRACE_PERIOD (0xdf)
long
ncp_get_bindery_object_id(struct ncp_conn *conn,
__u16 object_type,
const char *object_name,
struct ncp_bindery_object *target);
long
ncp_login_user(struct ncp_conn *conn,
const unsigned char *username,
const unsigned char *password);
#endif /* _NCPLIB_H */

View File

@@ -86,6 +86,11 @@ canonicalize (const char *path)
if (realpath (path, canonical))
return canonical;
if (strlen(path) > PATH_MAX)
{
return NULL;
}
strcpy (canonical, path);
return canonical;
}
@@ -116,7 +121,15 @@ main(int argc, char *argv[])
mount_point = canonicalize(argv[1]);
if (mount_point == NULL)
{
fprintf(stderr, "Invalid mount point: %s\n", argv[1]);
exit(1);
}
if (umount_ok(mount_point) != 0) {
fprintf(stderr, "You are not allowed to umount %s\n",
mount_point);
exit(1);
}

209
sutil/nwcrypt.c Normal file
View File

@@ -0,0 +1,209 @@
/*$*********************************************************
$*
$* This code has been taken from DDJ 11/93, from an
$* article by Pawel Szczerbina.
$*
$* Password encryption routines follow.
$* Converted to C from Barry Nance's Pascal
$* prog published in the March -93 issue of Byte.
$*
$* Adapted to be useable for ncpfs by
$* Volker Lendecke <lendecke@namu01.gwdg.de> in
$* October 1995.
$*
$**********************************************************/
/****************************************************************************
I read that Novell is not very open when it comes to technical details
of the Netware Core Protocol. This might be especially true for the
encryption stuff. I took the necessary code from Dr. Dobb's Journal
11/93, Undocumented Corner. I asked Jon Erickson <jon@ddj.com> about
the legal status of this piece of code:
---
Date: Thu, 12 Oct 1995 13:44:18 +0100
From: Volker Lendecke <lendecke>
To: jon@ddj.com
Subject: legal status of your source code?
Hello!
I hope that you're the right one to write to, you are the first on your WWW
server. If you are not, could you please forward this message to the right
person? Thanks.
I'm currently exploring the possibility to write a free (in the GNU GPL
sense) NCP filesystem, which would allow me to access a novell server
transparently. For that I would like to use the encryption functions you
published in DDJ 11/93, Undocumented Corner. I would make some cosmetic
changes, such as other indentations, minor code changes and so on. But I do
not know if that allows me to publish this code under GPL. One alternative
would be to publish a diff against your listing, but that would probably
contain much of your code as well, and it would be very inconvenient for
the average user.
I think that you have some kind of standard procedure for such a
case. Please tell me what I should do.
Many thanks in advance,
Volker
+=================================================================+
! Volker Lendecke Internet: lendecke@namu01.gwdg.de !
! D-37081 Goettingen, Germany !
+=================================================================+
--
I got the following answer:
---
From: Jon Erickson <jon@ddj.com>
X-Mailer: SCO System V Mail (version 3.2)
To: lendecke@namu01.gwdg.de
Subject: Re: legal status of your source code?
Date: Thu, 12 Oct 95 5:42:56 PDT
Volker,
Code from Dr. Dobb's Journal related articles is provided for
anyone to use. Clearly, the author of the article should be
given credit.
Jon Erickson
---
With this answer in mind, I took the code and made it a bit more
C-like. The original seemed to be translated by a mechanical pascal->c
translator. Jon's answer encouraged me to publish nwcrypt.c under the
GPL. If anybody who knows more about copyright and sees any problems
with this, please tell me.
****************************************************************************/
/******************* Data types ***************************/
typedef unsigned char buf32[32];
typedef unsigned char buf16[16];
typedef unsigned char buf8[8];
typedef unsigned char buf4[4];
static unsigned char encrypttable[256] =
{0x7,0x8,0x0,0x8,0x6,0x4,0xE,0x4,0x5,0xC,0x1,0x7,0xB,0xF,0xA,0x8,
0xF,0x8,0xC,0xC,0x9,0x4,0x1,0xE,0x4,0x6,0x2,0x4,0x0,0xA,0xB,0x9,
0x2,0xF,0xB,0x1,0xD,0x2,0x1,0x9,0x5,0xE,0x7,0x0,0x0,0x2,0x6,0x6,
0x0,0x7,0x3,0x8,0x2,0x9,0x3,0xF,0x7,0xF,0xC,0xF,0x6,0x4,0xA,0x0,
0x2,0x3,0xA,0xB,0xD,0x8,0x3,0xA,0x1,0x7,0xC,0xF,0x1,0x8,0x9,0xD,
0x9,0x1,0x9,0x4,0xE,0x4,0xC,0x5,0x5,0xC,0x8,0xB,0x2,0x3,0x9,0xE,
0x7,0x7,0x6,0x9,0xE,0xF,0xC,0x8,0xD,0x1,0xA,0x6,0xE,0xD,0x0,0x7,
0x7,0xA,0x0,0x1,0xF,0x5,0x4,0xB,0x7,0xB,0xE,0xC,0x9,0x5,0xD,0x1,
0xB,0xD,0x1,0x3,0x5,0xD,0xE,0x6,0x3,0x0,0xB,0xB,0xF,0x3,0x6,0x4,
0x9,0xD,0xA,0x3,0x1,0x4,0x9,0x4,0x8,0x3,0xB,0xE,0x5,0x0,0x5,0x2,
0xC,0xB,0xD,0x5,0xD,0x5,0xD,0x2,0xD,0x9,0xA,0xC,0xA,0x0,0xB,0x3,
0x5,0x3,0x6,0x9,0x5,0x1,0xE,0xE,0x0,0xE,0x8,0x2,0xD,0x2,0x2,0x0,
0x4,0xF,0x8,0x5,0x9,0x6,0x8,0x6,0xB,0xA,0xB,0xF,0x0,0x7,0x2,0x8,
0xC,0x7,0x3,0xA,0x1,0x4,0x2,0x5,0xF,0x7,0xA,0xC,0xE,0x5,0x9,0x3,
0xE,0x7,0x1,0x2,0xE,0x1,0xF,0x4,0xA,0x6,0xC,0x6,0xF,0x4,0x3,0x0,
0xC,0x0,0x3,0x6,0xF,0x8,0x7,0xB,0x2,0xD,0xC,0x6,0xA,0xA,0x8,0xD};
static buf32 encryptkeys =
{0x48,0x93,0x46,0x67,0x98,0x3D,0xE6,0x8D,
0xB7,0x10,0x7A,0x26,0x5A,0xB9,0xB1,0x35,
0x6B,0x0F,0xD5,0x70,0xAE,0xFB,0xAD,0x11,
0xF4,0x47,0xDC,0xA7,0xEC,0xCF,0x50,0xC0};
static void
shuffle1(buf32 temp, unsigned char *target)
{
short b4;
unsigned char b3;
int s, b2, i;
b4 = 0;
for (b2 = 0; b2 <= 1; ++b2)
{
for (s = 0; s <= 31; ++s)
{
b3 = (temp[s]+b4) ^ (temp[(s+b4)&31] - encryptkeys[s]);
b4 = b4 + b3;
temp[s] = b3;
}
}
for (i = 0; i <= 15; ++i) {
target[i] = encrypttable[temp[ 2*i ]]
| (encrypttable[temp[ 2*i + 1]] << 4);
}
}
static void
shuffle(const unsigned char *lon, const unsigned char *buf, int buflen,
unsigned char *target)
{
int b2, d, s;
buf32 temp;
while ( (buflen > 0)
&& (buf[buflen - 1] == 0)) {
buflen = buflen - 1;
}
for (s = 0; s < 32; s++) {
temp[s] = 0;
}
d = 0;
while (buflen >= 32)
{
for (s = 0; s <= 31; ++s)
{
temp[s] = temp[s] ^ buf[d];
d = d + 1;
}
buflen = buflen - 32;
}
b2 = d;
if (buflen > 0)
{
for (s = 0; s <= 31; ++s)
{
if (d + buflen == b2)
{
b2 = d;
temp[s] = temp[s] ^ encryptkeys[s];
} else {
temp[s] = temp[s] ^ buf[b2];
b2 = b2 + 1;
}
}
}
for (s = 0; s <= 31; ++s)
temp[s] = temp[s] ^ lon[s & 3];
shuffle1(temp,target);
}
static void
nw_encrypt(const unsigned char *fra,
const unsigned char *buf,
unsigned char *til)
{
buf32 k;
int s;
shuffle(&(fra[0]), buf, 16, &(k[ 0]));
shuffle(&(fra[4]), buf, 16, &(k[16]));
for (s = 0; s <= 15; ++s)
k[s] = k[s] ^ k[31 - s];
for (s = 0; s <= 7; ++s)
til[s] = k[s] ^ k[15 - s];
}

102
sutil/nwsfind.c Normal file
View File

@@ -0,0 +1,102 @@
/*
* nwsfind.c
*
* Find a NetWare server and open a route to it.
* This tool can safely be setuid root, if normal users should be able to
* access any NetWare server.
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [server]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [server]\n", progname);
printf("\n"
"-t Server type, default: File server\n"
"-h Print this help text\n"
"\n");
}
static void
swallow_error(const char * name, long code, const char *format, va_list arg)
{
printf("%s ", error_message(code));
vfprintf(stdout, format, arg);
putchar('\n');
return;
}
int
main(int argc, char *argv[])
{
char *server = NULL;
int object_type = NCP_BINDERY_FSERVER;
struct sockaddr_ipx *result;
long err;
int opt;
progname = argv[0];
set_com_err_hook(swallow_error);
while ((opt = getopt(argc, argv, "t:")) != EOF)
{
switch(opt) {
case 't':
object_type = atoi(optarg);
break;
case 'h':
case '?':
help();
exit(1);
default:
usage();
exit(1);
}
}
if (optind < argc-1)
{
usage();
exit(1);
}
if (optind == argc-1)
{
server = argv[optind];
if (strlen(server) >= NCP_BINDERY_NAME_LEN)
{
com_err(argv[0], ENAMETOOLONG, "server name too long");
exit(1);
}
}
result = ncp_find_server(&server, object_type, &err);
if (result == NULL)
{
com_err(argv[0], err, "when trying to find server");
exit(1);
}
ipx_print_saddr(result);
printf(" %s\n", server);
return 0;
}

View File

@@ -5,30 +5,19 @@
USERUTILS = slist pqlist nwfsinfo pserver nprint nsend ncopy nwpasswd
USERUTILS += nwbols nwbocreate nwborm nwboprops
USERUTILS += nwbpcreate nwbprm nwbpvalues nwbpadd nwbpset
USERUTILS += nwgrant nwrevoke nwuserlist nwrights
UIDUTILS = ncpmount ncpumount
USERUTILS += nwgrant nwrevoke nwuserlist nwrights nwauth
USERUTILS += nwfstime
SBINUTILS = nwmsg
UTIL_EXECS = $(USERUTILS) $(UIDUTILS) $(SBINUTILS)
UTILS = $(addprefix $(INTERM_BINDIR)/,$(UTIL_EXECS))
UTILS = $(USERUTILS) $(SBINUTILS) ncptest
CFLAGS = -Wall $(INCLUDES) $(KERNELD) -DNCPFS_VERSION=\"$(VERSION)\"
CC = gcc
#CFLAGS += -g
CFLAGS += -O2
ifeq ($(HAVE_ELF),yes)
PIC_FLAG = -fPIC
NCP_LIB = libncp.so.1.0
LIB_LINK_COMMAND = gcc -shared -Wl,-soname,libncp.so.1 -o $(NCP_LIB)
INSTALL_LIB = install $(NCP_LIB) -m 755 /lib; \
ln -sf $(NCP_LIB) /lib/libncp.so.1; \
ldconfig
export PIC_FLAG
else
NCP_LIB = libncp.a
LIB_LINK_COMMAND = ar r libncp.a
LIBDEP = ../lib/libncp.a
endif
default:
@@ -37,59 +26,22 @@ default:
all: $(UTILS) ncptest
install: all
for i in $(UTIL_EXECS); \
do install $(INTERM_BINDIR)/$$i -m 755 $(BINDIR); done
for i in $(UIDUTILS); \
do install $(INTERM_BINDIR)/$$i -m 4755 $(BINDIR); done
for i in $(USERUTILS); \
do install $$i -m 755 $(BINDIR); done
for i in $(SBINUTILS); \
do install $(INTERM_BINDIR)/$$i -m 755 $(SBINDIR); done
$(INSTALL_LIB)
do install $$i -m 755 $(SBINDIR); done
$(UTILS): $(addsuffix .o,$(UTIL_EXECS)) $(NCP_LIB)
$(CC) -o $@ $(addsuffix .o,$(notdir $@)) -L. -lncp
$(UTILS): %: %.o $(LIBDEP)
$(CC) -o $@ $(addsuffix .o,$@) -L../lib -lncp
ncplib.o: ncplib.c ncplib.h ncplib_err.h
$(CC) $(CFLAGS) $(PIC_FLAG) -finline-functions -c ncplib.c
COM_ERR_CFILES = com_err/com_err.c com_err/error_message.c com_err/et_name.c \
com_err/init_et.c
$(NCP_LIB): ncplib.o ncplib_err.o $(COM_ERR_CFILES)
make -C com_err
$(LIB_LINK_COMMAND) ncplib.o ncplib_err.o \
com_err/com_err.o com_err/error_message.o com_err/et_name.o \
com_err/init_et.o
ln -sf libncp.so.1.0 libncp.so.1
ln -sf libncp.so.1 libncp.so
export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
ncplib_err.o: ncplib_err.h ncplib_err.c
$(CC) $(CFLAGS) $(PIC_FLAG) -c ncplib_err.c
ncplib_err.h: ncplib_err.et
com_err/compile_et ncplib_err
ncplib_err.c: ncplib_err.et
com_err/compile_et ncplib_err
test: test.o ncplib.o
$(CC) -o test test.o ncplib.o
ncptest: ncptest.o $(NCP_LIB)
$(CC) -o ncptest ncptest.o -L. -lncp
dep: ncplib_err.h
make -C com_err dep
dep:
$(CPP) -M $(INCLUDES) *.c > .depend
clean:
make -C com_err clean
rm -f *.o *~ slist test ncptest ncplib_err.[ch]
rm -f libncp.*
rm -f *.o *~ $(UTILS)
mrproper: clean
make -C com_err mrproper
rm -f $(UTILS) .depend $(DISTFILE)
rm -f .depend
#
# include a dependency file if one exists

View File

@@ -1 +0,0 @@
com_err/com_err.h

127
util/nwauth.c Normal file
View File

@@ -0,0 +1,127 @@
/*
* nwauth.c
*
* Check a user/passwd against a NetWare server
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include "ncplib.h"
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [options]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-t type Object type (decimal value)\n"
"\n");
}
static void
swallow_error(const char * s, long x, const char *t, va_list arg)
{
return;
}
int
main(int argc, char *argv[])
{
struct ncp_conn_spec *spec;
struct ncp_conn *conn;
char *server = NULL;
char *object_name = NULL;
int object_type = NCP_BINDERY_USER;
long err;
char *str;
int opt;
progname = argv[0];
if (!isatty(0))
{
set_com_err_hook(swallow_error);
}
while ((opt = getopt(argc, argv, "h?S:U:t:")) != EOF)
{
switch(opt) {
case 'S':
server = optarg;
break;
case 'U':
object_name = optarg;
break;
case 't':
object_type = atoi(optarg);
break;
case 'h':
case '?':
help();
exit(1);
default:
usage();
exit(1);
}
}
spec = ncp_find_conn_spec(server, object_name, "",
1, getuid(), &err);
if (spec == NULL)
{
com_err(argv[0], err, "when trying to find server");
exit(1);
}
if (ncp_find_fileserver(spec->server, &err) == NULL)
{
com_err(argv[0], err, "when trying to find server");
exit(1);
}
spec->login_type = object_type;
memset(spec->password, 0, sizeof(spec->password));
if (isatty(0))
{
str = getpass("Enter password: ");
if (strlen(str) >= sizeof(spec->password))
{
printf("Password too long\n");
exit(1);
}
strcpy(spec->password, str);
}
else
{
fgets(spec->password, sizeof(spec->password), stdin);
}
str_upper(spec->password);
if ((conn = ncp_open(spec, &err)) == NULL)
{
com_err(argv[0], err, "when trying to open connection");
exit(1);
}
ncp_close(conn);
return 0;
}

98
util/nwfstime.c Normal file
View File

@@ -0,0 +1,98 @@
/*
* nwfstime.c
*
* get/set a file server's time
*
* Copyright (C) 1996 by Volker Lendecke
*
*/
#include <stdio.h>
#include <unistd.h>
#include "ncplib.h"
static char *progname;
static void
usage(void)
{
fprintf(stderr, "usage: %s [pattern]\n", progname);
}
static void
help(void)
{
printf("\n");
printf("usage: %s [options]\n", progname);
printf("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-U username Username sent to server\n"
"-P password Use this password\n"
"-n Do not use any password\n"
"-C Don't convert password to uppercase\n"
"\n"
"-s Set file server's time from local time\n"
"\n");
}
int
main(int argc, char **argv)
{
struct ncp_conn *conn;
int opt;
long err;
int set = 0;
time_t t;
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, "when initializing");
return 1;
}
while ((opt = getopt(argc, argv, "h?s")) != EOF)
{
switch(opt)
{
case 'h':
case '?':
help();
break;
case 's':
set = 1;
break;
default:
usage();
goto finished;
}
}
finished:
if (set != 0)
{
time(&t);
if ((err = ncp_set_file_server_time(conn, &t)) != 0)
{
com_err(argv[0], err, "when setting file server time");
ncp_close(conn);
return 1;
}
}
else
{
if ((err = ncp_get_file_server_time(conn, &t)) != 0)
{
com_err(argv[0], err, "when getting file server time");
ncp_close(conn);
return 1;
}
fputs(ctime(&t), stdout);
}
ncp_close(conn);
return 0;
}

View File

@@ -260,6 +260,70 @@ init_queue(struct ncp_conn *conn, char *queue_name, char *command,
}
void
build_command(struct nw_queue *q, struct queue_job *j,
char *target, int target_size)
{
char *s = q->command;
char *target_end = target+target_size;
void add_string(char *s)
{
int len = strlen(s);
if (target + len + 1 > target_end)
{
len = target_end - target - 1;
}
strncpy(target, s, len);
target += len;
}
memset(target, 0, target_size);
while ((*s != 0) && (target < target_end))
{
if (*s != '%')
{
*target = *s;
target += 1;
s += 1;
continue;
}
switch (*(s+1))
{
case '%':
*target = '%';
target += 1;
case 'u':
{
char *user;
struct ncp_bindery_object u;
if (ncp_get_bindery_object_name
(q->conn, j->j.ClientObjectID, &u)
== 0)
{
user = u.object_name;
}
else
{
user = "*UNKNOWN USER*";
}
add_string(user);
}
default:
*target = '%';
*(target+1) = *(s+1);
target += 2;
}
s += 2;
}
}
static int
poll_queue(struct nw_queue *q)
{
@@ -316,6 +380,8 @@ poll_queue(struct nw_queue *q)
{
/* child */
char command[2048];
close(fd[1]); /* close write end */
if (fd[0] != STDIN_FILENO)
@@ -329,7 +395,9 @@ poll_queue(struct nw_queue *q)
close(fd[0]);
}
execl("/bin/sh", "sh", "-c", q->command, NULL);
build_command(q, &job, command, sizeof(command));
execl("/bin/sh", "sh", "-c", command, NULL);
syslog(LOG_ERR, "exec error: %m\n");
close(fd[0]);
exit(1);