From d78b61e3efaea197a6e5b2b72bf2981a9ed69461 Mon Sep 17 00:00:00 2001 From: Rob Funk Date: Tue, 8 Jun 2004 03:59:01 +0000 Subject: Add files from ESR's dev directory that weren't under version control svn path=/trunk/; revision=3881 --- libntlm-0.21/COPYING | 339 +++++++++++++++++++++++++++++++++++++ libntlm-0.21/HISTORY | 21 +++ libntlm-0.21/Makefile | 42 +++++ libntlm-0.21/README | 98 +++++++++++ libntlm-0.21/ntlm.h | 68 ++++++++ libntlm-0.21/smb.h | 52 ++++++ libntlm-0.21/smbbyteorder.h | 265 +++++++++++++++++++++++++++++ libntlm-0.21/smbdes.c | 399 ++++++++++++++++++++++++++++++++++++++++++++ libntlm-0.21/smbdes.h | 9 + libntlm-0.21/smbencrypt.c | 323 +++++++++++++++++++++++++++++++++++ libntlm-0.21/smbencrypt.h | 2 + libntlm-0.21/smbmd4.c | 172 +++++++++++++++++++ libntlm-0.21/smbmd4.h | 1 + libntlm-0.21/smbutil.c | 218 ++++++++++++++++++++++++ libntlm-0.21/test/COPYING | 339 +++++++++++++++++++++++++++++++++++++ libntlm-0.21/test/Makefile | 6 + libntlm-0.21/test/README | 19 +++ libntlm-0.21/test/dumper.c | 237 ++++++++++++++++++++++++++ libntlm-0.21/test/getargs.c | 240 ++++++++++++++++++++++++++ libntlm-0.21/test/getargs.h | 19 +++ 20 files changed, 2869 insertions(+) create mode 100644 libntlm-0.21/COPYING create mode 100644 libntlm-0.21/HISTORY create mode 100644 libntlm-0.21/Makefile create mode 100644 libntlm-0.21/README create mode 100644 libntlm-0.21/ntlm.h create mode 100644 libntlm-0.21/smb.h create mode 100644 libntlm-0.21/smbbyteorder.h create mode 100644 libntlm-0.21/smbdes.c create mode 100644 libntlm-0.21/smbdes.h create mode 100644 libntlm-0.21/smbencrypt.c create mode 100644 libntlm-0.21/smbencrypt.h create mode 100644 libntlm-0.21/smbmd4.c create mode 100644 libntlm-0.21/smbmd4.h create mode 100644 libntlm-0.21/smbutil.c create mode 100755 libntlm-0.21/test/COPYING create mode 100644 libntlm-0.21/test/Makefile create mode 100644 libntlm-0.21/test/README create mode 100644 libntlm-0.21/test/dumper.c create mode 100644 libntlm-0.21/test/getargs.c create mode 100644 libntlm-0.21/test/getargs.h (limited to 'libntlm-0.21') diff --git a/libntlm-0.21/COPYING b/libntlm-0.21/COPYING new file mode 100644 index 00000000..a43ea212 --- /dev/null +++ b/libntlm-0.21/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libntlm-0.21/HISTORY b/libntlm-0.21/HISTORY new file mode 100644 index 00000000..58c31c57 --- /dev/null +++ b/libntlm-0.21/HISTORY @@ -0,0 +1,21 @@ + +7 October 1999 Revsion 0.21 + +Added support for usernames with embedded domain strings of the +format username@domain. If present, the domain will override the +domain that is returned by the host in the challenge. + +6 October 1999 Revision 0.2 +----------------------------- + +Fixed another byte-order problem in unicode routine in smbutil.c. +Added a copy of GPL to the distribution. Added test driver +program directory. + +5 October 1999 Revision 0.1 +----------------------------- + +Fixed usage of byte-order macros in smbutil.c. Hopefully this +will make it work on SPARC machines... + + diff --git a/libntlm-0.21/Makefile b/libntlm-0.21/Makefile new file mode 100644 index 00000000..3195f4b0 --- /dev/null +++ b/libntlm-0.21/Makefile @@ -0,0 +1,42 @@ +CFLAGS=-Wall -g + +DEST=/usr/local +LIBDEST=$(DEST)/lib +INCDEST=$(DEST)/include + +SRCS=smbdes.c smbencrypt.c smbmd4.c smbutil.c +OBJS=smbdes.o smbencrypt.o smbmd4.o smbutil.o + +libntlm.a: $(OBJS) + ar cru libntlm.a $(OBJS) + ranlib libntlm.a + +install: libntlm.a ntlm.h + install libntlm.a $(LIBDEST) + install ntlm.h $(INCDEST) + +clean: + rm -f *.a *.o *~ *.bak \#*\# + +depend: + makedepend $(SRCS) +# DO NOT DELETE + +smbdes.o: smbdes.h +smbencrypt.o: /usr/include/unistd.h /usr/include/sys/feature_tests.h +smbencrypt.o: /usr/include/sys/types.h /usr/include/sys/isa_defs.h +smbencrypt.o: /usr/include/sys/machtypes.h /usr/include/sys/int_types.h +smbencrypt.o: /usr/include/sys/select.h /usr/include/sys/time.h +smbencrypt.o: /usr/include/sys/time.h /usr/include/sys/unistd.h +smbencrypt.o: /usr/include/stdlib.h /usr/include/string.h +smbencrypt.o: /usr/include/ctype.h smbbyteorder.h smbdes.h smbmd4.h +smbmd4.o: smbmd4.h +smbutil.o: /usr/include/unistd.h /usr/include/sys/feature_tests.h +smbutil.o: /usr/include/sys/types.h /usr/include/sys/isa_defs.h +smbutil.o: /usr/include/sys/machtypes.h /usr/include/sys/int_types.h +smbutil.o: /usr/include/sys/select.h /usr/include/sys/time.h +smbutil.o: /usr/include/sys/time.h /usr/include/sys/unistd.h +smbutil.o: /usr/include/stdlib.h /usr/include/stdio.h +smbutil.o: /usr/include/sys/va_list.h /usr/include/ctype.h +smbutil.o: /usr/include/assert.h /usr/include/string.h ntlm.h smbencrypt.h +smbutil.o: smbbyteorder.h diff --git a/libntlm-0.21/README b/libntlm-0.21/README new file mode 100644 index 00000000..2ce20c39 --- /dev/null +++ b/libntlm-0.21/README @@ -0,0 +1,98 @@ + +This directory contains sources for a library which provides +routines to manipulate the structures used for the client end +of Microsoft NTLM authentication. + +This code was taken mostly from the Samba project and was +initially intended for use with Microsoft Exchange Server when +it is configured to require NTLM authentication for clients of +it's IMAP server. + +BUILDING + +If you want the library installed in /usr/local/lib and +the header in /usr/local/include, then + + $ make + $ make install + +will probably work. Not much effort has been put into making +this portable, and I only know for sure that it works on i386 +Linux glibc systems -- though there shouldn't be anything all +that system-specific anywhere. System byte order differences +should already be taken care of. + +TEST PROGRAM + +The test directory contains sources for a program named +"dumper" that will dump out base64 NTLM auth messages in a +readable format. It will also take a challenge and generate a +response if provided with a username and password. + +USAGE + +The application program must convert these structures to/from +base64 which is used to transfer data for IMAP authentication. +For example usage see the sources for the mutt MUA or the +fetchmail package. + +In general the usage is something like shown below (no, I don't +know if this code even compiles, but you get the idea +hopefully): + + +#include + +extern char *seqTag; /* IMAP sequence number */ + +int imap_auth_ntlm(char *user, char *domain, char *pass) +{ + tSmbNtlmAuthRequest request; + tSmbNtlmAuthChallenge challenge; + tSmbNtlmAuthResponse response; + char buffer[512]; + char tmpstr[32]; + + writeToServer("%s AUTHENTICATE NTLM\r\n",seqTag); + readFromServer(buffer) + + /* buffer should be "+", but we won't show code to check */ + + /* + * prepare the request, convert to base64, and send it to + * the the server. My server didn't care about domain, and NULL + * worked fine. + */ + + buildSmbNtlmAuthRequest(&request,user,domain); + convertToBase64(buffer, &request, SmbLength(&request)); + writeToServer("%s\r\n",buffer); + + /* read challange data from server, convert from base64 */ + + readFromServer(buffer); + + /* buffer should contain the string "+ [base 64 data]" */ + + convertFromBase64(&challenge, buffer+2); + + /* prepare response, convert to base64, send to server */ + + buildSmbNtlmAuthResponse(&challenge, &response, user, pass); + convertToBase64(buffer,&response,SmbLength(&response)); + writeToServer("%s\r\n",buffer); + + /* read line from server, it should be "[seq] OK blah blah blah" */ + + readFromServer(buffer); + + sprintf(tmpstr,"%s OK",seqTag); + + if (strncmp(buffer,tmpstr,strlen(tmpstr))) + { + /* login failed */ + return -1; + } + + return 0; +} diff --git a/libntlm-0.21/ntlm.h b/libntlm-0.21/ntlm.h new file mode 100644 index 00000000..3f6d206f --- /dev/null +++ b/libntlm-0.21/ntlm.h @@ -0,0 +1,68 @@ +typedef unsigned short uint16; +typedef unsigned int uint32; +typedef unsigned char uint8; + + +/* + * These structures are byte-order dependant, and should not + * be manipulated except by the use of the routines provided + */ + +typedef struct +{ +uint16 len; +uint16 maxlen; +uint32 offset; +}tSmbStrHeader; + +typedef struct +{ +char ident[8]; +uint32 msgType; +uint32 flags; +tSmbStrHeader user; +tSmbStrHeader domain; +uint8 buffer[1024]; +uint32 bufIndex; +}tSmbNtlmAuthRequest; + +typedef struct +{ +char ident[8]; +uint32 msgType; +tSmbStrHeader uDomain; +uint32 flags; +uint8 challengeData[8]; +uint8 reserved[8]; +tSmbStrHeader emptyString; +uint8 buffer[1024]; +uint32 bufIndex; +}tSmbNtlmAuthChallenge; + + +typedef struct +{ +char ident[8]; +uint32 msgType; +tSmbStrHeader lmResponse; +tSmbStrHeader ntResponse; +tSmbStrHeader uDomain; +tSmbStrHeader uUser; +tSmbStrHeader uWks; +tSmbStrHeader sessionKey; +uint32 flags; +uint8 buffer[1024]; +uint32 bufIndex; +}tSmbNtlmAuthResponse; + +/* public: */ + +#define SmbLength(ptr) (((ptr)->buffer - (uint8*)(ptr)) + (ptr)->bufIndex) + +extern void dumpSmbNtlmAuthRequest(FILE *fp, tSmbNtlmAuthRequest *request); +extern void dumpSmbNtlmAuthChallenge(FILE *fp, tSmbNtlmAuthChallenge *challenge); +extern void dumpSmbNtlmAuthResponse(FILE *fp, tSmbNtlmAuthResponse *response); + +extern void buildSmbNtlmAuthRequest(tSmbNtlmAuthRequest *request, char *user, char *domain); +extern void buildSmbNtlmAuthResponse(tSmbNtlmAuthChallenge *challenge, tSmbNtlmAuthResponse *response, char *user, char *password); + diff --git a/libntlm-0.21/smb.h b/libntlm-0.21/smb.h new file mode 100644 index 00000000..eb5e382e --- /dev/null +++ b/libntlm-0.21/smb.h @@ -0,0 +1,52 @@ +typedef unsigned short uint16; +typedef unsigned uint32; +typedef unsigned char uint8; + +typedef struct +{ +uint16 len; +uint16 maxlen; +uint32 offset; +}tSmbStrHeader; + +typedef struct +{ +char ident[8]; +uint32 msgType; +uint32 flags; +tSmbStrHeader user; +tSmbStrHeader domain; +uint8 buffer[1024]; +uint32 bufIndex; +}tSmbNtlmAuthRequest; + +typedef struct +{ +char ident[8]; +uint32 msgType; +tSmbStrHeader uDomain; +uint32 flags; +uint8 challengeData[8]; +uint8 reserved[8]; +tSmbStrHeader emptyString; +uint8 buffer[1024]; +uint32 bufIndex; +}tSmbNtlmAuthChallenge; + + +typedef struct +{ +char ident[8]; +uint32 msgType; +tSmbStrHeader lmResponse; +tSmbStrHeader ntResponse; +tSmbStrHeader uDomain; +tSmbStrHeader uUser; +tSmbStrHeader uWks; +tSmbStrHeader sessionKey; +uint32 flags; +uint8 buffer[1024]; +uint32 bufIndex; +}tSmbNtlmAuthResponse; + +#define SmbLength(ptr) (((ptr)->buffer - (uint8*)(ptr)) + (ptr)->bufIndex) diff --git a/libntlm-0.21/smbbyteorder.h b/libntlm-0.21/smbbyteorder.h new file mode 100644 index 00000000..59ae4979 --- /dev/null +++ b/libntlm-0.21/smbbyteorder.h @@ -0,0 +1,265 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB Byte handling + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _BYTEORDER_H +#define _BYTEORDER_H + +/* + This file implements macros for machine independent short and + int manipulation + +Here is a description of this file that I emailed to the samba list once: + +> I am confused about the way that byteorder.h works in Samba. I have +> looked at it, and I would have thought that you might make a distinction +> between LE and BE machines, but you only seem to distinguish between 386 +> and all other architectures. +> +> Can you give me a clue? + +sure. + +The distinction between 386 and other architectures is only there as +an optimisation. You can take it out completely and it will make no +difference. The routines (macros) in byteorder.h are totally byteorder +independent. The 386 optimsation just takes advantage of the fact that +the x86 processors don't care about alignment, so we don't have to +align ints on int boundaries etc. If there are other processors out +there that aren't alignment sensitive then you could also define +CAREFUL_ALIGNMENT=0 on those processors as well. + +Ok, now to the macros themselves. I'll take a simple example, say we +want to extract a 2 byte integer from a SMB packet and put it into a +type called uint16 that is in the local machines byte order, and you +want to do it with only the assumption that uint16 is _at_least_ 16 +bits long (this last condition is very important for architectures +that don't have any int types that are 2 bytes long) + +You do this: + +#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) +#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos)) +#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) + +then to extract a uint16 value at offset 25 in a buffer you do this: + +char *buffer = foo_bar(); +uint16 xx = SVAL(buffer,25); + +We are using the byteoder independence of the ANSI C bitshifts to do +the work. A good optimising compiler should turn this into efficient +code, especially if it happens to have the right byteorder :-) + +I know these macros can be made a bit tidier by removing some of the +casts, but you need to look at byteorder.h as a whole to see the +reasoning behind them. byteorder.h defines the following macros: + +SVAL(buf,pos) - extract a 2 byte SMB value +IVAL(buf,pos) - extract a 4 byte SMB value +SVALS(buf,pos) signed version of SVAL() +IVALS(buf,pos) signed version of IVAL() + +SSVAL(buf,pos,val) - put a 2 byte SMB value into a buffer +SIVAL(buf,pos,val) - put a 4 byte SMB value into a buffer +SSVALS(buf,pos,val) - signed version of SSVAL() +SIVALS(buf,pos,val) - signed version of SIVAL() + +RSVAL(buf,pos) - like SVAL() but for NMB byte ordering +RSVALS(buf,pos) - like SVALS() but for NMB byte ordering +RIVAL(buf,pos) - like IVAL() but for NMB byte ordering +RIVALS(buf,pos) - like IVALS() but for NMB byte ordering +RSSVAL(buf,pos,val) - like SSVAL() but for NMB ordering +RSIVAL(buf,pos,val) - like SIVAL() but for NMB ordering +RSIVALS(buf,pos,val) - like SIVALS() but for NMB ordering + +it also defines lots of intermediate macros, just ignore those :-) + +*/ + +/* some switch macros that do both store and read to and from SMB buffers */ + +#define RW_PCVAL(read,inbuf,outbuf,len) \ + { if (read) { PCVAL (inbuf,0,outbuf,len); } \ + else { PSCVAL(inbuf,0,outbuf,len); } } + +#define RW_PIVAL(read,big_endian,inbuf,outbuf,len) \ + { if (read) { if (big_endian) { RPIVAL(inbuf,0,outbuf,len); } else { PIVAL(inbuf,0,outbuf,len); } } \ + else { if (big_endian) { RPSIVAL(inbuf,0,outbuf,len); } else { PSIVAL(inbuf,0,outbuf,len); } } } + +#define RW_PSVAL(read,big_endian,inbuf,outbuf,len) \ + { if (read) { if (big_endian) { RPSVAL(inbuf,0,outbuf,len); } else { PSVAL(inbuf,0,outbuf,len); } } \ + else { if (big_endian) { RPSSVAL(inbuf,0,outbuf,len); } else { PSSVAL(inbuf,0,outbuf,len); } } } + +#define RW_CVAL(read, inbuf, outbuf, offset) \ + { if (read) { (outbuf) = CVAL (inbuf,offset); } \ + else { SCVAL(inbuf,offset,outbuf); } } + +#define RW_IVAL(read, big_endian, inbuf, outbuf, offset) \ + { if (read) { (outbuf) = ((big_endian) ? RIVAL(inbuf,offset) : IVAL (inbuf,offset)); } \ + else { if (big_endian) { RSIVAL(inbuf,offset,outbuf); } else { SIVAL(inbuf,offset,outbuf); } } } + +#define RW_SVAL(read, big_endian, inbuf, outbuf, offset) \ + { if (read) { (outbuf) = ((big_endian) ? RSVAL(inbuf,offset) : SVAL (inbuf,offset)); } \ + else { if (big_endian) { RSSVAL(inbuf,offset,outbuf); } else { SSVAL(inbuf,offset,outbuf); } } } + +#undef CAREFUL_ALIGNMENT + +/* we know that the 386 can handle misalignment and has the "right" + byteorder */ +#ifdef __i386__ +#define CAREFUL_ALIGNMENT 0 +#endif + +#ifndef CAREFUL_ALIGNMENT +#define CAREFUL_ALIGNMENT 1 +#endif + +#define CVAL(buf,pos) (((unsigned char *)(buf))[pos]) +#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos)) +#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val)) + + +#if CAREFUL_ALIGNMENT + +#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8) +#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16) +#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8) +#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16)) +#define SVALS(buf,pos) ((int16)SVAL(buf,pos)) +#define IVALS(buf,pos) ((int32)IVAL(buf,pos)) +#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val))) +#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val))) +#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val))) +#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val))) + +#else /* CAREFUL_ALIGNMENT */ + +/* this handles things for architectures like the 386 that can handle + alignment errors */ +/* + WARNING: This section is dependent on the length of int16 and int32 + being correct +*/ + +/* get single value from an SMB buffer */ +#define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos))) +#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos))) +#define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos))) +#define IVALS(buf,pos) (*(int32 *)((char *)(buf) + (pos))) + +/* store single value in an SMB buffer */ +#define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16)(val)) +#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val)) +#define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val)) +#define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val)) + +#endif /* CAREFUL_ALIGNMENT */ + +/* macros for reading / writing arrays */ + +#define SMBMACRO(macro,buf,pos,val,len,size) \ +{ int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); } + +#define SSMBMACRO(macro,buf,pos,val,len,size) \ +{ int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); } + +/* reads multiple data from an SMB buffer */ +#define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1) +#define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2) +#define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4) +#define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1) +#define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2) +#define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4) + +/* stores multiple data in an SMB buffer */ +#define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1) +#define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2) +#define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4) +#define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1) +#define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2) +#define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4) + + +/* now the reverse routines - these are used in nmb packets (mostly) */ +#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) +#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16))) + +#define RSVAL(buf,pos) SREV(SVAL(buf,pos)) +#define RSVALS(buf,pos) SREV(SVALS(buf,pos)) +#define RIVAL(buf,pos) IREV(IVAL(buf,pos)) +#define RIVALS(buf,pos) IREV(IVALS(buf,pos)) +#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val)) +#define RSSVALS(buf,pos,val) SSVALS(buf,pos,SREV(val)) +#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val)) +#define RSIVALS(buf,pos,val) SIVALS(buf,pos,IREV(val)) + +/* reads multiple data from an SMB buffer (big-endian) */ +#define RPSVAL(buf,pos,val,len) SMBMACRO(RSVAL,buf,pos,val,len,2) +#define RPIVAL(buf,pos,val,len) SMBMACRO(RIVAL,buf,pos,val,len,4) +#define RPSVALS(buf,pos,val,len) SMBMACRO(RSVALS,buf,pos,val,len,2) +#define RPIVALS(buf,pos,val,len) SMBMACRO(RIVALS,buf,pos,val,len,4) + +/* stores multiple data in an SMB buffer (big-endian) */ +#define RPSSVAL(buf,pos,val,len) SSMBMACRO(RSSVAL,buf,pos,val,len,2) +#define RPSIVAL(buf,pos,val,len) SSMBMACRO(RSIVAL,buf,pos,val,len,4) +#define RPSSVALS(buf,pos,val,len) SSMBMACRO(RSSVALS,buf,pos,val,len,2) +#define RPSIVALS(buf,pos,val,len) SSMBMACRO(RSIVALS,buf,pos,val,len,4) + +#define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \ + { RW_PCVAL(read,inbuf,outbuf,len) \ + DEBUG(5,("%s%04x %s: ", \ + tab_depth(depth), base,string)); \ + if (charmode) print_asc(5, (unsigned char*)(outbuf), (len)); else \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \ + DEBUG(5,("\n")); } + +#define DBG_RW_PSVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \ + { RW_PSVAL(read,big_endian,inbuf,outbuf,len) \ + DEBUG(5,("%s%04x %s: ", \ + tab_depth(depth), base,string)); \ + if (charmode) print_asc(5, (unsigned char*)(outbuf), 2*(len)); else \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \ + DEBUG(5,("\n")); } + +#define DBG_RW_PIVAL(charmode,string,depth,base,read,big_endian,inbuf,outbuf,len) \ + { RW_PIVAL(read,big_endian,inbuf,outbuf,len) \ + DEBUG(5,("%s%04x %s: ", \ + tab_depth(depth), base,string)); \ + if (charmode) print_asc(5, (unsigned char*)(outbuf), 4*(len)); else \ + { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \ + DEBUG(5,("\n")); } + +#define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \ + { RW_CVAL(read,inbuf,outbuf,0) \ + DEBUG(5,("%s%04x %s: %02x\n", \ + tab_depth(depth), base, string, outbuf)); } + +#define DBG_RW_SVAL(string,depth,base,read,big_endian,inbuf,outbuf) \ + { RW_SVAL(read,big_endian,inbuf,outbuf,0) \ + DEBUG(5,("%s%04x %s: %04x\n", \ + tab_depth(depth), base, string, outbuf)); } + +#define DBG_RW_IVAL(string,depth,base,read,big_endian,inbuf,outbuf) \ + { RW_IVAL(read,big_endian,inbuf,outbuf,0) \ + DEBUG(5,("%s%04x %s: %08x\n", \ + tab_depth(depth), base, string, outbuf)); } + +#endif /* _BYTEORDER_H */ diff --git a/libntlm-0.21/smbdes.c b/libntlm-0.21/smbdes.c new file mode 100644 index 00000000..e3ab78af --- /dev/null +++ b/libntlm-0.21/smbdes.c @@ -0,0 +1,399 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + + a partial implementation of DES designed for use in the + SMB authentication protocol + + Copyright (C) Andrew Tridgell 1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "smbdes.h" + +/* NOTES: + + This code makes no attempt to be fast! In fact, it is a very + slow implementation + + This code is NOT a complete DES implementation. It implements only + the minimum necessary for SMB authentication, as used by all SMB + products (including every copy of Microsoft Windows95 ever sold) + + In particular, it can only do a unchained forward DES pass. This + means it is not possible to use this code for encryption/decryption + of data, instead it is only useful as a "hash" algorithm. + + There is no entry point into this code that allows normal DES operation. + + I believe this means that this code does not come under ITAR + regulations but this is NOT a legal opinion. If you are concerned + about the applicability of ITAR regulations to this code then you + should confirm it for yourself (and maybe let me know if you come + up with a different answer to the one above) +*/ + + +#define uchar unsigned char + +static uchar perm1[56] = {57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4}; + +static uchar perm2[48] = {14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32}; + +static uchar perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7}; + +static uchar perm4[48] = { 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1}; + +static uchar perm5[32] = { 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25}; + + +static uchar perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25}; + + +static uchar sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1}; + +static uchar sbox[8][4][16] = { + {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7}, + {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8}, + {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0}, + {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}}, + + {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10}, + {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5}, + {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15}, + {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}}, + + {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8}, + {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1}, + {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7}, + {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}}, + + {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15}, + {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9}, + {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4}, + {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}}, + + {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9}, + {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6}, + {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14}, + {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}}, + + {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11}, + {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8}, + {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6}, + {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}}, + + {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1}, + {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6}, + {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2}, + {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}}, + + {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7}, + {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2}, + {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8}, + {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}}; + +static void permute(char *out, char *in, uchar *p, int n) +{ + int i; + for (i=0;i>1; + key[1] = ((str[0]&0x01)<<6) | (str[1]>>2); + key[2] = ((str[1]&0x03)<<5) | (str[2]>>3); + key[3] = ((str[2]&0x07)<<4) | (str[3]>>4); + key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5); + key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6); + key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7); + key[7] = str[6]&0x7F; + for (i=0;i<8;i++) { + key[i] = (key[i]<<1); + } +} + + +static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key, int forw) +{ + int i; + char outb[64]; + char inb[64]; + char keyb[64]; + unsigned char key2[8]; + + str_to_key(key, key2); + + for (i=0;i<64;i++) { + inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0; + keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0; + outb[i] = 0; + } + + dohash(outb, inb, keyb, forw); + + for (i=0;i<8;i++) { + out[i] = 0; + } + + for (i=0;i<64;i++) { + if (outb[i]) + out[i/8] |= (1<<(7-(i%8))); + } +} + +void E_P16(unsigned char *p14,unsigned char *p16) +{ + unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25}; + smbhash(p16, sp8, p14, 1); + smbhash(p16+8, sp8, p14+7, 1); +} + +void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24) +{ + smbhash(p24, c8, p21, 1); + smbhash(p24+8, c8, p21+7, 1); + smbhash(p24+16, c8, p21+14, 1); +} + +void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out) +{ + smbhash(out, in, p14, 0); + smbhash(out+8, in+8, p14+7, 0); +} + +void E_old_pw_hash( unsigned char *p14, unsigned char *in, unsigned char *out) +{ + smbhash(out, in, p14, 1); + smbhash(out+8, in+8, p14+7, 1); +} + +void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key) +{ + unsigned char buf[8]; + + smbhash(buf, in, key, 1); + smbhash(out, buf, key+9, 1); +} + +void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key) +{ + unsigned char buf[8]; + static unsigned char key2[8]; + + smbhash(buf, in, key, 1); + key2[0] = key[7]; + smbhash(out, buf, key2, 1); +} + +void cred_hash3(unsigned char *out,unsigned char *in,unsigned char *key, int forw) +{ + static unsigned char key2[8]; + + smbhash(out, in, key, forw); + key2[0] = key[7]; + smbhash(out + 8, in + 8, key2, forw); +} + +void SamOEMhash( unsigned char *data, unsigned char *key, int val) +{ + unsigned char s_box[256]; + unsigned char index_i = 0; + unsigned char index_j = 0; + unsigned char j = 0; + int ind; + + for (ind = 0; ind < 256; ind++) + { + s_box[ind] = (unsigned char)ind; + } + + for( ind = 0; ind < 256; ind++) + { + unsigned char tc; + + j += (s_box[ind] + key[ind%16]); + + tc = s_box[ind]; + s_box[ind] = s_box[j]; + s_box[j] = tc; + } + for( ind = 0; ind < (val ? 516 : 16); ind++) + { + unsigned char tc; + unsigned char t; + + index_i++; + index_j += s_box[index_i]; + + tc = s_box[index_i]; + s_box[index_i] = s_box[index_j]; + s_box[index_j] = tc; + + t = s_box[index_i] + s_box[index_j]; + data[ind] = data[ind] ^ s_box[t]; + } +} diff --git a/libntlm-0.21/smbdes.h b/libntlm-0.21/smbdes.h new file mode 100644 index 00000000..f890fcd5 --- /dev/null +++ b/libntlm-0.21/smbdes.h @@ -0,0 +1,9 @@ + +extern void E_P16(unsigned char *p14,unsigned char *p16); +extern void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24); +extern void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out); +extern void E_old_pw_hash( unsigned char *p14, unsigned char *in, unsigned char *out); +extern void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key); +extern void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key); +extern void cred_hash3(unsigned char *out,unsigned char *in,unsigned char *key, int forw); +extern void SamOEMhash( unsigned char *data, unsigned char *key, int val); diff --git a/libntlm-0.21/smbencrypt.c b/libntlm-0.21/smbencrypt.c new file mode 100644 index 00000000..e58f0d41 --- /dev/null +++ b/libntlm-0.21/smbencrypt.c @@ -0,0 +1,323 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1998 + Modified by Jeremy Allison 1995. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#define DEBUG(a,b) ; + +extern int DEBUGLEVEL; + +#include +#include +#include +#include +#include "smbbyteorder.h" +#include "smbdes.h" +#include "smbmd4.h" + +typedef unsigned char uchar; +typedef signed short int16; +typedef unsigned short uint16; +typedef int BOOL; +#define False 0 +#define True 1 + +/**************************************************************************** + Like strncpy but always null terminates. Make sure there is room! + The variable n should always be one less than the available size. +****************************************************************************/ + +char *StrnCpy(char *dest,const char *src, size_t n) +{ + char *d = dest; + if (!dest) return(NULL); + if (!src) { + *dest = 0; + return(dest); + } + while (n-- && (*d++ = *src++)) ; + *d = 0; + return(dest); +} + +size_t skip_multibyte_char(char c) +{ +return 0; +} + + +/******************************************************************* +safe string copy into a known length string. maxlength does not +include the terminating zero. +********************************************************************/ + +char *safe_strcpy(char *dest,const char *src, size_t maxlength) +{ + size_t len; + + if (!dest) { + DEBUG(0,("ERROR: NULL dest in safe_strcpy\n")); + return NULL; + } + + if (!src) { + *dest = 0; + return dest; + } + + len = strlen(src); + + if (len > maxlength) { + DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n", + (int)(len-maxlength), src)); + len = maxlength; + } + + memcpy(dest, src, len); + dest[len] = 0; + return dest; +} + + +void strupper(char *s) +{ +while (*s) + { + { + size_t skip = skip_multibyte_char( *s ); + if( skip != 0 ) + s += skip; + else + { + if (islower(*s)) + *s = toupper(*s); + s++; + } + } + } +} + +extern void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24]); + +/* + This implements the X/Open SMB password encryption + It takes a password, a 8 byte "crypt key" and puts 24 bytes of + encrypted password into p24 + */ + +void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24) + { + uchar p14[15], p21[21]; + + memset(p21,'\0',21); + memset(p14,'\0',14); + StrnCpy((char *)p14,(char *)passwd,14); + + strupper((char *)p14); + E_P16(p14, p21); + + SMBOWFencrypt(p21, c8, p24); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("SMBencrypt: lm#, challenge, response\n")); + dump_data(100, (char *)p21, 16); + dump_data(100, (char *)c8, 8); + dump_data(100, (char *)p24, 24); +#endif + } + +/* Routines for Windows NT MD4 Hash functions. */ +static int _my_wcslen(int16 *str) +{ + int len = 0; + while(*str++ != 0) + len++; + return len; +} + +/* + * Convert a string into an NT UNICODE string. + * Note that regardless of processor type + * this must be in intel (little-endian) + * format. + */ + +static int _my_mbstowcs(int16 *dst, uchar *src, int len) +{ + int i; + int16 val; + + for(i = 0; i < len; i++) { + val = *src; + SSVAL(dst,0,val); + dst++; + src++; + if(val == 0) + break; + } + return i; +} + +/* + * Creates the MD4 Hash of the users password in NT UNICODE. + */ + +void E_md4hash(uchar *passwd, uchar *p16) +{ + int len; + int16 wpwd[129]; + + /* Password cannot be longer than 128 characters */ + len = strlen((char *)passwd); + if(len > 128) + len = 128; + /* Password must be converted to NT unicode */ + _my_mbstowcs(wpwd, passwd, len); + wpwd[len] = 0; /* Ensure string is null terminated */ + /* Calculate length in bytes */ + len = _my_wcslen(wpwd) * sizeof(int16); + + mdfour(p16, (unsigned char *)wpwd, len); +} + +/* Does both the NT and LM owfs of a user's password */ +void nt_lm_owf_gen(char *pwd, uchar nt_p16[16], uchar p16[16]) +{ + char passwd[130]; + + memset(passwd,'\0',130); + safe_strcpy( passwd, pwd, sizeof(passwd)-1); + + /* Calculate the MD4 hash (NT compatible) of the password */ + memset(nt_p16, '\0', 16); + E_md4hash((uchar *)passwd, nt_p16); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("nt_lm_owf_gen: pwd, nt#\n")); + dump_data(120, passwd, strlen(passwd)); + dump_data(100, (char *)nt_p16, 16); +#endif + + /* Mangle the passwords into Lanman format */ + passwd[14] = '\0'; + strupper(passwd); + + /* Calculate the SMB (lanman) hash functions of the password */ + + memset(p16, '\0', 16); + E_P16((uchar *) passwd, (uchar *)p16); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("nt_lm_owf_gen: pwd, lm#\n")); + dump_data(120, passwd, strlen(passwd)); + dump_data(100, (char *)p16, 16); +#endif + /* clear out local copy of user's password (just being paranoid). */ + memset(passwd, '\0', sizeof(passwd)); +} + +/* Does the des encryption from the NT or LM MD4 hash. */ +void SMBOWFencrypt(uchar passwd[16], uchar *c8, uchar p24[24]) +{ + uchar p21[21]; + + memset(p21,'\0',21); + + memcpy(p21, passwd, 16); + E_P24(p21, c8, p24); +} + +/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ +void NTLMSSPOWFencrypt(uchar passwd[8], uchar *ntlmchalresp, uchar p24[24]) +{ + uchar p21[21]; + + memset(p21,'\0',21); + memcpy(p21, passwd, 8); + memset(p21 + 8, 0xbd, 8); + + E_P24(p21, ntlmchalresp, p24); +#ifdef DEBUG_PASSWORD + DEBUG(100,("NTLMSSPOWFencrypt: p21, c8, p24\n")); + dump_data(100, (char *)p21, 21); + dump_data(100, (char *)ntlmchalresp, 8); + dump_data(100, (char *)p24, 24); +#endif +} + + +/* Does the NT MD4 hash then des encryption. */ + +void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24) +{ + uchar p21[21]; + + memset(p21,'\0',21); + + E_md4hash(passwd, p21); + SMBOWFencrypt(p21, c8, p24); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("SMBNTencrypt: nt#, challenge, response\n")); + dump_data(100, (char *)p21, 16); + dump_data(100, (char *)c8, 8); + dump_data(100, (char *)p24, 24); +#endif +} + +#if 0 + +BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[16], BOOL unicode) +{ + int new_pw_len = strlen(passwd) * (unicode ? 2 : 1); + + if (new_pw_len > 512) + { + DEBUG(0,("make_oem_passwd_hash: new password is too long.\n")); + return False; + } + + /* + * Now setup the data area. + * We need to generate a random fill + * for this area to make it harder to + * decrypt. JRA. + */ + generate_random_buffer((unsigned char *)data, 516, False); + if (unicode) + { + struni2( &data[512 - new_pw_len], passwd); + } + else + { + fstrcpy( &data[512 - new_pw_len], passwd); + } + SIVAL(data, 512, new_pw_len); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("make_oem_passwd_hash\n")); + dump_data(100, data, 516); +#endif + SamOEMhash( (unsigned char *)data, (unsigned char *)old_pw_hash, True); + + return True; +} + +#endif diff --git a/libntlm-0.21/smbencrypt.h b/libntlm-0.21/smbencrypt.h new file mode 100644 index 00000000..0f33b062 --- /dev/null +++ b/libntlm-0.21/smbencrypt.h @@ -0,0 +1,2 @@ +void SMBencrypt(char *passwd, uint8 *c8, uint8 *p24); +void SMBNTencrypt(char *passwd, uint8 *c8, uint8 *p24); diff --git a/libntlm-0.21/smbmd4.c b/libntlm-0.21/smbmd4.c new file mode 100644 index 00000000..f43d797d --- /dev/null +++ b/libntlm-0.21/smbmd4.c @@ -0,0 +1,172 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + a implementation of MD4 designed for use in the SMB authentication protocol + Copyright (C) Andrew Tridgell 1997-1998. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "smbmd4.h" + +typedef unsigned uint32; + +/* NOTE: This code makes no attempt to be fast! + + It assumes that a int is at least 32 bits long +*/ + +static uint32 A, B, C, D; + +static uint32 F(uint32 X, uint32 Y, uint32 Z) +{ + return (X&Y) | ((~X)&Z); +} + +static uint32 G(uint32 X, uint32 Y, uint32 Z) +{ + return (X&Y) | (X&Z) | (Y&Z); +} + +static uint32 H(uint32 X, uint32 Y, uint32 Z) +{ + return X^Y^Z; +} + +static uint32 lshift(uint32 x, int s) +{ + x &= 0xFFFFFFFF; + return ((x<>(32-s)); +} + +#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s) +#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s) +#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s) + +/* this applies md4 to 64 byte chunks */ +static void mdfour64(uint32 *M) +{ + int j; + uint32 AA, BB, CC, DD; + uint32 X[16]; + + for (j=0;j<16;j++) + X[j] = M[j]; + + AA = A; BB = B; CC = C; DD = D; + + ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7); + ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19); + ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7); + ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19); + ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7); + ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19); + ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7); + ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19); + + ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5); + ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13); + ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5); + ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13); + ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5); + ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13); + ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5); + ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13); + + ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9); + ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15); + ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9); + ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15); + ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9); + ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15); + ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9); + ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15); + + A += AA; B += BB; C += CC; D += DD; + + A &= 0xFFFFFFFF; B &= 0xFFFFFFFF; + C &= 0xFFFFFFFF; D &= 0xFFFFFFFF; + + for (j=0;j<16;j++) + X[j] = 0; +} + +static void copy64(uint32 *M, unsigned char *in) +{ + int i; + + for (i=0;i<16;i++) + M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) | + (in[i*4+1]<<8) | (in[i*4+0]<<0); +} + +static void copy4(unsigned char *out,uint32 x) +{ + out[0] = x&0xFF; + out[1] = (x>>8)&0xFF; + out[2] = (x>>16)&0xFF; + out[3] = (x>>24)&0xFF; +} + +/* produce a md4 message digest from data of length n bytes */ +void mdfour(unsigned char *out, unsigned char *in, int n) +{ + unsigned char buf[128]; + uint32 M[16]; + uint32 b = n * 8; + int i; + + A = 0x67452301; + B = 0xefcdab89; + C = 0x98badcfe; + D = 0x10325476; + + while (n > 64) { + copy64(M, in); + mdfour64(M); + in += 64; + n -= 64; + } + + for (i=0;i<128;i++) + buf[i] = 0; + memcpy(buf, in, n); + buf[n] = 0x80; + + if (n <= 55) { + copy4(buf+56, b); + copy64(M, buf); + mdfour64(M); + } else { + copy4(buf+120, b); + copy64(M, buf); + mdfour64(M); + copy64(M, buf+64); + mdfour64(M); + } + + for (i=0;i<128;i++) + buf[i] = 0; + copy64(M, buf); + + copy4(out, A); + copy4(out+4, B); + copy4(out+8, C); + copy4(out+12, D); + + A = B = C = D = 0; +} + + diff --git a/libntlm-0.21/smbmd4.h b/libntlm-0.21/smbmd4.h new file mode 100644 index 00000000..af739949 --- /dev/null +++ b/libntlm-0.21/smbmd4.h @@ -0,0 +1 @@ +extern void mdfour(unsigned char *out, unsigned char *in, int n); diff --git a/libntlm-0.21/smbutil.c b/libntlm-0.21/smbutil.c new file mode 100644 index 00000000..415e0665 --- /dev/null +++ b/libntlm-0.21/smbutil.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include +#include "ntlm.h" +#include "smbencrypt.h" +#include "smbbyteorder.h" + +char versionString[] ="libntlm version 0.21"; + +/* Utility routines that handle NTLM auth structures. */ + +/* The [IS]VAL macros are to take care of byte order for non-Intel + * Machines -- I think this file is OK, but it hasn't been tested. + * The other files (the ones stolen from Samba) should be OK. + */ + + +/* I am not crazy about these macros -- they seem to have gotten + * a bit complex. A new scheme for handling string/buffer fields + * in the structures probably needs to be designed + */ + +#define AddBytes(ptr, header, buf, count) \ +{ \ +if (buf && count) \ + { \ + SSVAL(&ptr->header.len,0,count); \ + SSVAL(&ptr->header.maxlen,0,count); \ + SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8*)ptr)) + ptr->bufIndex)); \ + memcpy(ptr->buffer+ptr->bufIndex, buf, count); \ + ptr->bufIndex += count; \ + } \ +else \ + { \ + ptr->header.len = \ + ptr->header.maxlen = 0; \ + SIVAL(&ptr->header.offset,0,ptr->bufIndex); \ + } \ +} + +#define AddString(ptr, header, string) \ +{ \ +char *p = string; \ +int len = 0; \ +if (p) len = strlen(p); \ +AddBytes(ptr, header, ((unsigned char*)p), len); \ +} + +#define AddUnicodeString(ptr, header, string) \ +{ \ +char *p = string; \ +unsigned char *b = NULL; \ +int len = 0; \ +if (p) \ + { \ + len = strlen(p); \ + b = strToUnicode(p); \ + } \ +AddBytes(ptr, header, b, len*2); \ +} + + +#define GetUnicodeString(structPtr, header) \ +unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2) +#define GetString(structPtr, header) \ +toString((((char *)structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0)) +#define DumpBuffer(fp, structPtr, header) \ +dumpRaw(fp,((unsigned char*)structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0)) + + +static void dumpRaw(FILE *fp, unsigned char *buf, size_t len) + { + int i; + + for (i=0; iident); + fprintf(fp," mType = %d\n",IVAL(&request->msgType,0)); + fprintf(fp," Flags = %08x\n",IVAL(&request->flags,0)); + fprintf(fp," User = %s\n",GetString(request,user)); + fprintf(fp," Domain = %s\n",GetString(request,domain)); + } + +void dumpSmbNtlmAuthChallenge(FILE *fp, tSmbNtlmAuthChallenge *challenge) + { + fprintf(fp,"NTLM Challenge:\n"); + fprintf(fp," Ident = %s\n",challenge->ident); + fprintf(fp," mType = %d\n",IVAL(&challenge->msgType,0)); + fprintf(fp," Domain = %s\n",GetUnicodeString(challenge,uDomain)); + fprintf(fp," Flags = %08x\n",IVAL(&challenge->flags,0)); + fprintf(fp," Challenge = "); dumpRaw(fp, challenge->challengeData,8); + } + +void dumpSmbNtlmAuthResponse(FILE *fp, tSmbNtlmAuthResponse *response) + { + fprintf(fp,"NTLM Response:\n"); + fprintf(fp," Ident = %s\n",response->ident); + fprintf(fp," mType = %d\n",IVAL(&response->msgType,0)); + fprintf(fp," LmResp = "); DumpBuffer(fp,response,lmResponse); + fprintf(fp," NTResp = "); DumpBuffer(fp,response,ntResponse); + fprintf(fp," Domain = %s\n",GetUnicodeString(response,uDomain)); + fprintf(fp," User = %s\n",GetUnicodeString(response,uUser)); + fprintf(fp," Wks = %s\n",GetUnicodeString(response,uWks)); + fprintf(fp," sKey = "); DumpBuffer(fp, response,sessionKey); + fprintf(fp," Flags = %08x\n",IVAL(&response->flags,0)); + } + +void buildSmbNtlmAuthRequest(tSmbNtlmAuthRequest *request, char *user, char *domain) + { + char *u = strdup(user); + char *p = strchr(u,'@'); + + if (p) + { + if (!domain) + domain = p+1; + *p = '\0'; + } + + request->bufIndex = 0; + memcpy(request->ident,"NTLMSSP\0\0\0",8); + SIVAL(&request->msgType,0,1); + SIVAL(&request->flags,0,0x0000b207); /* have to figure out what these mean */ + AddString(request,user,u); + AddString(request,domain,domain); + free(u); + } + +void buildSmbNtlmAuthResponse(tSmbNtlmAuthChallenge *challenge, tSmbNtlmAuthResponse *response, char *user, char *password) + { + uint8 lmRespData[24]; + uint8 ntRespData[24]; + char *d = strdup(GetUnicodeString(challenge,uDomain)); + char *domain = d; + char *u = strdup(user); + char *p = strchr(u,'@'); + + if (p) + { + domain = p+1; + *p = '\0'; + } + + SMBencrypt(password, challenge->challengeData, lmRespData); + SMBNTencrypt(password, challenge->challengeData, ntRespData); + + response->bufIndex = 0; + memcpy(response->ident,"NTLMSSP\0\0\0",8); + SIVAL(&response->msgType,0,3); + + AddBytes(response,lmResponse,lmRespData,24); + AddBytes(response,ntResponse,ntRespData,24); + AddUnicodeString(response,uDomain,domain); + AddUnicodeString(response,uUser,u); + AddUnicodeString(response,uWks,u); + AddString(response,sessionKey,NULL); + + response->flags = challenge->flags; + + free(d); + free(u); + } + diff --git a/libntlm-0.21/test/COPYING b/libntlm-0.21/test/COPYING new file mode 100755 index 00000000..a43ea212 --- /dev/null +++ b/libntlm-0.21/test/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/libntlm-0.21/test/Makefile b/libntlm-0.21/test/Makefile new file mode 100644 index 00000000..d99dcb09 --- /dev/null +++ b/libntlm-0.21/test/Makefile @@ -0,0 +1,6 @@ +dumper: dumper.c getargs.o + gcc -g -I.. -o dumper dumper.c getargs.o ../libntlm.a + +clean: + rm -f *.a *.o dumper *.bak *~ \#*\# + diff --git a/libntlm-0.21/test/README b/libntlm-0.21/test/README new file mode 100644 index 00000000..bcff72ac --- /dev/null +++ b/libntlm-0.21/test/README @@ -0,0 +1,19 @@ + +Dumper is a simple command line utility to display in readable +format base64 NTLM messages. Given a base64 NTLM challenge, a +username and a password, it will optionally generate and +display a response message. + +Note that there are multiple correct response messages message +depending on what order the string data is placed at the end of +the frame. There is no required order. Dumper should always +generate the string data in the same order (and thus identical +base64 responses), even on different architectures. + +It's possible that another application will generate a +different but also correct response message. + +Run "dumper -?" for help. + +Someday I'll write more documentation... + diff --git a/libntlm-0.21/test/dumper.c b/libntlm-0.21/test/dumper.c new file mode 100644 index 00000000..aa84d127 --- /dev/null +++ b/libntlm-0.21/test/dumper.c @@ -0,0 +1,237 @@ +#include +#include +#include +#include + +#include "getargs.h" + +int from64tobits(char *out, const char *in); +void to64frombits(unsigned char *out, const unsigned char *in, int inlen); + +int dumpReq; +int dumpChal; +int dumpResp; +int genResp; +int dumpRaw; +int dumpb64only; +int genReq; + +char *username = "joeuser"; +char *password = "joespw"; + +argSpec argSpecArray[] = +{ + {'q', OptionBoolean, &dumpReq, NULL, "dump NTLM request", NULL}, + {'Q', OptionBoolean, &genReq, NULL, "generate (and dump) NTLM request", NULL}, + {'c', OptionBoolean, &dumpChal, NULL, "dump NTLM challange", NULL}, + {'g', OptionBoolean, &genResp, NULL, "generate (and dump) NTLM response given a challenge", NULL}, + {'r', OptionBoolean, &dumpResp, NULL, "dump NTLM response", NULL}, + {'R', OptionBoolean, &dumpRaw, NULL, "dump raw bytes", NULL}, + {'6', OptionBoolean, &dumpb64only, NULL, "dump generated base64 only", NULL}, + {'u', OptionString, &username, NULL, "username", NULL}, + {'p', OptionString, &password, NULL, "password", NULL}, +}; + +int argSpecCount = (sizeof argSpecArray / sizeof argSpecArray[0]); +char *progName; + +void usage(void) +{ + printf("usage: %s [options] [base-64-string]\n", progName); + printf(" %s -? will display options\n", progName); +} + +unsigned char buf[4096]; +unsigned char buf2[4096]; + +int main(int argc, char *argv[]) +{ + int rawLen = 0; + int argsUsed; + int i; + + progName = argv[0]; + + argsUsed = getargs(argc, argv, argSpecArray, argSpecCount); + + if (argsUsed < 0) + { + usage(); + exit(1); + } + + argc -= argsUsed; + argv += argsUsed; + + if (argc != 1 && argc != 0) + { + usage(); + exit(1); + } + + + if (argc == 1) + { + rawLen = from64tobits(buf,argv[0]); + if (genReq) + fprintf(stderr,"%s: extra argument with -Q ignored\n",progName); + } + else + { + if (dumpReq || dumpChal || dumpResp || dumpRaw) + { + fprintf(stderr,"%s: -q -r -c -R specified but no base64 data\n",progName); + return 1; + } + } + + + printf("Converted base64 string to %d data bytes\n",rawLen); + + if (dumpReq) + dumpSmbNtlmAuthRequest(stdout,(tSmbNtlmAuthRequest*)buf); + else if (dumpChal) + dumpSmbNtlmAuthChallenge(stdout,(tSmbNtlmAuthChallenge*)buf); + else if (dumpResp) + dumpSmbNtlmAuthResponse(stdout,(tSmbNtlmAuthResponse*)buf); + + if (dumpRaw) + for (i=0; i= 3; inlen -= 3) + { + *out++ = base64digits[in[0] >> 2]; + *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)]; + *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; + *out++ = base64digits[in[2] & 0x3f]; + in += 3; + } + if (inlen > 0) + { + unsigned char fragment; + + *out++ = base64digits[in[0] >> 2]; + fragment = (in[0] << 4) & 0x30; + if (inlen > 1) + fragment |= in[1] >> 4; + *out++ = base64digits[fragment]; + *out++ = (inlen < 2) ? '=' : base64digits[(in[1] << 2) & 0x3c]; + *out++ = '='; + } + *out = '\0'; +} + +int from64tobits(char *out, const char *in) +/* base 64 to raw bytes in quasi-big-endian order, returning count of bytes */ +{ + int len = 0; + register unsigned char digit1, digit2, digit3, digit4; + + if (in[0] == '+' && in[1] == ' ') + in += 2; + if (*in == '\r') + return(0); + + do { + digit1 = in[0]; + if (DECODE64(digit1) == BAD) + return(-1); + digit2 = in[1]; + if (DECODE64(digit2) == BAD) + return(-1); + digit3 = in[2]; + if (digit3 != '=' && DECODE64(digit3) == BAD) + return(-1); + digit4 = in[3]; + if (digit4 != '=' && DECODE64(digit4) == BAD) + return(-1); + in += 4; + *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4); + ++len; + if (digit3 != '=') + { + *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2); + ++len; + if (digit4 != '=') + { + *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4); + ++len; + } + } + } while + (*in && *in != '\r' && digit4 != '='); + + return (len); +} + +/* base64.c ends here */ diff --git a/libntlm-0.21/test/getargs.c b/libntlm-0.21/test/getargs.c new file mode 100644 index 00000000..ca81fc4d --- /dev/null +++ b/libntlm-0.21/test/getargs.c @@ -0,0 +1,240 @@ +#include "getargs.h" +#include +#include + +double dummy(double x) +{ +return x * 56.7; +} + +static int findString(char *name, char **namelist) + { + int i; + + for (i=0; *namelist; ++namelist, ++i) + if (!strcmp(name, *namelist)) + return i; + return -1; + } + +static char *progName; + +typedef int (*fptrNoParam)(void); +typedef int (*fptrParam)(char*); + +static void errorMsg(char c, const char *expected, const char *got) + { + fprintf(stderr,"%s: option -%c expected %s parameter, got '%s'\n",progName,c,expected,got); + } + +static void prOptions(argSpec arg[], int specCount) + { + int i; + fprintf(stderr,"%s: options: \n",progName); + + for (i=0; i "); break; + case OptionLong: fprintf(stderr," "); break; + case OptionDouble: fprintf(stderr," "); break; + case OptionString: fprintf(stderr," "); break; + case OptionBoolean: fprintf(stderr," "); break; + case OptionEnumerated: fprintf(stderr," "); break; + } + fprintf(stderr,arg[i].helpString); + if (arg[i].optionType == OptionEnumerated) + { + char **s; + int d = *(unsigned*)arg[i].optionPtr; + int n; + fprintf(stderr,"\n"); + fprintf(stderr," where is one of:\n"); + for (n=0,s=arg[i].enumValues; *s; ++s,++n) + fprintf(stderr," %s%s\n",*s,n==d ? " (default)" : ""); + } + else + { + switch (arg[i].optionType) + { + case OptionInteger: fprintf(stderr," (default %d)\n",*(int*)arg[i].optionPtr); break; + case OptionLong: fprintf(stderr," (default %ld)\n",*(long*)arg[i].optionPtr); break; + case OptionDouble: fprintf(stderr," (default %f)\n",*(double*)arg[i].optionPtr); break; + case OptionString: fprintf(stderr," (default '%s')\n",*(char**)arg[i].optionPtr); break; + case OptionBoolean: fprintf(stderr,"\n"); break; + case OptionEnumerated: break; + } + } + } + } + +union + { + int i; + long l; + double d; + char *p; + }trash; + +int getargs(int argc, char *argv[], argSpec arg[], int specCount) + { + int argsUsed; + char *p; + int a; + int argDone; + + progName = argv[0]; + argsUsed = 1; + ++argv; + + while (argsUsed < argc) + { + /* at this point, argv[0] is the next item to be processed */ + + p = argv[0]; + + if (*p != '-') + return argsUsed; + + ++argsUsed; + ++argv; + + ++p; + + if (*p =='?') + { + prOptions(arg,specCount); + return -1; + } + + argDone = 0; + + for (a=0; a argc) + { + errorMsg(*p,"",""); + return -1; + } + } + + if (arg[a].optionPtr) + optionPtr = arg[a].optionPtr; + + switch (arg[a].optionType) + { + case OptionInteger: + { + char *format = "%d"; + if (optionArgPtr[0]=='x') + { + format = "%x"; + ++optionArgPtr; + } + else if (optionArgPtr[0]=='0' && optionArgPtr[1]=='x') + { + format = "%x"; + optionArgPtr+=2; + } + + if (sscanf(optionArgPtr,format,optionPtr) != 1) + { + errorMsg(*p,"integer",optionArgPtr); + return -1; + } + break; + } + + case OptionLong: + if (sscanf(optionArgPtr,"%ld",(long*)optionPtr) != 1) + { + errorMsg(*p,"long",optionArgPtr); + return -1; + } + break; + + case OptionString: + *((char**)optionPtr) = strdup(optionArgPtr); + break; + + case OptionDouble: + if (sscanf(optionArgPtr,"%lf",(double*)optionPtr) != 1) + { + errorMsg(*p,"floating point",optionArgPtr); + return -1; + } + break; + + case OptionBoolean: + *((int*)optionPtr) = 1; + break; + + case OptionEnumerated: + if ((*((int*)optionPtr) = findString(optionArgPtr,arg[a].enumValues)) < 0) + { + char **n = arg[a].enumValues; + fprintf(stderr,"%s: option -%c expects parameter to be one of:\n",progName,*p); + while (*n) + { + fprintf(stderr," %s\n",*n); + ++n; + } + return -1; + } + break; + + default: + break; + } + + if (arg[a].funcPtr) + { + int s = (*arg[a].funcPtr)(optionArgPtr); + if (s<0) + return s; + } + + if (arg[a].optionType == OptionBoolean) + { + ++p; + if (*p != '\0') + { + a = 0; + continue; + } + } + + argDone = 1; + break; + } + ++a; + } + + if (!argDone) + { + fprintf(stderr,"%s: unrecognized option '%c'\n",progName,*p); + prOptions(arg,specCount); + return -1; + } + } + return argsUsed; + } + diff --git a/libntlm-0.21/test/getargs.h b/libntlm-0.21/test/getargs.h new file mode 100644 index 00000000..1f5a1857 --- /dev/null +++ b/libntlm-0.21/test/getargs.h @@ -0,0 +1,19 @@ +typedef struct + { + char optionChar; + enum + { + OptionInteger, + OptionDouble, + OptionLong, + OptionString, + OptionBoolean, + OptionEnumerated + } optionType; + void *optionPtr; + int (*funcPtr)(char *param); + char *helpString; + char **enumValues; + }argSpec; + +extern int getargs(int argc, char *argv[], argSpec *arg, int numberSpecs); -- cgit v1.2.3