diff --git a/.downloads/ncpfs-2.0.0.tgz b/.downloads/ncpfs-2.0.0.tgz new file mode 100644 index 0000000..ceec7fb Binary files /dev/null and b/.downloads/ncpfs-2.0.0.tgz differ diff --git a/Changes b/Changes index 56766d1..8818fd0 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,12 @@ 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-0.24 -> ncpfs-2.0.0 +- Changed the numbering scheme :-). +- Added npasswd. Many thanks to Guntram Blom for his work! +- Hopefully improved error messages a bit +- Hopefully made slist a bit more robust + ncpfs-0.23 -> ncpfs-0.24 - Fixed a bug that made it impossible to umount a filesystem after you tried 'mkdir .' or 'mkdir ..'. diff --git a/Makefile b/Makefile index 6609631..02a1d3d 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux ncp-filesystem routines. # -VERSION = 0.24 +VERSION = 2.0.0 # If you are using kerneld to autoload ncp support, # uncomment this (kerneld is in linux since about 1.3.57): diff --git a/README b/README index 830f12a..22aa684 100644 --- a/README +++ b/README @@ -3,6 +3,12 @@ some little utilities it also contains nprint, which enables you to print on NetWare print queues. The opposite side, pserver, is also provided. +I'm planning major changes in the structure of ncpfs for Linux 2.1.x +which will break the binary compatibility. So I changed the numbering +scheme for ncpfs. ncpfs-2.0.x will be the version to be used with +Linux 2.0.0 and older kernels, and ncpfs-2.1.x will be the version for +the development kernels. + INSTALLATION Before you start the installation, make sure that your kernel has IPX diff --git a/ipx-1.0/ipx_configure.c b/ipx-1.0/ipx_configure.c index ba93a2b..da72787 100644 --- a/ipx-1.0/ipx_configure.c +++ b/ipx-1.0/ipx_configure.c @@ -12,6 +12,7 @@ #include #include #include +#include struct option options[] = { { "auto_primary", required_argument, NULL, 1 }, @@ -66,8 +67,14 @@ main(int argc, char **argv) s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); if (s < 0) { + int old_errno = errno; sprintf(errmsg, "%s: socket", progname); perror(errmsg); + if (old_errno == -EINVAL) + { + fprintf(stderr, "Probably you have no IPX support in " + "your kernel\n"); + } exit(-1); } diff --git a/ipx-1.0/ipx_interface.c b/ipx-1.0/ipx_interface.c index bbf9776..e1ef8fe 100644 --- a/ipx-1.0/ipx_interface.c +++ b/ipx-1.0/ipx_interface.c @@ -15,6 +15,7 @@ #include #include #include +#include static struct ifreq id; static char *progname; @@ -118,8 +119,14 @@ ipx_add_interface(int argc, char **argv) s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); if (s < 0) { + int old_errno = errno; sprintf(errmsg, "%s: socket", progname); perror(errmsg); + if (old_errno == -EINVAL) + { + fprintf(stderr, "Probably you have no IPX support in " + "your kernel\n"); + } exit(-1); } diff --git a/ipxdump/ipxdump b/ipxdump/ipxdump deleted file mode 100755 index b6c3cbb..0000000 Binary files a/ipxdump/ipxdump and /dev/null differ diff --git a/ipxdump/ipxparse b/ipxdump/ipxparse deleted file mode 100755 index f98b146..0000000 Binary files a/ipxdump/ipxparse and /dev/null differ diff --git a/man/Makefile b/man/Makefile index 474ad75..21abba7 100644 --- a/man/Makefile +++ b/man/Makefile @@ -1,4 +1,4 @@ -MAN1= slist nprint pqlist nsend pserver ncopy +MAN1= slist nprint pqlist nsend pserver ncopy npasswd MAN5= nwclient MAN8= ncpmount ncpumount ipx_configure ipx_interface ipx_internal_net \ ipx_route nwmsg diff --git a/man/npasswd.1 b/man/npasswd.1 new file mode 100644 index 0000000..811668c --- /dev/null +++ b/man/npasswd.1 @@ -0,0 +1,55 @@ +.TH NPASSWD 1 06/22/1996 npasswd npasswd +.SH NAME +npasswd \- Change a user's password +.SH SYNOPSIS +.B npasswd +[ +.B -h +] [ +.B -S +.I server +] [ +.B -U +.I user name +] +.B -t +.I object type +] + +.SH DESCRIPTION +With +.B npasswd, +you can change your password on a NetWare server. +.B npasswd +asks for the old password and twice for the new password. Then it +changes the password on the server. + +.SH OPTIONS + +.B -h +.RS 3 +With -h npasswd 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 name +.RS 3 +is the name of the bindery object whose password is to be changed. +.RE + +.B -t +.I object type +.RS 3 +is the bindery object type of the object whose password is to be +changed. +.RE + +.SH CREDITS +npasswd would not have been possible without the work of Guntram +Blom. Look at nwcrypt.c for his work. diff --git a/ncpfs-0.24.lsm b/ncpfs-2.0.0.lsm similarity index 84% rename from ncpfs-0.24.lsm rename to ncpfs-2.0.0.lsm index 72c1444..2ffb659 100644 --- a/ncpfs-0.24.lsm +++ b/ncpfs-2.0.0.lsm @@ -1,7 +1,7 @@ Begin3 Title: ncpfs -Version: 0.24 -Entered-date: 02. June 1996 +Version: 2.0.0 +Entered-date: 22. June 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/system/Filesystems/ncpfs - ~120k ncpfs-0.24.tgz - ~ 1k ncpfs-0.24.lsm + ~120k ncpfs-2.0.0.tgz + ~ 1k ncpfs-2.0.0.lsm Copying-policy: GPL End diff --git a/util/Makefile b/util/Makefile index 2202269..c21ac1f 100644 --- a/util/Makefile +++ b/util/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux ncp-filesystem routines. # -USERUTILS = slist pqlist nwfsinfo pserver nprint nsend ncopy +USERUTILS = slist pqlist nwfsinfo pserver nprint nsend ncopy npasswd UIDUTILS = ncpmount ncpumount SBINUTILS = nwmsg diff --git a/util/ncplib.c b/util/ncplib.c index 1ad50f6..8314bf4 100644 --- a/util/ncplib.c +++ b/util/ncplib.c @@ -237,6 +237,10 @@ ipx_sap_find_nearest(int server_type, struct sockaddr_ipx *result, if ((sock = socket(AF_IPX,SOCK_DGRAM,PF_IPX)) < 0) { + if (errno == EINVAL) + { + return NCPL_ET_NO_IPX; + } return errno; } @@ -344,7 +348,11 @@ ipx_make_reachable(IPXNet network) if (sock == -1) { - return -1; + if (errno == EINVAL) + { + return NCPL_ET_NO_IPX; + } + return errno; } opt=1; @@ -1833,7 +1841,7 @@ ncp_send_broadcast(struct ncp_conn *conn, } /* - * result is a 8-byte buffer + * target is a 8-byte buffer */ long ncp_get_encryption_key(struct ncp_conn *conn, @@ -1941,14 +1949,17 @@ ncp_scan_bindery_object(struct ncp_conn *conn, long ncp_create_bindery_object(struct ncp_conn *conn, - struct ncp_bindery_object *source) + __u16 object_type, + const char *object_name, + __u8 object_security, + __u8 object_status) { long result; ncp_init_request_s(conn, 50); - ncp_add_byte(conn, source->object_flags); - ncp_add_byte(conn, source->object_security); - ncp_add_word(conn, htons(source->object_type)); - ncp_add_pstring(conn, source->object_name); + ncp_add_byte(conn, object_status); + ncp_add_byte(conn, object_security); + ncp_add_word(conn, htons(object_type)); + ncp_add_pstring(conn, object_name); result = ncp_request(conn, 23); ncp_unlock_conn(conn); @@ -2163,6 +2174,43 @@ ncp_login_encrypted(struct ncp_conn *conn, return result; } +long +ncp_change_login_passwd(struct ncp_conn *conn, + const struct ncp_bindery_object *object, + const unsigned char *key, + const unsigned char *oldpasswd, + const unsigned char *newpasswd) +{ + long id = htonl(object->object_id); + unsigned char cryptkey[8]; + unsigned char newpwd[16]; /* new passwd as stored by server */ + unsigned char oldpwd[16]; /* old passwd as stored by server */ + unsigned char len; + long result; + + memcpy(cryptkey, key, 8); + shuffle((byte *)&id, oldpasswd, strlen(oldpasswd), oldpwd); + shuffle((byte *)&id, newpasswd, strlen(newpasswd), newpwd); + nw_encrypt(cryptkey, oldpwd, cryptkey); + newpassencrypt(oldpwd, newpwd, newpwd); + newpassencrypt(oldpwd+8, newpwd+8, newpwd+8); + if ((len = strlen(newpasswd)) > 63) + { + len = 63; + } + len = ((len ^ oldpwd[0] ^ oldpwd[1]) & 0x7f) | 0x40; + + ncp_init_request_s(conn, 75); + ncp_add_mem(conn, cryptkey, 8); + ncp_add_word(conn, htons(object->object_type)); + ncp_add_pstring(conn, object->object_name); + ncp_add_byte(conn, len); + ncp_add_mem(conn, newpwd, 16); + result = ncp_request(conn, 23); + ncp_unlock_conn(conn); + return result; +} + long ncp_login_user(struct ncp_conn *conn, const unsigned char *username, diff --git a/util/ncplib.h b/util/ncplib.h index 2638b36..ff83776 100644 --- a/util/ncplib.h +++ b/util/ncplib.h @@ -104,7 +104,7 @@ ncp_initialize_as(int *argc, char **argv, int login_necessary, int login_type, long *err); -/* Open an existing permanent connection */ +/* Open a connection */ struct ncp_conn * ncp_open(const struct ncp_conn_spec *spec, long *err); @@ -183,12 +183,21 @@ ncp_scan_bindery_object(struct ncp_conn *conn, struct ncp_bindery_object *target); long ncp_create_bindery_object(struct ncp_conn *conn, - struct ncp_bindery_object *source); + __u16 object_type, + const char *object_name, + __u8 object_security, + __u8 object_status); long ncp_delete_bindery_object(struct ncp_conn *conn, __u16 object_type, const char *object_name); +long +ncp_change_object_security(struct ncp_conn *conn, + __u16 object_type, + const char *object_name, + __u8 security); + struct ncp_prop_login_control { __u8 AccountExpireDate[3] __attribute__ ((packed)); __u8 Disabled __attribute__ ((packed)); @@ -256,6 +265,13 @@ ncp_login_encrypted(struct ncp_conn *conn, const unsigned char *key, const unsigned char *passwd); +long +ncp_change_login_passwd(struct ncp_conn *conn, + const struct ncp_bindery_object *object, + const unsigned char *key, + const unsigned char *oldpasswd, + const unsigned char *newpasswd); + #define NCP_GRACE_PERIOD (0xdf) long diff --git a/util/ncplib_err.et b/util/ncplib_err.et index 3e785d3..f0d5bb6 100644 --- a/util/ncplib_err.et +++ b/util/ncplib_err.et @@ -33,4 +33,7 @@ ec NCPL_ET_NO_PASSWORD, ec NCPL_ET_PWD_TOO_LONG, "Password too long" +ec NCPL_ET_NO_IPX, + "Could not alloc IPX socket. Probably no IPX support in kernel." + end \ No newline at end of file diff --git a/util/ncptest.c b/util/ncptest.c index ad9a268..75488c4 100644 --- a/util/ncptest.c +++ b/util/ncptest.c @@ -106,7 +106,30 @@ test_create(struct ncp_conn *conn) return; } } - + +int +test_change(struct ncp_conn *conn) +{ + long result; + unsigned char ncp_key[8]; + struct ncp_bindery_object user; + + if ((result = ncp_get_encryption_key(conn, ncp_key)) != 0) { + return result; + } + + if ((result = ncp_get_bindery_object_id(conn, 1, + "ME", &user)) != 0) { + return result; + } + + if ((result = ncp_change_login_passwd(conn, &user, ncp_key, + "MEE", "ME")) != 0) + { + return result; + } + return 0; +} int main(int argc, char *argv[]) @@ -120,7 +143,7 @@ main(int argc, char *argv[]) return 1; } - test_send(conn); + test_change(conn); ncp_close(conn); return 0; } diff --git a/util/npasswd.c b/util/npasswd.c new file mode 100644 index 0000000..0f2e551 --- /dev/null +++ b/util/npasswd.c @@ -0,0 +1,144 @@ +/* + * npasswd.c + * + * Change a bindery object's password + * + * Copyright (C) 1996 by Volker Lendecke + * + */ + +#include "ncplib.h" +#include +#include + +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"); +} + + +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; + unsigned char ncp_key[8]; + struct ncp_bindery_object user; + long err; + + char *str; + + char oldpass[200], newpass1[200], newpass2[200]; + + int opt; + + progname = argv[0]; + + while ((opt = getopt(argc, argv, "hS: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': + 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, "trying to find server"); + exit(1); + } + + spec->login_type = object_type; + + printf("Changing password for user %s on server %s\n", + spec->user, spec->server); + + str = getpass("Enter old password: "); + if (strlen(str) >= sizeof(oldpass)) + { + printf("Password too long\n"); + exit(1); + } + strcpy(oldpass, str); + + str = getpass("Enter new password: "); + if (strlen(str) >= sizeof(newpass1)) + { + printf("Password too long\n"); + exit(1); + } + strcpy(newpass1, str); + + str = getpass("Re-Enter new password: "); + if (strlen(str) >= sizeof(newpass2)) + { + printf("Password too long\n"); + exit(1); + } + strcpy(newpass2, str); + + str_upper(oldpass); + str_upper(newpass1); + str_upper(newpass2); + + if (strcmp(newpass1, newpass2) != 0) + { + printf("You mistype the new password, try again\n"); + exit(1); + } + + strcpy(spec->password, oldpass); + + if ((conn = ncp_open(spec, &err)) == NULL) + { + com_err(argv[0], err, "when trying to open connection"); + exit(1); + } + + if ( ((err = ncp_get_encryption_key(conn, ncp_key)) != 0) + || ((err = ncp_get_bindery_object_id(conn, 1, spec->user, + &user)) != 0) + || ((err = ncp_change_login_passwd(conn, &user, ncp_key, + oldpass, newpass1)) != 0)) + { + com_err(argv[0], err, "trying to change password"); + } + + ncp_close(conn); + return 0; +} diff --git a/util/nwcrypt.c b/util/nwcrypt.c index 27ee843..de9d955 100644 --- a/util/nwcrypt.c +++ b/util/nwcrypt.c @@ -209,3 +209,131 @@ nw_encrypt(const unsigned char *fra, } +/*****************************************************************************/ +/* */ +/* The following code was contributed by */ +/* Guntram Blohm */ +/* */ +/*****************************************************************************/ + +/* server side (mars etc.) should: + * store the *encrypted* password internally (output from shuffle) + * verify if nw_encrypt(cryptkey from GetCryptKey, old stored password) + == cryptkey in EncryptedChangePassword request buffer (this means + old password was correct) + * decrypt new password in request buffer using (yet to write) inverse of + newpassencrypt with old stored password as parameter + * compute the length of the unencrypted new password as len ^ (first byte of + old internal password) ^ (second byte of old internal password) + */ + +static char +newshuffle[256+16] = { + 0x0f, 0x08, 0x05, 0x07, 0x0c, 0x02, 0x0e, 0x09, + 0x00, 0x01, 0x06, 0x0d, 0x03, 0x04, 0x0b, 0x0a, + 0x02, 0x0c, 0x0e, 0x06, 0x0f, 0x00, 0x01, 0x08, + 0x0d, 0x03, 0x0a, 0x04, 0x09, 0x0b, 0x05, 0x07, + + 0x05, 0x02, 0x09, 0x0f, 0x0c, 0x04, 0x0d, 0x00, + 0x0e, 0x0a, 0x06, 0x08, 0x0b, 0x01, 0x03, 0x07, + 0x0f, 0x0d, 0x02, 0x06, 0x07, 0x08, 0x05, 0x09, + 0x00, 0x04, 0x0c, 0x03, 0x01, 0x0a, 0x0b, 0x0e, + + 0x05, 0x0e, 0x02, 0x0b, 0x0d, 0x0a, 0x07, 0x00, + 0x08, 0x06, 0x04, 0x01, 0x0f, 0x0c, 0x03, 0x09, + 0x08, 0x02, 0x0f, 0x0a, 0x05, 0x09, 0x06, 0x0c, + 0x00, 0x0b, 0x01, 0x0d, 0x07, 0x03, 0x04, 0x0e, + + 0x0e, 0x08, 0x00, 0x09, 0x04, 0x0b, 0x02, 0x07, + 0x0c, 0x03, 0x0a, 0x05, 0x0d, 0x01, 0x06, 0x0f, + 0x01, 0x04, 0x08, 0x0a, 0x0d, 0x0b, 0x07, 0x0e, + 0x05, 0x0f, 0x03, 0x09, 0x00, 0x02, 0x06, 0x0c, + + 0x05, 0x03, 0x0c, 0x08, 0x0b, 0x02, 0x0e, 0x0a, + 0x04, 0x01, 0x0d, 0x00, 0x06, 0x07, 0x0f, 0x09, + 0x06, 0x00, 0x0b, 0x0e, 0x0d, 0x04, 0x0c, 0x0f, + 0x07, 0x02, 0x08, 0x0a, 0x01, 0x05, 0x03, 0x09, + + 0x0b, 0x05, 0x0a, 0x0e, 0x0f, 0x01, 0x0c, 0x00, + 0x06, 0x04, 0x02, 0x09, 0x03, 0x0d, 0x07, 0x08, + 0x07, 0x02, 0x0a, 0x00, 0x0e, 0x08, 0x0f, 0x04, + 0x0c, 0x0b, 0x09, 0x01, 0x05, 0x0d, 0x03, 0x06, + + 0x07, 0x04, 0x0f, 0x09, 0x05, 0x01, 0x0c, 0x0b, + 0x00, 0x03, 0x08, 0x0e, 0x02, 0x0a, 0x06, 0x0d, + 0x09, 0x04, 0x08, 0x00, 0x0a, 0x03, 0x01, 0x0c, + 0x05, 0x0f, 0x07, 0x02, 0x0b, 0x0e, 0x06, 0x0d, + + 0x09, 0x05, 0x04, 0x07, 0x0e, 0x08, 0x03, 0x01, + 0x0d, 0x0b, 0x0c, 0x02, 0x00, 0x0f, 0x06, 0x0a, + 0x09, 0x0a, 0x0b, 0x0d, 0x05, 0x03, 0x0f, 0x00, + 0x01, 0x0c, 0x08, 0x07, 0x06, 0x04, 0x0e, 0x02, + + 0x03, 0x0e, 0x0f, 0x02, 0x0d, 0x0c, 0x04, 0x05, + 0x09, 0x06, 0x00, 0x01, 0x0b, 0x07, 0x0a, 0x08, +}; + +/* + * verschluesseln des neuen Passworts fuer keyed change password + * Verwendung: + * - Shuffle (aus nwcrypt.c) altes passwort nach old (16 bytes) + * - shuffle neues passwort nach new (16 bytes) + * - nwpassencrypt (diese Funktion) zweimal aufrufen fuer je 8 bytes: + * nwpassencrypt(old+0, new+0, out+0) + * nwpassencrypt(old+8, new+8, out+8) + * - NCP-Buffer aufbauen: + * 2 byte Laenge im Hi-Lo-Format + * 1 byte Funktion (0x4b) + * 8 byte (nwcrypt Ergebnis analog login/verify password) + * 2 byte Objecttype + * 1 byte Objectname-Laenge + * n byte Objectname + * 1 byte (Laenge des eingegebenen neuen Passworts ^ old[0] ^ old[1])&0x7f|0x40 + * 16 byte (Ergebnis dieser Funktion doppelt aufgerufen, s.o.) + */ + +/* + * Encrypt the new password for keyed change password + * For info on how to use this function, look at ncp_change_login_passwd + * in ncplib.c. + */ + +static void +newpassencrypt(char *old, char *new, char *out) +{ + char *p, *bx; + char copy[8]; + int i, di, ax; + char cl, dl, ch; + + memcpy(copy, new, 8); + + for (i=0; i<16; i++) + { + for (di=0, ax=0, p=old; di<8; di++, ax+=0x20, p++) + { + cl=newshuffle[(((copy[di]^*p)>>4)&0x0f)+ax+0x10]<<4; + dl=newshuffle[((copy[di]^*p)&0xf)+ax]; + copy[di]=cl|dl; + } + + ch=old[7]; + for (bx=old+7; bx>old; bx--) + { + *bx=((bx[-1]>>4)&0x0f)|((*bx)<<4); + } + *old=((ch>>4)&0x0f)|(*old)<<4; + + memset(out, '\0', 8); + + for (di=0; di<16; di++) + { + if (newshuffle[di+0x100]&1) + ch=((copy[newshuffle[di+0x100]/2]>>4)&0x0f); + else + ch=copy[newshuffle[di+0x100]/2]&0x0f; + out[di/2]|=((di&1) ? ch<<4 : ch); + } + memcpy(copy, out, 8); + } +} diff --git a/util/slist.c b/util/slist.c index 08b2075..9c2a773 100644 --- a/util/slist.c +++ b/util/slist.c @@ -41,9 +41,9 @@ main(int argc, char *argv[]) *p = toupper(*p); } - if ((conn = ncp_initialize(&argc, argv, 0, &err)) == NULL) + if ((conn = ncp_open(NULL, &err)) == NULL) { - com_err(argv[0], err, "in ncp_initialize"); + com_err(argv[0], err, "in ncp_open"); exit(1); }