diff --git a/.downloads/ncpfs-0.2.tgz b/.downloads/ncpfs-0.2.tgz new file mode 100644 index 0000000..0bce85f Binary files /dev/null and b/.downloads/ncpfs-0.2.tgz differ diff --git a/Changes b/Changes new file mode 100644 index 0000000..c9af799 --- /dev/null +++ b/Changes @@ -0,0 +1,6 @@ +ncpfs-0.1 -> ncpfs-0.2 + +- should be compileable with gcc other than 2.7.0 +- first attempt at read/write access +- more complete ncpmount.c +- included file ipx.tar \ No newline at end of file diff --git a/Makefile b/Makefile index a37b865..f41c49e 100644 --- a/Makefile +++ b/Makefile @@ -6,8 +6,8 @@ INCLUDES = -I/usr/src/linux/include CFLAGS = -Wall -Wstrict-prototypes -O2 -DMODULE -fomit-frame-pointer \ $(INCLUDES) \ + -DDEBUG_NCP_MALLOC # -DDEBUG_NCP=1 -DDEBUG_NCP_MALLOC -# -DDEBUG_NCP_MALLOC CC = gcc -D__KERNEL__ -I. AS = as @@ -22,26 +22,29 @@ ARCH = i386 OBJS= inode.o dir.o file.o sock.o ioctl.o ncplib.o nwcrypt.o -all: ncpfs.o ncpmount +all: ncpfs.o ncpmount ncptest ncpfs.o: $(OBJS) $(LD) -r -o ncpfs.o $(OBJS) -ncpmount: ncpmount.o +ncpmount: ncpmount.o gcc -o ncpmount ncpmount.o ncpmount.o: ncpmount.c gcc -c ncpmount.c -Wall -I. -g +ncptest: ncptest.o ncplib_user.o nwcrypt.o + gcc -o ncptest ncptest.o ncplib_user.o nwcrypt.o + +ncptest.o: ncptest.c + gcc -c ncptest.c -Wall -I. -g + ncplib_user.o: ncplib.o gcc -c ncplib.c -Wall -I. -g -o ncplib_user.o nwcrypt.o: nwcrypt.c gcc -c -O2 -Wall nwcrypt.c -ncpumount: ncpumount.o - gcc -o ncpumount ncpumount.o - dep: $(CPP) -M $(INCLUDES) *.c > .depend @@ -49,7 +52,7 @@ clean: rm -f *.o *~ realclean: clean - rm -fr ncpmount ncpumount .depend $(DISTFILE) mnt + rm -fr ncpmount ncptest .depend $(DISTFILE) mnt modules: ncpfs.o diff --git a/README b/README index e584f28..ffdb0cb 100644 --- a/README +++ b/README @@ -1,90 +1,47 @@ -This is version 0.1 of ncpfs, a free NetWare client for Linux. For me -it works with 1.3.32 and 1.3.35. +This is version 0.2 of ncpfs, a free NetWare client for Linux. For me +it works with 1.3.32 -I know that this piece of software is VERY incomplete, as it only -gives you read-only access. I have to apologize for that. But I -thought I should make it publically available, because I have tried to -ask several people about the legal status of the code. I did not get -very satisfying answers. So I publish ncpfs to open it for -criticism. If nobody complains, I will go on working. +I know that this piece of software is VERY incomplete, I have to +apologize for that. But I thought I should make it publically +available, because I have tried to ask several people about the legal +status of the code. I did not get very satisfying answers. So I publish +ncpfs to open it for criticism. If nobody complains, I will go on +working. -To install ncpfs, just type 'make', 'insmod ncpfs.o' and -'ncpmount server mount-point user password'. Please note that your IPX -system has to be configured correctly. There has to be a route to the -internal network of your server. I use tools from the dosemu-0.60.3 -distribution to do this. Once again I have to apologize for this -cryptic description, but before I'm sure that I'm allowed to do all -this I will not do more. +To install ncpfs, just type 'make', 'insmod ncpfs.o' and then +'ncpmount server mount-point'. Please note that your IPX system has to +be configured correctly. There has to be a route to the internal +network of your server. Please see the file start_ipx for an example. +I use tools written by Greg Page, Caldera. I hope I did not do too +much harm to their business. For your convenience I included the file +ipx.tar made available by Caldera. -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 about -the legal status of this piece of code: - - ---- -Date: Thu, 12 Oct 1995 13:44:18 +0100 -From: Volker 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 -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. +For the curious: the file ncplib.c is usable from user space as well! +Look at the file ncptest.c for a possible use. I use ncptest to check +my assumptions about the widely undocumented NetWare Core +Protocol. Maybe this is the beginning of a free NetWare API for Linux! +I would be happy to receive your comments on this. +LIMITATIONS (compare these with smbfs :-)) +The limitations ncpfs has are the natural limitations of the NCP +protocol, which was designed with MS-DOS based PCs in mind. The first +limitation is the lack of uid, gid and permission information per +file. You have to assign those values once for a complete mounted +directory. +The second limitation is just as annoying as the first: You cannot +re-export a ncp-mounted directory by nfs. It is not possible because +the NFS protocol defines access to files through unique file handles, +which can be mapped to the device and inode numbers in unix NFS +servers. NCP does not have unique numbers per file, you only have the +path name. I implemented a caching scheme for inode numbers, which +gives unique inode numbers for every open file in the system. This is +just sufficient for local use of the files, because you can tell when +an inode number can be discarded. With NFS the situation is +different. You can never know when the client will access the file-id +you offered, so you would have to cache the inode numbers +indefinitely long. I think this should not be done in kernel mode, as +it would require an unlimited amount of RAM. diff --git a/dir.c b/dir.c index 2a1c611..6b9ee20 100644 --- a/dir.c +++ b/dir.c @@ -1,4 +1,4 @@ - /* +/* * dir.c * * Copyright (C) 1995 by Volker Lendecke @@ -60,6 +60,23 @@ static int ncp_lookup(struct inode *dir, const char *__name, int len, struct inode **result); +static int +ncp_create(struct inode *dir, const char *name, int len, int mode, + struct inode **result); + +static int +ncp_mkdir(struct inode *dir, const char *name, int len, int mode); + +static int +ncp_rmdir(struct inode *dir, const char *name, int len); + +static int +ncp_unlink(struct inode *dir, const char *name, int len); + +static int +ncp_rename(struct inode *old_dir, const char *old_name, int old_len, + struct inode *new_dir, const char *new_name, int new_len); + static int date_dos2unix(unsigned short time,unsigned short date); @@ -103,15 +120,15 @@ static struct file_operations ncp_dir_operations = { struct inode_operations ncp_dir_inode_operations = { &ncp_dir_operations, /* default directory file ops */ - NULL, /* create */ + ncp_create, /* create */ ncp_lookup, /* lookup */ NULL, /* link */ - NULL, /* unlink */ + ncp_unlink, /* unlink */ NULL, /* symlink */ - NULL, /* mkdir */ - NULL, /* rmdir */ + ncp_mkdir, /* mkdir */ + ncp_rmdir, /* rmdir */ NULL, /* mknod */ - NULL, /* rename */ + ncp_rename, /* rename */ NULL, /* readlink */ NULL, /* follow_link */ NULL, /* bmap */ @@ -364,7 +381,6 @@ ncp_do_readdir(struct ncp_server *server, struct inode *dir, int fpos, date_dos2unix(0, finfo.creation_date); entry->atime = date_dos2unix(0, finfo.access_date); -; entry->size = (attr & aDIR) != 0 ? 1024 : finfo.file_length; entry->f_pos = total_count; @@ -437,7 +453,7 @@ get_pname_static(struct inode *dir, const char *name, int len, } #endif - DPRINTK("get_pname_static: parentname = %s, len = %d\n", + DDPRINTK("get_pname_static: parentname = %s, len = %d\n", parentname, parentlen); if (len > NCP_MAXNAMELEN) { @@ -458,16 +474,16 @@ get_pname_static(struct inode *dir, const char *name, int len, char *pos = strrchr(parentname, '\\'); if ( (pos == NULL) - && (parentlen == 0)) { + && ( (parentname[parentlen-1] == ':') + || (parentlen == 0))) { /* We're at the top */ - path[0] = '\\'; - path[1] = '\0'; - *res_len = 2; + path[0] = '\0'; + *res_len = 1; return 0; } - + if (pos == NULL) { printk("ncp_make_name: Bad parent NCP-name: %s", @@ -501,7 +517,7 @@ get_pname_static(struct inode *dir, const char *name, int len, *res_len = len; - DPRINTK("get_pname: path = %s, *pathlen = %d\n", + DDPRINTK("get_pname: path = %s, *pathlen = %d\n", path, *res_len); return 0; } @@ -845,10 +861,191 @@ ncp_lookup(struct inode *dir, const char *__name, int len, return 0; } +static int +ncp_create(struct inode *dir, const char *name, int len, int mode, + struct inode **result) +{ + int error; + char *path = NULL; + struct ncp_dirent entry; + struct ncp_file_info finfo; + struct ncp_dirent *ino_finfo; + *result = NULL; + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("ncp_create: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } -/* The following are taken directly from msdos-fs */ + /* Now we will have to build up an NCP filename. */ + if ((error = get_pname(dir, name, len, &path, &len)) < 0) { + iput(dir); + return error; + } + + if (ncp_create_newfile(NCP_SERVER(dir), 0, path, 0, &finfo) != 0) { + put_pname(path); + iput(dir); + return -EACCES; + } + + entry.attr = finfo.file_attributes; + entry.mtime = date_dos2unix(finfo.update_time, + finfo.update_date); + entry.ctime = date_dos2unix(0, finfo.creation_date); + entry.atime = date_dos2unix(0, finfo.access_date); + entry.size = 0; + + ncp_invalid_dir_cache(dir->i_ino); + + if (!(*result = ncp_iget(dir, path, &entry)) < 0) { + ncp_close_file(NCP_SERVER(dir), finfo.file_id); + put_pname(path); + iput(dir); + return error; + } + + ino_finfo = &(NCP_INOP(*result)->finfo); + ino_finfo->opened = 1; + ino_finfo->access = O_RDWR; + memcpy(&(ino_finfo->file_id), finfo.file_id, NCP_FILE_ID_LEN); + + iput(dir); + return 0; +} + +static int +ncp_mkdir(struct inode *dir, const char *name, int len, int mode) +{ + int error; + char path[NCP_MAXPATHLEN]; + + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("ncp_mkdir: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + + /* Now we will have to build up an NCP filename. */ + if ((error = get_pname_static(dir, name, len, path, &len)) < 0) { + iput(dir); + return error; + } + + if ((error = ncp_create_directory(NCP_SERVER(dir), 0, path, + 0xff)) == 0) { + ncp_invalid_dir_cache(dir->i_ino); + } + + iput(dir); + return error; +} + +static int +ncp_rmdir(struct inode *dir, const char *name, int len) +{ + int error; + char path[NCP_MAXPATHLEN]; + + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("ncp_rmdir: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if ((error = get_pname_static(dir, name, len, path, &len)) < 0) { + iput(dir); + return error; + } + if (ncp_find_inode(NCP_SERVER(dir), path) != NULL) { + error = -EBUSY; + } else { + if ((error = ncp_delete_directory(NCP_SERVER(dir), + 0, path)) == 0) { + ncp_invalid_dir_cache(dir->i_ino); + } + } + iput(dir); + return error; +} + +static int +ncp_unlink(struct inode *dir, const char *name, int len) +{ + int error; + char path[NCP_MAXPATHLEN]; + + if (!dir || !S_ISDIR(dir->i_mode)) { + printk("ncp_unlink: inode is NULL or not a directory\n"); + iput(dir); + return -ENOENT; + } + if ((error = get_pname_static(dir, name, len, path, &len)) < 0) { + iput(dir); + return error; + } + if (ncp_find_inode(NCP_SERVER(dir), path) != NULL) { + error = -EBUSY; + } else { + if ((error = ncp_erase_file(NCP_SERVER(dir), 0, path, + 0)) == 0) + ncp_invalid_dir_cache(dir->i_ino); + } + + iput(dir); + return error; +} + +static int +ncp_rename(struct inode *old_dir, const char *old_name, int old_len, + struct inode *new_dir, const char *new_name, int new_len) +{ + int res; + char old_path[NCP_MAXPATHLEN], new_path[NCP_MAXPATHLEN]; + + if (!old_dir || !S_ISDIR(old_dir->i_mode)) { + printk("ncp_rename: old inode is NULL or not a directory\n"); + res = -ENOENT; + goto finished; + } + + if (!new_dir || !S_ISDIR(new_dir->i_mode)) { + printk("ncp_rename: new inode is NULL or not a directory\n"); + res = -ENOENT; + goto finished; + } + + res = get_pname_static(old_dir, old_name, old_len, old_path, &old_len); + if (res < 0) { + goto finished; + } + + res = get_pname_static(new_dir, new_name, new_len, new_path, &new_len); + if (res < 0) { + goto finished; + } + + if ( (ncp_find_inode(NCP_SERVER(old_dir), old_path) != NULL) + || (ncp_find_inode(NCP_SERVER(new_dir), new_path) != NULL)) { + res = -EBUSY; + goto finished; + } + + res = ncp_rename_file(NCP_SERVER(old_dir), 0, old_path, 0,0, new_path); + + if (res == 0) { + ncp_invalid_dir_cache(old_dir->i_ino); + ncp_invalid_dir_cache(new_dir->i_ino); + } + + finished: + iput(old_dir); + iput(new_dir); + return res; +} + +/* The following routines are taken directly from msdos-fs */ /* Linear day numbers of the respective 1sts in non-leap years. */ diff --git a/file.c b/file.c index 581be2b..e582a2d 100644 --- a/file.c +++ b/file.c @@ -93,9 +93,6 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count) return -EINVAL; } - if ((errno = ncp_make_open(inode, O_RDONLY)) != 0) - return errno; - pos = file->f_pos; if (pos + count > inode->i_size) @@ -104,6 +101,9 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count) if (count <= 0) return 0; + if ((errno = ncp_make_open(inode, O_RDONLY)) != 0) + return errno; + bufsize = NCP_SERVER(inode)->buffer_size; already_read = 0; @@ -145,10 +145,85 @@ ncp_file_read(struct inode *inode, struct file *file, char *buf, int count) return already_read; } +static int +ncp_file_write(struct inode *inode, struct file *file, const char *buf, + int count) +{ + int bufsize, to_write, already_written; + off_t pos; + int errno; + + if (!inode) { + DPRINTK("ncp_file_write: inode = NULL\n"); + return -EINVAL; + } + + if (!S_ISREG(inode->i_mode)) { + DPRINTK("ncp_file_write: write to non-file, mode %07o\n", + inode->i_mode); + return -EINVAL; + } + + DPRINTK("ncp_file_write: enter %s\n", NCP_FINFO(inode)->path); + + if (count <= 0) + return 0; + + if ((errno = ncp_make_open(inode, O_RDWR)) != 0) + return errno; + + pos = file->f_pos; + + if (file->f_flags & O_APPEND) + pos = inode->i_size; + + bufsize = NCP_SERVER(inode)->buffer_size; + + already_written = 0; + + while (already_written < count) { + + int written_this_time; + + if ((pos % bufsize) != 0) { + to_write = bufsize - (pos % bufsize); + } else { + to_write = bufsize; + } + + to_write = min(to_write, count - already_written); + if (ncp_write(NCP_SERVER(inode), NCP_FINFO(inode)->file_id, + pos, to_write, buf, &written_this_time) != 0) { + return -EIO; + } + + pos += written_this_time; + buf += written_this_time; + already_written += written_this_time; + + if (written_this_time < to_write) { + break; + } + } + + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + inode->i_dirt = 1; + + file->f_pos = pos; + + if (pos > inode->i_size) { + inode->i_size = pos; + } + + DPRINTK("ncp_file_write: exit %s\n", NCP_FINFO(inode)->path); + + return already_written; +} + static struct file_operations ncp_file_operations = { NULL, /* lseek - default */ ncp_file_read, /* read */ - NULL, /* write */ + ncp_file_write, /* write */ NULL, /* readdir - bad */ NULL, /* select - default */ ncp_ioctl, /* ioctl */ diff --git a/inode.c b/inode.c index 0eeccf7..742158d 100644 --- a/inode.c +++ b/inode.c @@ -34,10 +34,11 @@ extern int close_fp(struct file *filp); static void ncp_put_inode(struct inode *); static void ncp_read_inode(struct inode *); static void ncp_put_super(struct super_block *); +static int ncp_notify_change(struct inode *inode, struct iattr *attr); static struct super_operations ncp_sops = { ncp_read_inode, /* read inode */ - NULL, /* notify change */ + ncp_notify_change, /* notify change */ NULL, /* write inode */ ncp_put_inode, /* put inode */ ncp_put_super, /* put superblock */ @@ -328,6 +329,58 @@ ncp_put_super(struct super_block *sb) MOD_DEC_USE_COUNT; } + +/* DO MORE */ +static int +ncp_notify_change(struct inode *inode, struct iattr *attr) +{ + int error = 0; + + if ((error = inode_change_ok(inode, attr)) < 0) + return error; + + if (((attr->ia_valid & ATTR_UID) && + (attr->ia_uid != NCP_SERVER(inode)->m.uid))) + return -EPERM; + + if (((attr->ia_valid & ATTR_GID) && + (attr->ia_uid != NCP_SERVER(inode)->m.gid))) + return -EPERM; + + if (((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & + ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)))) + return -EPERM; + + if ((attr->ia_valid & ATTR_SIZE) != 0) { + + struct ncp_file_info finfo; + struct ncp_dirent *dirent = NCP_FINFO(inode); + + DPRINTK("ncpfs: trying to change size of %s to %ld\n", + dirent->path, attr->ia_size); + + if (attr->ia_size != 0) { + return -EPERM; + } + + if (NCP_FINFO(inode)->opened != 0) { + ncp_close_file(NCP_SERVER(inode), dirent->file_id); + dirent->opened = 0; + } + + if (ncp_create_file(NCP_SERVER(inode), 0, + dirent->path, 0, &finfo) == 0) { + ncp_close_file(NCP_SERVER(inode), finfo.file_id); + dirent->opened = 0; + } + error = 0; + } + + ncp_invalid_dir_cache((unsigned long)(NCP_INOP(inode)->dir)); + + return error; +} #ifdef DEBUG_NCP_MALLOC int ncp_malloced; diff --git a/ipx.tar b/ipx.tar new file mode 100644 index 0000000..f4b1ecc Binary files /dev/null and b/ipx.tar differ diff --git a/ncp.h b/ncp.h index e07afbe..862d6af 100644 --- a/ncp.h +++ b/ncp.h @@ -18,28 +18,28 @@ #define NCP_DEALLOC_SLOT_REQUEST (0x5555) struct ncp_request_header { - __u16 type; - __u8 sequence; - __u8 conn_low; - __u8 task; - __u8 conn_high; - __u8 function; - __u8 data[0]; /* Depends upon request type */ -} __attribute__ ((packed)); + __u16 type __attribute__ ((packed)); + __u8 sequence __attribute__ ((packed)); + __u8 conn_low __attribute__ ((packed)); + __u8 task __attribute__ ((packed)); + __u8 conn_high __attribute__ ((packed)); + __u8 function __attribute__ ((packed)); + __u8 data[0] __attribute__ ((packed)); +}; #define NCP_REPLY (0x3333) #define NCP_POSITIVE_ACK (0x9999) struct ncp_reply_header { - __u16 type; - __u8 sequence; - __u8 conn_low; - __u8 task; - __u8 conn_high; - __u8 completion_code; - __u8 connection_state; - __u8 data[0]; /* Depends upon request type */ -} __attribute__ ((packed)); + __u16 type __attribute__ ((packed)); + __u8 sequence __attribute__ ((packed)); + __u8 conn_low __attribute__ ((packed)); + __u8 task __attribute__ ((packed)); + __u8 conn_high __attribute__ ((packed)); + __u8 completion_code __attribute__ ((packed)); + __u8 connection_state __attribute__ ((packed)); + __u8 data[0] __attribute__ ((packed)); +}; #define NCP_BINDERY_USER (0x0001) diff --git a/ncp_fs.h b/ncp_fs.h index ae1fdef..a8d4fdd 100644 --- a/ncp_fs.h +++ b/ncp_fs.h @@ -50,10 +50,10 @@ struct ncp_ioctl_request { #define NCP_SUPER_MAGIC 0x564c -#define NCP_SBP(sb) ((struct ncp_server *)(sb->u.generic_sbp)) -#define NCP_INOP(inode) ((struct ncp_inode_info *)(inode->u.generic_ip)) +#define NCP_SBP(sb) ((struct ncp_server *)((sb)->u.generic_sbp)) +#define NCP_INOP(inode) ((struct ncp_inode_info *)((inode)->u.generic_ip)) -#define NCP_SERVER(inode) NCP_SBP(inode->i_sb) +#define NCP_SERVER(inode) NCP_SBP((inode)->i_sb) #define NCP_FINFO(inode) (&(NCP_INOP(inode)->finfo)) static inline int min(int a, int b) { @@ -124,7 +124,6 @@ int ncp_ioctl (struct inode * inode, struct file * filp, /* linux/fs/ncpfs/inode.c */ struct super_block *ncp_read_super(struct super_block *sb, void *raw_data, int silent); -int ncp_notify_change(struct inode *inode, struct iattr *attr); void ncp_invalidate_connection(struct ncp_server *server); int ncp_conn_is_valid(struct ncp_server *server); diff --git a/ncpfs-0.1.lsm b/ncpfs-0.2.lsm similarity index 61% rename from ncpfs-0.1.lsm rename to ncpfs-0.2.lsm index d5b2072..e2559f8 100644 --- a/ncpfs-0.1.lsm +++ b/ncpfs-0.2.lsm @@ -1,14 +1,14 @@ Begin3 Title: ncpfs -Version: 0.1 +Version: 0.2 Entered-date: 19. October 1995 Description: With ncpfs you can mount volumes of your novell server under Linux. -Keywords: filesystem kernel ncp novell +Keywords: filesystem kernel ncp novell netware Author: lendecke@namu01.gwdg.de (Volker Lendecke) Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke) -Primary-site: linux01.gwdg.de:/pub/smbfs - ~30k ncpfs-0.1.tgz - ~ 1k ncpfs-0.1.lsm +Primary-site: linux01.gwdg.de:/pub/ncpfs + ~44k ncpfs-0.2.tgz + ~ 1k ncpfs-0.2.lsm Copying-policy: GPL End diff --git a/ncplib.c b/ncplib.c index a500fb7..d3c63e3 100644 --- a/ncplib.c +++ b/ncplib.c @@ -126,6 +126,19 @@ ncp_add_mem(struct ncp_server *server, const char *source, int size) return; } +#ifdef __KERNEL__ + +static void +ncp_add_mem_fromfs(struct ncp_server *server, const char *source, int size) +{ + assert_server_locked(server); + memcpy_fromfs(&(server->packet[server->current_size]), source, size); + server->current_size += size; + return; +} + +#endif + static void ncp_add_pstring(struct ncp_server *server, const char *s) { @@ -536,6 +549,176 @@ ncp_close_file(struct ncp_server *server, const char *file_id) return 0; } +static int +ncp_do_create(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target, + int function) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, dir_handle); + ncp_add_byte(server, attr); + ncp_add_pstring(server, path); + + if ((result = ncp_request(server, function)) != 0) { + ncp_printf("ncp_request_error: %d\n", result); + ncp_unlock_server(server); + return result; + } + + memcpy(&(target->file_id), ncp_reply_data(server, 0), + NCP_FILE_ID_LEN); + + memset(&(target->file_name), 0, sizeof(target->file_name)); + memcpy(&(target->file_name), ncp_reply_data(server, 8), + NCP_MAX_FILENAME); + + target->file_attributes = ncp_reply_byte(server, 22); + target->file_mode = ncp_reply_byte(server, 23); + target->file_length = ntohl(ncp_reply_dword(server, 24)); + target->creation_date = ntohs(ncp_reply_word(server, 28)); + target->access_date = ntohs(ncp_reply_word(server, 30)); + target->update_date = ntohs(ncp_reply_word(server, 32)); + target->update_time = ntohs(ncp_reply_word(server, 34)); + + ncp_unlock_server(server); + return 0; +} + +int +ncp_create_newfile(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target) +{ + return ncp_do_create(server, dir_handle, path, attr, target, 77); +} + +int +ncp_create_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target) +{ + return ncp_do_create(server, dir_handle, path, attr, target, 67); +} + +int +ncp_erase_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, dir_handle); + ncp_add_byte(server, attr); + ncp_add_pstring(server, path); + + if ((result = ncp_request(server, 68)) != 0) { + ncp_printf("ncp_request_error: %d\n", result); + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_rename_file(struct ncp_server *server, + int old_handle, const char *old_path, + int attr, + int new_handle, const char *new_path) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, old_handle); + ncp_add_byte(server, attr); + ncp_add_pstring(server, old_path); + ncp_add_byte(server, new_handle); + ncp_add_pstring(server, new_path); + + if ((result = ncp_request(server, 69)) != 0) { + ncp_printf("ncp_request_error: %d\n", result); + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_create_directory(struct ncp_server *server, + int dir_handle, const char *path, + int inherit_mask) +{ + int result; + + ncp_init_request_s(server, 10); + ncp_add_byte(server, dir_handle); + ncp_add_byte(server, inherit_mask); + ncp_add_pstring(server, path); + + if ((result = ncp_request(server, 22)) != 0) { + ncp_printf("ncp_request_error: %d\n", result); + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_delete_directory(struct ncp_server *server, + int dir_handle, const char *path) +{ + int result; + + ncp_init_request_s(server, 11); + ncp_add_byte(server, dir_handle); + ncp_add_byte(server, 0); /* reserved */ + ncp_add_pstring(server, path); + + if ((result = ncp_request(server, 22)) != 0) { + ncp_printf("ncp_request_error: %d\n", result); + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + +int +ncp_rename_directory(struct ncp_server *server, + int dir_handle, + const char *old_path, const char *new_path) +{ + int result; + + ncp_init_request_s(server, 15); + ncp_add_byte(server, dir_handle); + ncp_add_pstring(server, old_path); + ncp_add_pstring(server, new_path); + + if ((result = ncp_request(server, 22)) != 0) { + ncp_printf("ncp_request_error: %d\n", result); + ncp_unlock_server(server); + return result; + } + + ncp_unlock_server(server); + return 0; +} + + #ifndef __KERNEL__ int @@ -565,9 +748,35 @@ ncp_read(struct ncp_server *server, const char *file_id, return 0; } +int +ncp_write(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_dword(server, htonl(offset)); + ncp_add_word(server, htons(to_write)); + ncp_add_mem(server, source, to_write); + + if ((result = ncp_request(server, 73)) != 0) { + ncp_printf("ncp_request_error: %d\n", result); + ncp_unlock_server(server); + return result; + } + + *bytes_written = to_write; + + ncp_unlock_server(server); + return 0; +} + #else -/* We have to read into user space */ +/* We have to transfer to/from user space */ int ncp_read(struct ncp_server *server, const char *file_id, __u32 offset, __u16 to_read, @@ -595,4 +804,30 @@ ncp_read(struct ncp_server *server, const char *file_id, return 0; } +int +ncp_write(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written) +{ + int result; + + ncp_init_request(server); + ncp_add_byte(server, 0); + ncp_add_mem(server, file_id, 6); + ncp_add_dword(server, htonl(offset)); + ncp_add_word(server, htons(to_write)); + ncp_add_mem_fromfs(server, source, to_write); + + if ((result = ncp_request(server, 73)) != 0) { + ncp_printf("ncp_request_error: %d\n", result); + ncp_unlock_server(server); + return result; + } + + *bytes_written = to_write; + + ncp_unlock_server(server); + return 0; +} + #endif diff --git a/ncplib.h b/ncplib.h index 49797ba..65d954d 100644 --- a/ncplib.h +++ b/ncplib.h @@ -94,9 +94,51 @@ ncp_open_file(struct ncp_server *server, int ncp_close_file(struct ncp_server *server, const char *file_id); +int +ncp_create_newfile(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target); + +int +ncp_create_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr, + struct ncp_file_info *target); + +int +ncp_erase_file(struct ncp_server *server, + int dir_handle, const char *path, + int attr); + +int +ncp_rename_file(struct ncp_server *server, + int old_handle, const char *old_path, + int attr, + int new_handle, const char *new_path); + +int +ncp_create_directory(struct ncp_server *server, + int dir_handle, const char *path, + int inherit_mask); + +int +ncp_delete_directory(struct ncp_server *server, + int dir_handle, const char *path); + +int +ncp_rename_directory(struct ncp_server *server, + int dir_handle, + const char *old_path, const char *new_path); + int ncp_read(struct ncp_server *server, const char *file_id, - __u32 start, __u16 to_read, + __u32 offset, __u16 to_read, char *target, int *bytes_read); +int +ncp_write(struct ncp_server *server, const char *file_id, + __u32 offset, __u16 to_write, + const char *source, int *bytes_written); + #endif /* _NCPLIB_H */ diff --git a/ncpmount.c b/ncpmount.c index 2bb6be9..7922945 100644 --- a/ncpmount.c +++ b/ncpmount.c @@ -15,13 +15,11 @@ #include #include #include -#include -#include #include -#include /* #include */ /* generates a warning here */ extern pid_t waitpid(pid_t, int *, int); #include +#include #include #include #include @@ -38,8 +36,54 @@ extern pid_t waitpid(pid_t, int *, int); #include "ipxutil.h" static char *progname; -static char *mount_point; -static char *server_name; + + +static void +str_upper(char *name) +{ + while (*name) { + *name = toupper(*name); + name = name + 1; + } +} + +static char * +fullpath(const char *p) +{ + char path[MAXPATHLEN]; + + if (realpath(p, path) == NULL) + return strdup(p); + else + return strdup(path); +} + +static void +usage(void) +{ + printf("usage: %s server mount-point [options]\n", progname); + printf("Try `%s -h' for more information\n", progname); +} + +static void +help(void) +{ + printf("\n"); + printf("usage: %s server mount-point [options]\n", progname); + printf("\n" + "-U username Username sent to server\n" + "-u uid uid the mounted files get\n" + "-g gid gid the mounted files get\n" + "-f mode permission the files get (octal notation)\n" + "-d mode permission the dirs get (octal notation)\n" + "-C Don't convert password to uppercase\n" + "-P password Use this password\n" + "-n Do not use any password\n" + " If neither -P nor -n are given, you are\n" + " asked for a password.\n" + "-h print this help text\n" + "\n"); +} struct sap_query { unsigned short query_type; /* net order */ @@ -47,15 +91,14 @@ struct sap_query { }; struct sap_server_ident { - unsigned short server_type; - char server_name[48]; - IPXNet server_network; - IPXNode server_node; - IPXPort server_port; - unsigned short intermediate_network; -} __attribute__ ((packed)); + 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)); +}; - void ipx_fprint_node(FILE* file,IPXNode node) { @@ -212,33 +255,217 @@ ipx_sap_find_server(char *name, int server_type, int timeout, return res; } -int ipx_sscanf_node(char *buf, unsigned char node[6]) +int +ipx_sscanf_node(char *buf, unsigned char node[6]) { - int i; - int n[6]; + int i; + int n[6]; - if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x", - &(n[0]), &(n[1]), &(n[2]), - &(n[3]), &(n[4]), &(n[5]))) != 6) { - return i; - } + if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x", + &(n[0]), &(n[1]), &(n[2]), + &(n[3]), &(n[4]), &(n[5]))) != 6) { + return i; + } - for (i=0; i<6; i++) { - node[i] = n[i]; - } - return 6; + for (i=0; i<6; i++) { + node[i] = n[i]; + } + return 6; } -int -main(int argc, char **argv) +static int +parse_args(int argc, char *argv[], struct ncp_mount_data *data, + int *got_password, int *upcase_password) { - struct ncp_mount_data data; - struct stat st; - struct sockaddr_ipx addr; - int ncp_sock, wdog_sock; - int flags; + int opt; + struct passwd *pwd; + struct group *grp; - progname = argv[0]; + *got_password = 0; + *upcase_password = 1; + + while ((opt = getopt (argc, argv, "Cp:s:c:U:u:g:f:d:m:P:n")) != EOF) { + switch (opt) { + case 'C': + *upcase_password = 0; + break; + case 'U': + if (strlen(optarg) > 63) { + fprintf(stderr, "Username too long: %s\n", + optarg); + return 1; + } + strcpy(data->username, optarg); + break; + case 'u': + if (isdigit(optarg[0])) { + data->uid = atoi(optarg); + } else { + pwd = getpwnam(optarg); + if (pwd == NULL) { + fprintf(stderr, "Unknown user: %s\n", + optarg); + return 1; + } + data->uid = pwd->pw_uid; + } + break; + case 'g': + if (isdigit(optarg[0])) { + data->gid = atoi(optarg); + } else { + grp = getgrnam(optarg); + if (grp == NULL) { + fprintf(stderr, "Unknown group: %s\n", + optarg); + return 1; + } + data->gid = grp->gr_gid; + } + break; + case 'f': + data->file_mode = strtol(optarg, NULL, 8); + break; + case 'd': + data->dir_mode = strtol(optarg, NULL, 8); + break; + case 'P': + strcpy(data->password, optarg); + *got_password = 1; + break; + case 'n': + data->password[0] = '0'; + *got_password = 1; + break; + default: + return -1; + } + } + return 0; + +} + +/* Returns 0 if the filesystem is in the kernel after this routine + completes */ +static int +load_ncpfs() +{ + FILE *fver, *ffs; + char s[1024]; + char modname[1024]; + char *p, *p1; + pid_t pid; + int status; + + /* Check if ncpfs is in the kernel */ + ffs = fopen("/proc/filesystems", "r"); + if (ffs == NULL) { + perror("Error: \"/proc/filesystems\" could not be read:"); + return -1; + } + p = NULL; + while (! feof(ffs)) { + p1 = fgets(s, sizeof(s), ffs); + if (p1) { + p = strstr(s, "ncpfs"); + if (p) { + break; + } + } + } + fclose(ffs); + if (p) { + return 0; + } + fver = fopen("/proc/version", "r"); + if (fver == NULL) { + perror("Error: \"/proc/version\" could not be read:"); + return -1; + } + fgets(s, 1024, fver); + fclose(fver); + p = strstr(s, "version "); + if (p == NULL) { + version_error: + fprintf(stderr, "Error: Unable to determine the Linux version" + "from \"/proc/version\n"); + return -1; + } + p = strchr(p, ' ') + 1; + p1 = strchr(p, ' '); + if (p1 == NULL) { + goto version_error; + } + strcpy(modname, "/lib/modules/"); + strncat(modname, p, p1 - p); + strcat(modname, "/ncpfs.o"); + + /* system() function without signal handling, from Stevens */ + + if ((pid = fork()) < 0) { + return 1; + } else if (pid == 0) { + /* child */ + execl("/sbin/insmod", "insmod", modname, NULL); + _exit(127); /* execl error */ + } else { + /* parent */ + while (waitpid(pid, &status, 0) < 0) { + if (errno != EINTR) { + status = -1; + break; + } + } + } + return status; +} + +/* Check whether user is allowed to mount on the specified mount point */ +static int +mount_ok(struct stat *st) +{ + if (!S_ISDIR(st->st_mode)) + { + errno = ENOTDIR; + return -1; + } + + if ( (getuid() != 0) + && ( (getuid() != st->st_uid) + || ((st->st_mode & S_IRWXU) != S_IRWXU))) + { + errno = EPERM; + return -1; + } + + return 0; +} + + + +int +main(int argc, char *argv[]) +{ + struct ncp_mount_data data; + struct sockaddr_ipx addr; + struct stat st; + + int fd; + int Got_Password; + int Upcase_Password; + int um; + unsigned int flags; + char hostname[MAXHOSTNAMELEN + 1]; + + char *server_name; + char *mount_point; + + struct mntent ment; + FILE *mtab; + + int ncp_sock, wdog_sock; + + progname = argv[0]; if (geteuid() != 0) { fprintf(stderr, "%s must be installed suid root\n", progname); @@ -247,22 +474,43 @@ main(int argc, char **argv) memset(&data, 0, sizeof(struct ncp_mount_data)); - if (argc != 5) { - fprintf(stderr, "usage: %s server mount-point" - " user password\n", progname); - exit(1); - } + memset(hostname, '\0', MAXHOSTNAMELEN+1); + gethostname(hostname, MAXHOSTNAMELEN); - server_name = argv[1]; - mount_point = argv[2]; - + if (argc < 3) { + if ( (argc == 2) + && (argv[1][0] == '-') + && (argv[1][1] == 'h') + && (argv[1][2] == '\0')) { - if (stat(mount_point, &st) == -1) { + help(); + return 0; + } + else + { + usage(); + return -1; + } + } + + server_name = argv[1]; + mount_point = argv[2]; + + argv += 2; + argc -= 2; + + if (stat(mount_point, &st) == -1) { fprintf(stderr, "could not find mount point %s: %s\n", mount_point, strerror(errno)); exit(1); } + if (mount_ok(&st) != 0) { + fprintf(stderr, "cannot to mount on %s: %s\n", + mount_point, strerror(errno)); + exit(1); + } + ncp_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX); if (ncp_sock == -1) { fprintf(stderr, "could not open ncp socket: %s\n", @@ -297,10 +545,13 @@ main(int argc, char **argv) exit(1); } - printf("server: "); - ipx_fprint_saddr(stdout, &addr); - printf("\n"); - + /* Check if the ncpfs filesystem is in the kernel. If not, attempt + * to load the ncpfs module */ + if (load_ncpfs() != 0) { + fprintf(stderr, "Error: Unable to start ncpfs, exiting...\n"); + exit(1); + } + data.version = NCP_MOUNT_VERSION; data.ncp_fd = ncp_sock; data.wdog_fd = wdog_sock; @@ -309,24 +560,111 @@ main(int argc, char **argv) strcpy(data.server_name, server_name); data.time_out = 20; /* 2 seconds */ data.retry_count = 2; - data.uid = 501; /* me */ - data.gid = 100; /* users */ - data.file_mode = data.dir_mode = S_IRWXU|S_IRWXG|S_IRWXO; - strcpy(data.username, argv[3]); - strcpy(data.password, argv[4]); + + /* getuid() gives us the real uid, who may umount the fs */ + data.mounted_uid = getuid(); + + if (getenv("USER")) { + strcpy(data.username, getenv("USER")); + str_upper(data.username); + } + + if (data.username[0] == 0 && getenv("LOGNAME")) + { + strcpy(data.username,getenv("LOGNAME")); + str_upper(data.username); + } + + data.uid = getuid(); + data.gid = getgid(); + um = umask(0); + umask(um); + data.file_mode = (S_IRWXU|S_IRWXG|S_IRWXO) & ~um; + data.dir_mode = 0; + + if (parse_args(argc, argv, &data, &Got_Password, + &Upcase_Password) != 0) { + usage(); + return -1; + } + + if (data.dir_mode == 0) { + data.dir_mode = data.file_mode; + if ((data.dir_mode & S_IRUSR) != 0) + data.dir_mode |= S_IXUSR; + if ((data.dir_mode & S_IRGRP) != 0) + data.dir_mode |= S_IXGRP; + if ((data.dir_mode & S_IROTH) != 0) + data.dir_mode |= S_IXOTH; + } + + if (Got_Password == 0) { + strcpy(data.password, getpass("Password: ")); + } + + if (Upcase_Password == 1) { + str_upper(data.password); + } + + if (data.server_name[0] == '\0') { + strcpy(data.server_name, server_name); + str_upper(data.server_name); + } flags = MS_MGC_VAL; - if (mount(NULL, mount_point, "ncpfs", flags, (char *)&data) < 0) { + if (mount(NULL, mount_point, "ncpfs", + flags, (char *)&data) < 0) { perror("mount error"); - fprintf(stderr, "Maybe you should try your password in " - "upper case\n"); + close(wdog_sock); + close(ncp_sock); + printf("Maybe you should try to type the username and\n" + "password in UPPERCASE.\n"); return -1; } close(ncp_sock); close(wdog_sock); - return 0; -} + ment.mnt_fsname = server_name; + ment.mnt_dir = fullpath(mount_point); + ment.mnt_type = "ncpfs"; + ment.mnt_opts = ""; + ment.mnt_freq = 0; + ment.mnt_passno= 0; + mount_point = ment.mnt_dir; + + if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) + { + fprintf(stderr, "Can't get "MOUNTED"~ lock file"); + return 1; + } + close(fd); + + if ((mtab = setmntent(MOUNTED, "a+")) == NULL) + { + fprintf(stderr, "Can't open " MOUNTED); + return 1; + } + + if (addmntent(mtab, &ment) == 1) + { + fprintf(stderr, "Can't write mount entry"); + return 1; + } + if (fchmod(fileno(mtab), 0644) == -1) + { + fprintf(stderr, "Can't set perms on "MOUNTED); + return 1; + } + endmntent(mtab); + + if (unlink(MOUNTED"~") == -1) + { + fprintf(stderr, "Can't remove "MOUNTED"~"); + return 1; + } + + return 0; +} diff --git a/ncptest.c b/ncptest.c new file mode 100644 index 0000000..a914ac7 --- /dev/null +++ b/ncptest.c @@ -0,0 +1,173 @@ +/* + * ncpmount.c + * + * Copyright (C) 1995 by Volker Lendecke + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* #include */ /* generates a warning here */ +extern pid_t waitpid(pid_t, int *, int); +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "ncplib.h" +#include "ipxutil.h" + +static char *progname; +static char *mount_point; + +void +test_filesearch(struct ncp_server *server) +{ + struct ncp_filesearch_info fsinfo; + struct ncp_file_info finfo; + + if (ncp_file_search_init(server, 0, "sys:\\public", &fsinfo) != 0) { + printf("could not fs init\n"); + return; + } + + while (ncp_file_search_continue(server, &fsinfo, + 0, + "*", &finfo) == 0) { + printf("name: %s\n", finfo.file_name); + } + return; +} + +void +test_getfinfo(struct ncp_server *server) +{ + struct ncp_file_info finfo; + + ncp_get_finfo(server, 0, "sys:", "public", &finfo); + ncp_get_finfo(server, 0, "sys:login", "login.exe", &finfo); +} + +void +testopen(struct ncp_server *server) +{ + struct ncp_file_info finfo; + char buf[1025]; + int bytes_read; + + ncp_open_file(server, 0, "sys:\\etc\\samples\\protocol", 0, + AR_READ|AR_WRITE, + &finfo); + if (ncp_read(server, finfo.file_id, 0, 1024, buf, &bytes_read) == 0) { + printf("bytes: %d\n", bytes_read); + buf[bytes_read]=0; + puts(buf); + } + + ncp_close_file(server, finfo.file_id); +} + +void +testcreate(struct ncp_server *server) +{ + + if (ncp_rename_file(server, 0, "sys:\\me\\blub.txt", 0, + 0, "sys:\\me\\blub1.txt") != 0) { + printf("create war nix\n"); + } + if (ncp_create_directory(server, 0, "sys:\\me\\blubdir", 0xff) != 0) { + printf("mkdir war nix\n"); + } + if (ncp_rename_directory(server, 0, "sys:\\me\\blubdir", + "\\me\\blubneu") != 0) { + printf("mvdir war nix\n"); + return; + } + if (ncp_delete_directory(server, 0, "sys:\\me\\blubneu") != 0) { + printf("rmdir war nix\n"); + return; + } + + +} + +int +main(int argc, char **argv) +{ + struct ncp_mount_data data; + struct stat st; + struct ncp_server serv; + struct ncp_server *server = &serv; + + + progname = argv[0]; + + if (geteuid() != 0) { + fprintf(stderr, "%s must be installed suid root\n", progname); + exit(1); + } + + memset(&data, 0, sizeof(struct ncp_mount_data)); + + if (argc == 2) { + mount_point = argv[1]; + } else { + fprintf(stderr, "usage: %s mount-point\n", progname); + printf("defaulting to %s mnt\n", progname); + mount_point = "mnt"; + } + + + if (stat(mount_point, &st) == -1) { + fprintf(stderr, "could not find mount point %s: %s\n", + mount_point, strerror(errno)); + exit(1); + } + + server->mount_fid = open(mount_point, O_RDONLY, 0); + + if (server->mount_fid == -1) { + fprintf(stderr, "Could not open %s: %s\n", + mount_point, strerror(errno)); + return -1; + } + +#if 0 + for (i=0; i<5; i++) { + struct ncp_volume_info info; + ncp_get_volume_info_with_number(server, i, &info); + printf("vol %d: %s\n", i, info.volume_name); + } + + test_filesearch(server); + test_getfinfo(server); + + +#endif + + testcreate(server); + + return 0; +} + diff --git a/nwcrypt.c b/nwcrypt.c index eceafe8..d12e1c2 100644 --- a/nwcrypt.c +++ b/nwcrypt.c @@ -1,9 +1,7 @@ /*$********************************************************* $* $* This code has been taken from DDJ 11/93, from an -$* article by Pawel Szczerbina. Please read the file -$* README for my questions about the legal status of -$* this code. +$* article by Pawel Szczerbina. $* $* Password encryption routines follow. $* Converted to C from Barry Nance's Pascal @@ -15,6 +13,77 @@ $* 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 about +the legal status of this piece of code: + + +--- +Date: Thu, 12 Oct 1995 13:44:18 +0100 +From: Volker 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 +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]; diff --git a/start_ipx b/start_ipx new file mode 100755 index 0000000..624b58d --- /dev/null +++ b/start_ipx @@ -0,0 +1,7 @@ +#!/bin/sh +# +# abcd is my ipx network number and 1234 my server's internal network number. +# 00001b038b11 is the server's node number. +# +ipx_interface add -p eth0 EtherII abcd +ipx_route add 1234 abcd 00001b038b11 diff --git a/startnet b/startnet deleted file mode 100755 index b8baed8..0000000 --- a/startnet +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -ipx_interface add -p eth0 EtherII abcd -ipx_route add 1234 abcd 00001b038b11