diff --git a/source/smb/DES.c b/source/smb/DES.c deleted file mode 100644 index 8095566..0000000 --- a/source/smb/DES.c +++ /dev/null @@ -1,726 +0,0 @@ -/* ========================================================================== ** - * - * DES.c - * - * Copyright: - * Copyright (C) 2003, 2004 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * - * $Id: DES.c,v 0.6 2004/05/30 05:41:20 crh Exp $ - * - * -------------------------------------------------------------------------- ** - * - * Description: - * - * Implements DES encryption, but not decryption. - * DES is used to create LM password hashes and both LM and NTLM Responses. - * - * -------------------------------------------------------------------------- ** - * - * License: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * -------------------------------------------------------------------------- ** - * - * Notes: - * - * This implementation was created by studying many existing examples - * found in Open Source, in the public domain, and in various documentation. - * The SMB protocol makes minimal use of the DES function, so this is a - * minimal implementation. That which is not required has been removed. - * - * The SMB protocol uses the DES algorithm as a hash function, not an - * encryption function. The auth_DEShash() implemented here is a one-way - * function. The reverse is not implemented in this module. Also, there - * is no attempt at making this either fast or efficient. There is no - * need, as the auth_DEShash() function is used for generating the LM - * Response from a 7-byte key and an 8-byte challenge. It is not intended - * for use in encrypting large blocks of data or data streams. - * - * As stated above, this implementation is based on studying existing work - * in the public domain or under Open Source (specifically LGPL) license. - * The code, however, is written from scratch. Obviously, I make no claim - * with regard to those earlier works (except to claim that I am grateful - * to the previous implementors whose work I studied). See the list of - * references below for resources I used. - * - * References: - * I read through the libmcrypt code to see how they put the pieces - * together. See: http://mcrypt.hellug.gr/ - * Libmcrypt is available under the terms of the LGPL. - * - * The libmcrypt implementation includes the following credits: - * written 12 Dec 1986 by Phil Karn, KA9Q; large sections adapted - * from the 1977 public-domain program by Jim Gillogly - * Modified for additional speed - 6 December 1988 Phil Karn - * Modified for parameterized key schedules - Jan 1991 Phil Karn - * modified in order to use the libmcrypt API by Nikos Mavroyanopoulos - * All modifications are placed under the license of libmcrypt. - * - * See also Phil Karn's privacy and security page: - * http://www.ka9q.net/privacy.html - * - * I relied heavily upon: - * Applied Cryptography, Second Edition: - * Protocols, Algorithms, and Source Code in C - * by Bruce Schneier. ISBN 0-471-11709-9, John Wiley & Sons, Inc., 1996 - * Particularly Chapter 12. - * - * Here's one more DES resource, which I found quite helpful (aside from - * the Clinton jokes): - * http://www.aci.net/kalliste/des.htm - * - * Finally, the use of DES in SMB is covered in: - * Implementing CIFS - the Common Internet File System - * by your truly. ISBN 0-13-047116-X, Prentice Hall PTR., August 2003 - * Section 15.3, in particular. - * (Online at: http://ubiqx.org/cifs/SMB.html#SMB.8.3) - * - * ========================================================================== ** - */ - -#include "DES.h" - - -/* -------------------------------------------------------------------------- ** - * Static Constants: - */ - -/* Initial permutation map. - * In the first step of DES, the bits of the initial plaintext are rearranged - * according to the map given below. This map and those like it are read by - * the Permute() function (below) which uses the maps as a guide when moving - * bits from one place to another. - * - * Note that the values here are all one less than those shown in Schneier. - * That's because C likes to start counting from 0, not 1. - * - * According to Schneier (Ch12, pg 271), the purpose of the initial - * permutation was to make it easier to load plaintext and ciphertext into - * a DES ecryption chip. I have no idea why that would be the case. - */ -static const uint8_t InitialPermuteMap[64] = - { - 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, - 56, 48, 40, 32, 24, 16, 8, 0, - 58, 50, 42, 34, 26, 18, 10, 2, - 60, 52, 44, 36, 28, 20, 12, 4, - 62, 54, 46, 38, 30, 22, 14, 6 - }; - - -/* Key permutation map. - * Like the input data and encryption result, the key is permuted before - * the algorithm really gets going. The original algorithm called for an - * eight-byte key in which each byte contained a parity bit. During the - * key permutiation, the parity bits were discarded. The DES algorithm, - * as used with SMB, does not make use of the parity bits. Instead, SMB - * passes 7-byte keys to DES. For DES implementations that expect parity, - * the parity bits must be added. In this case, however, we're just going - * to start with a 7-byte (56 bit) key. KeyPermuteMap, below, is adjusted - * accordingly and, of course, each entry in the map is reduced by 1 with - * respect to the documented values because C likes to start counting from - * 0, not 1. - */ -static const uint8_t KeyPermuteMap[56] = - { - 49, 42, 35, 28, 21, 14, 7, 0, - 50, 43, 36, 29, 22, 15, 8, 1, - 51, 44, 37, 30, 23, 16, 9, 2, - 52, 45, 38, 31, 55, 48, 41, 34, - 27, 20, 13, 6, 54, 47, 40, 33, - 26, 19, 12, 5, 53, 46, 39, 32, - 25, 18, 11, 4, 24, 17, 10, 3, - }; - - -/* Key rotation table. - * At the start of each round of encryption, the key is split and each - * 28-bit half is rotated left. The number of bits of rotation per round - * is given in the table below. - */ -static const uint8_t KeyRotation[16] = - { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 }; - - -/* Key compression table. - * This table is used to select 48 of the 56 bits of the key. - * The left and right halves of the source text are each 32 bits, - * but they are expanded to 48 bits and the results are XOR'd - * against the compressed (48-bit) key. - */ -static const uint8_t KeyCompression[48] = - { - 13, 16, 10, 23, 0, 4, 2, 27, - 14, 5, 20, 9, 22, 18, 11, 3, - 25, 7, 15, 6, 26, 19, 12, 1, - 40, 51, 30, 36, 46, 54, 29, 39, - 50, 44, 32, 47, 43, 48, 38, 55, - 33, 52, 45, 41, 49, 35, 28, 31 - }; - - -/* Data expansion table. - * This table is used after the data block (64-bits) has been split - * into two 32-bit (4-byte) halves (generally denoted L and R). - * Each 32-bit half is "expanded", using this table, to a 48 bit - * data block, which is then XOR'd with the 48 bit subkey for the - * round. - */ -static const uint8_t DataExpansion[48] = - { - 31, 0, 1, 2, 3, 4, 3, 4, - 5, 6, 7, 8, 7, 8, 9, 10, - 11, 12, 11, 12, 13, 14, 15, 16, - 15, 16, 17, 18, 19, 20, 19, 20, - 21, 22, 23, 24, 23, 24, 25, 26, - 27, 28, 27, 28, 29, 30, 31, 0 - }; - - -/* The (in)famous S-boxes. - * These are used to perform substitutions. - * Six bits worth of input will return four bits of output. - * The four bit values are stored in these tables. Each table has - * 64 entries...and 6 bits provides a number between 0 and 63. - * There are eight S-boxes, one per 6 bits of a 48-bit value. - * Thus, 48 bits are reduced to 32 bits. Obviously, this step - * follows the DataExpansion step. - * - * Note that the literature generally shows this as 8 arrays each - * with four rows and 16 colums. There is a complex formula for - * mapping the 6 bit input values to the correct row and column. - * I've pre-computed that mapping, and the tables below provide - * direct 6-bit input to 4-bit output. See pp 274-274 in Schneier. - */ -static const uint8_t SBox[8][64] = - { - { /* S0 */ - 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1, - 3, 10, 10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8, - 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7, - 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13 - }, - { /* S1 */ - 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14, - 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5, - 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2, - 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9 - }, - { /* S2 */ - 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10, - 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1, - 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7, - 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12 - }, - { /* S3 */ - 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3, - 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9, - 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8, - 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14 - }, - { /* S4 */ - 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1, - 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6, - 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13, - 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3 - }, - { /* S5 */ - 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5, - 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8, - 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10, - 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13 - }, - { /* S6 */ - 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10, - 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6, - 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7, - 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12 - }, - { /* S7 */ - 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4, - 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2, - 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13, - 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11 - } - }; - - -/* P-Box permutation. - * This permutation is applied to the result of the S-Box Substitutions. - * It's a straight-forward re-arrangement of the bits. - */ -static const uint8_t PBox[32] = - { - 15, 6, 19, 20, 28, 11, 27, 16, - 0, 14, 22, 25, 4, 17, 30, 9, - 1, 7, 23, 13, 31, 26, 2, 8, - 18, 12, 29, 5, 21, 10, 3, 24 - }; - - -/* Final permutation map. - * This is supposed to be the inverse of the Initial Permutation, - * but there's been a bit of fiddling done. - * As always, the values given are one less than those in the literature - * (because C starts counting from 0, not 1). In addition, the penultimate - * step in DES is to swap the left and right hand sides of the ciphertext. - * The inverse of the Initial Permutation is then applied to produce the - * final result. - * To save a step, the map below does the left/right swap as well as the - * inverse permutation. - */ -static const uint8_t FinalPermuteMap[64] = - { - 7, 39, 15, 47, 23, 55, 31, 63, - 6, 38, 14, 46, 22, 54, 30, 62, - 5, 37, 13, 45, 21, 53, 29, 61, - 4, 36, 12, 44, 20, 52, 28, 60, - 3, 35, 11, 43, 19, 51, 27, 59, - 2, 34, 10, 42, 18, 50, 26, 58, - 1, 33, 9, 41, 17, 49, 25, 57, - 0, 32, 8, 40, 16, 48, 24, 56 - }; - - -/* -------------------------------------------------------------------------- ** - * Macros: - * - * CLRBIT( STR, IDX ) - * Input: STR - (uchar *) pointer to an array of 8-bit bytes. - * IDX - (int) bitwise index of a bit within the STR array - * that is to be cleared (that is, given a value of 0). - * Notes: This macro clears a bit within an array of bits (which is - * built within an array of bytes). - * - The macro converts to an assignment of the form A &= B. - * - The string of bytes is viewed as an array of bits, read from - * highest order bit first. The highest order bit of a byte - * would, therefore, be bit 0 (within that byte). - * - * SETBIT( STR, IDX ) - * Input: STR - (uchar *) pointer to an array of 8-bit bytes. - * IDX - (int) bitwise index of a bit within the STR array - * that is to be set (that is, given a value of 1). - * Notes: This macro sets a bit within an array of bits (which is - * built within an array of bytes). - * - The macro converts to an assignment of the form A |= B. - * - The string of bytes is viewed as an array of bits, read from - * highest order bit first. The highest order bit of a byte - * would, therefore, be bit 0 (within that byte). - * - * GETBIT( STR, IDX ) - * Input: STR - (uchar *) pointer to an array of 8-bit bytes. - * IDX - (int) bit-wise index of a bit within the STR array - * that is to be read. - * Output: True (1) if the indexed bit was set, else false (0). - * - * -------------------------------------------------------------------------- ** - */ - -#define CLRBIT( STR, IDX ) ( (STR)[(IDX)/8] &= ~(0x01 << (7 - ((IDX)%8))) ) - -#define SETBIT( STR, IDX ) ( (STR)[(IDX)/8] |= (0x01 << (7 - ((IDX)%8))) ) - -#define GETBIT( STR, IDX ) (( ((STR)[(IDX)/8]) >> (7 - ((IDX)%8)) ) & 0x01) - - -/* -------------------------------------------------------------------------- ** - * Static Functions: - */ - -static void Permute( uchar *dst, - const uchar *src, - const uint8_t *map, - const int mapsize ) - /* ------------------------------------------------------------------------ ** - * Performs a DES permutation, which re-arranges the bits in an array of - * bytes. - * - * Input: dst - Destination into which to put the re-arranged bits. - * src - Source from which to read the bits. - * map - Permutation map. - * mapsize - Number of bytes represented by the . This also - * represents the number of bytes to be copied to . - * - * Output: none. - * - * Notes: and must not point to the same location. - * - * - No checks are done to ensure that there is enough room - * in , or that the bit numbers in do not exceed - * the bits available in . A good reason to make this - * function static (private). - * - * - The value is in bytes. All permutations in DES - * use tables that are a multiple of 8 bits, so there is no - * need to handle partial bytes. (Yes, I know that there - * are some machines out there that still use bytes of a size - * other than 8 bits. For our purposes we'll stick with 8-bit - * bytes.) - * - * ------------------------------------------------------------------------ ** - */ - { - int bitcount; - int i; - - /* Clear all bits in the destination. - */ - for( i = 0; i < mapsize; i++ ) - dst[i] = 0; - - /* Set destination bit if the mapped source bit it set. */ - bitcount = mapsize * 8; - for( i = 0; i < bitcount; i++ ) - { - if( GETBIT( src, map[i] ) ) - SETBIT( dst, i ); - } - } /* Permute */ - - -static void KeyShift( uchar *key, const int numbits ) - /* ------------------------------------------------------------------------ ** - * Split the 56-bit key in half & left rotate each half by bits. - * - * Input: key - The 56-bit key to be split-rotated. - * numbits - The number of bits by which to rotate the key. - * - * Output: none. - * - * Notes: There are probably several better ways to implement this. - * - * ------------------------------------------------------------------------ ** - */ - { - int i; - uchar keep = key[0]; /* Copy the highest order bits of the key. */ - - /* Repeat the shift process times. - */ - for( i = 0; i < numbits; i++ ) - { - int j; - - /* Shift the entire thing, byte by byte. - */ - for( j = 0; j < 7; j++ ) - { - if( j && (key[j] & 0x80) ) /* If the top bit of this byte is set. */ - key[j-1] |= 0x01; /* ...shift it to last byte's low bit. */ - key[j] <<= 1; /* Then left-shift the whole byte. */ - } - - /* Now move the high-order bits of each 28-bit half-key to their - * correct locations. - * Bit 27 is the lowest order bit of the first half-key. - * Before the shift, it was the highest order bit of the 2nd half-key. - */ - if( GETBIT( key, 27 ) ) /* If bit 27 is set... */ - { - CLRBIT( key, 27 ); /* ...clear bit 27. */ - SETBIT( key, 55 ); /* ...set lowest order bit of 2nd half-key. */ - } - - /* We kept the highest order bit of the first half-key in . - * If it's set, copy it to bit 27. - */ - if( keep & 0x80 ) - SETBIT( key, 27 ); - - /* Rotate the byte too, in case is 2 and there's - * a second round coming. - */ - keep <<= 1; - } - } /* KeyShift */ - - -static void sbox( uchar *dst, const uchar *src ) - /* ------------------------------------------------------------------------ ** - * Perform S-Box substitutions. - * - * Input: dst - Destination byte array into which the S-Box substituted - * bitmap will be written. - * src - Source byte array. - * - * Output: none. - * - * Notes: It's really not possible (for me, anyway) to understand how - * this works without reading one or more detailed explanations. - * Quick overview, though: - * - * After the DataExpansion step (in which a 32-bit bit array is - * expanded to a 48-bit bit array) the expanded data block is - * XOR'd with 48-bits worth of key. That 48 bits then needs to - * be condensed back into 32 bits. - * - * The S-Box substitution handles the data reduction by breaking - * the 48-bit value into eight 6-bit values. For each of these - * 6-bit values there is a table (an S-Box table). The table - * contains 64 possible values. Conveniently, a 6-bit integer - * can represent a value between 0 and 63. - * - * So, if you think of the 48-bit bit array as an array of 6-bit - * integers, you use S-Box table 0 with the 0th 6-bit value. - * Table 1 is used with the 6-bit value #1, and so on until #7. - * Within each table, the correct substitution is found based - * simply on the value of the 6-bit integer. - * - * Well, the original algorithm (and most documentation) don't - * make it so simple. There's a complex formula for mapping - * the 6-bit values to the correct substitution. Fortunately, - * those lookups can be precomputed (and have been for this - * implementation). See pp 274-274 in Schneier. - * - * Oh, and the substitute values are all 4-bit values, so each - * 6-bits gets reduced to 4-bits resulting in a 32-bit bit array. - * - * ------------------------------------------------------------------------ ** - */ - { - int i; - - /* Clear the destination array. - */ - for( i = 0; i < 4; i++ ) - dst[i] = 0; - - /* For each set of six input bits... - */ - for( i = 0; i < 8; i++ ) - { - int j; - int Snum; - int bitnum; - - /* Extract the 6-bit integer from the source. - * This will be the lookup key within the SBox[i] array. - */ - for( Snum = j = 0, bitnum = (i * 6); j < 6; j++, bitnum++ ) - { - Snum <<= 1; - Snum |= GETBIT( src, bitnum ); - } - - /* Find the correct value in the correct SBox[] - * and copy it into the destination. - * Left shift the nibble four bytes for even values of . - */ - if( 0 == (i%2) ) - dst[i/2] |= ((SBox[i][Snum]) << 4); - else - dst[i/2] |= SBox[i][Snum]; - } - } /* sbox */ - - -static void xor( uchar *dst, const uchar *a, const uchar *b, const int count ) - /* ------------------------------------------------------------------------ ** - * Perform an XOR operation on two byte arrays. - * - * Input: dst - Destination array to which the result will be written. - * a - The first string of bytes. - * b - The second string of bytes. - * count - Number of bytes to XOR against one another. - * - * Output: none. - * - * Notes: This function operates on whole byte chunks. There's no need - * to XOR partial bytes so no need to write code to handle it. - * - * - This function essentially implements dst = a ^ b; for byte - * arrays. - * - * - may safely point to the same location as or . - * - * ------------------------------------------------------------------------ ** - */ - { - int i; - - for( i = 0; i < count; i++ ) - dst[i] = a[i] ^ b[i]; - } /* xor */ - - -/* -------------------------------------------------------------------------- ** - * Functions: - */ - -uchar *auth_DESkey8to7( uchar *dst, const uchar *key ) - /* ------------------------------------------------------------------------ ** - * Compress an 8-byte DES key to its 7-byte form. - * - * Input: dst - Pointer to a memory location (minimum 7 bytes) to accept - * the compressed key. - * key - Pointer to an 8-byte DES key. See the notes below. - * - * Output: A pointer to the compressed key (same as ) or NULL if - * either or were NULL. - * - * Notes: There are no checks done to ensure that and point - * to sufficient space. Please be carefull. - * - * The two pointers, and may point to the same - * memory location. Internally, a temporary buffer is used and - * the results are copied back to . - * - * The DES algorithm uses 8 byte keys by definition. The first - * step in the algorithm, however, involves removing every eigth - * bit to produce a 56-bit key (seven bytes). SMB authentication - * skips this step and uses 7-byte keys. The - * algorithm in this module expects 7-byte keys. This function - * is used to convert an 8-byte DES key into a 7-byte SMB DES key. - * - * ------------------------------------------------------------------------ ** - */ - { - int i; - uchar tmp[7]; - static const uint8_t map8to7[56] = - { - 0, 1, 2, 3, 4, 5, 6, - 8, 9, 10, 11, 12, 13, 14, - 16, 17, 18, 19, 20, 21, 22, - 24, 25, 26, 27, 28, 29, 30, - 32, 33, 34, 35, 36, 37, 38, - 40, 41, 42, 43, 44, 45, 46, - 48, 49, 50, 51, 52, 53, 54, - 56, 57, 58, 59, 60, 61, 62 - }; - - if( (NULL == dst) || (NULL == key) ) - return( NULL ); - - Permute( tmp, key, map8to7, 7 ); - for( i = 0; i < 7; i++ ) - dst[i] = tmp[i]; - - return( dst ); - } /* auth_DESkey8to7 */ - - -uchar *auth_DEShash( uchar *dst, const uchar *key, const uchar *src ) - /* ------------------------------------------------------------------------ ** - * DES encryption of the input data using the input key. - * - * Input: dst - Destination buffer. It *must* be at least eight bytes - * in length, to receive the encrypted result. - * key - Encryption key. Exactly seven bytes will be used. - * If your key is shorter, ensure that you pad it to seven - * bytes. - * src - Source data to be encrypted. Exactly eight bytes will - * be used. If your source data is shorter, ensure that - * you pad it to eight bytes. - * - * Output: A pointer to the encrpyted data (same as ). - * - * Notes: In SMB, the DES function is used as a hashing function rather - * than an encryption/decryption tool. When used for generating - * the LM hash the input is the known value "KGS!@#$%" and - * the key is derived from the password entered by the user. - * When used to generate the LM or NTLM response, the is - * derived from the LM or NTLM hash, and the challenge is used - * as the input. - * See: http://ubiqx.org/cifs/SMB.html#SMB.8.3 - * - * - This function is called "DEShash" rather than just "DES" - * because it is only used for creating LM hashes and the - * LM/NTLM responses. For all practical purposes, however, it - * is a full DES encryption implementation. - * - * - This DES implementation does not need to be fast, nor is a - * DES decryption function needed. The goal is to keep the - * code small, simple, and well documented. - * - * - The input values are copied and refiddled within the module - * and the result is not written to until the very last - * step, so it's okay if points to the same memory as - * or . - * - * ------------------------------------------------------------------------ ** - */ - { - int i; /* Loop counter. */ - uchar K[7]; /* Holds the key, as we manipulate it. */ - uchar D[8]; /* The data block, as we manipulate it. */ - - /* Create the permutations of the key and the source. - */ - Permute( K, key, KeyPermuteMap, 7 ); - Permute( D, src, InitialPermuteMap, 8 ); - - /* DES encryption proceeds in 16 rounds. - * The stuff inside the loop is known in the literature as "function f". - */ - for( i = 0; i < 16; i++ ) - { - int j; - uchar *L = D; /* The left 4 bytes (half) of the data block. */ - uchar *R = &(D[4]); /* The right half of the ciphertext block. */ - uchar Rexp[6]; /* Expanded right half. */ - uchar Rn[4]; /* New value of R, as we manipulate it. */ - uchar SubK[6]; /* The 48-bit subkey. */ - - /* Generate the subkey for this round. - */ - KeyShift( K, KeyRotation[i] ); - Permute( SubK, K, KeyCompression, 6 ); - - /* Expand the right half (R) of the data block to 48 bytes, - * then XOR the result with the Subkey for this round. - */ - Permute( Rexp, R, DataExpansion, 6 ); - xor( Rexp, Rexp, SubK, 6 ); - - /* S-Box substitutions, P-Box permutation, and final XOR. - * The S-Box substitutions return a 32-bit value, which is then - * run through the 32-bit to 32-bit P-Box permutation. The P-Box - * result is then XOR'd with the left-hand half of the key. - * (Rexp is used as a temporary variable between the P-Box & XOR). - */ - sbox( Rn, Rexp ); - Permute( Rexp, Rn, PBox, 4 ); - xor( Rn, L, Rexp, 4 ); - - /* The previous R becomes the new L, - * and Rn is moved into R ready for the next round. - */ - for( j = 0; j < 4; j++ ) - { - L[j] = R[j]; - R[j] = Rn[j]; - } - } - - /* The encryption is complete. - * Now reverse-permute the ciphertext to produce the final result. - * We actually combine two steps here. The penultimate step is to - * swap the positions of L and R in the result of the 16 rounds, - * after which the reverse of the Initial Permutation is applied. - * To save a step, the FinalPermuteMap applies both the L/R swap - * and the inverse of the Initial Permutation. - */ - Permute( dst, D, FinalPermuteMap, 8 ); - return( dst ); - } /* auth_DEShash */ - -/* ========================================================================== */ diff --git a/source/smb/DES.h b/source/smb/DES.h deleted file mode 100644 index d1b7f2e..0000000 --- a/source/smb/DES.h +++ /dev/null @@ -1,179 +0,0 @@ -#ifndef AUTH_DES_H -#define AUTH_DES_H -/* ========================================================================== ** - * - * DES.h - * - * Copyright: - * Copyright (C) 2003, 2004 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * - * $Id: DES.h,v 0.5 2004/05/30 02:31:47 crh Exp $ - * - * -------------------------------------------------------------------------- ** - * - * Description: - * - * Implements DES encryption, but not decryption. - * DES is used to create LM password hashes and both LM and NTLM Responses. - * - * -------------------------------------------------------------------------- ** - * - * License: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * -------------------------------------------------------------------------- ** - * - * Notes: - * - * This implementation was created by studying many existing examples - * found in Open Source, in the public domain, and in various documentation. - * The SMB protocol makes minimal use of the DES function, so this is a - * minimal implementation. That which is not required has been removed. - * - * The SMB protocol uses the DES algorithm as a hash function, not an - * encryption function. The auth_DEShash() implemented here is a one-way - * function. The reverse is not implemented in this module. Also, there - * is no attempt at making this either fast or efficient. There is no - * need, as the auth)DEShash() function is used for generating the LM - * Response from a 7-byte key and an 8-byte challenge. It is not intended - * for use in encrypting large blocks of data or data streams. - * - * As stated above, this implementation is based on studying existing work - * in the public domain or under Open Source (specifically LGPL) license. - * The code, however, is written from scratch. Obviously, I make no claim - * with regard to those earlier works (except to claim that I am grateful - * to the previous implementors whose work I studied). See the list of - * references below for resources I used. - * - * References: - * I read through the libmcrypt code to see how they put the pieces - * together. See: http://mcrypt.hellug.gr/ - * Libmcrypt is available under the terms of the LGPL. - * - * The libmcrypt implementation includes the following credits: - * written 12 Dec 1986 by Phil Karn, KA9Q; large sections adapted - * from the 1977 public-domain program by Jim Gillogly - * Modified for additional speed - 6 December 1988 Phil Karn - * Modified for parameterized key schedules - Jan 1991 Phil Karn - * modified in order to use the libmcrypt API by Nikos Mavroyanopoulos - * All modifications are placed under the license of libmcrypt. - * - * See also Phil Karn's privacy and security page: - * http://www.ka9q.net/privacy.html - * - * I relied heavily upon: - * Applied Cryptography, Second Edition: - * Protocols, Algorithms, and Source Code in C - * by Bruce Schneier. ISBN 0-471-11709-9, John Wiley & Sons, Inc., 1996 - * Particularly Chapter 12. - * - * Here's one more DES resource, which I found quite helpful (aside from - * the Clinton jokes): - * http://www.aci.net/kalliste/des.htm - * - * Finally, the use of DES in SMB is covered in: - * Implementing CIFS - the Common Internet File System - * by your truly. ISBN 0-13-047116-X, Prentice Hall PTR., August 2003 - * Section 15.3, in particular. - * (Online at: http://ubiqx.org/cifs/SMB.html#SMB.8.3) - * - * ========================================================================== ** - */ - -//#include "auth_common.h" -#include -typedef unsigned char uchar; -typedef unsigned char uint8_t; - -/* -------------------------------------------------------------------------- ** - * Functions: - */ - -uchar *auth_DESkey8to7( uchar *dst, const uchar *key ); - /* ------------------------------------------------------------------------ ** - * Compress an 8-byte DES key to its 7-byte form. - * - * Input: dst - Pointer to a memory location (minimum 7 bytes) to accept - * the compressed key. - * key - Pointer to an 8-byte DES key. See the notes below. - * - * Output: A pointer to the compressed key (same as ) or NULL if - * either or were NULL. - * - * Notes: There are no checks done to ensure that and point - * to sufficient space. Please be carefull. - * - * The two pointers, and may point to the same - * memory location. Internally, a temporary buffer is used and - * the results are copied back to . - * - * The DES algorithm uses 8 byte keys by definition. The first - * step in the algorithm, however, involves removing every eigth - * bit to produce a 56-bit key (seven bytes). SMB authentication - * skips this step and uses 7-byte keys. The - * algorithm in this module expects 7-byte keys. This function - * is used to convert an 8-byte DES key into a 7-byte SMB DES key. - * - * ------------------------------------------------------------------------ ** - */ - - -uchar *auth_DEShash( uchar *dst, const uchar *key, const uchar *src ); - /* ------------------------------------------------------------------------ ** - * DES encryption of the input data using the input key. - * - * Input: dst - Destination buffer. It *must* be at least eight bytes - * in length, to receive the encrypted result. - * key - Encryption key. Exactly seven bytes will be used. - * If your key is shorter, ensure that you pad it to seven - * bytes. - * src - Source data to be encrypted. Exactly eight bytes will - * be used. If your source data is shorter, ensure that - * you pad it to eight bytes. - * - * Output: A pointer to the encrpyted data (same as ). - * - * Notes: In SMB, the DES function is used as a hashing function rather - * than an encryption/decryption tool. When used for generating - * the LM hash the input is the known value "KGS!@#$%" and - * the key is derived from the password entered by the user. - * When used to generate the LM or NTLM response, the is - * derived from the LM or NTLM hash, and the challenge is used - * as the input. - * See: http://ubiqx.org/cifs/SMB.html#SMB.8.3 - * - * - This function is called "DEShash" rather than just "DES" - * because it is only used for creating LM hashes and the - * LM/NTLM responses. For all practical purposes, however, it - * is a full DES encryption implementation. - * - * - This DES implementation does not need to be fast, nor is a - * DES decryption function needed. The goal is to keep the - * code small, simple, and well documented. - * - * - The input values are copied and refiddled within the module - * and the result is not written to until the very last - * step, so it's okay if points to the same memory as - * or . - * - * ------------------------------------------------------------------------ ** - */ - - -/* ========================================================================== */ -#endif /* AUTH_DES_H */ diff --git a/source/smb/LMhash.c b/source/smb/LMhash.c deleted file mode 100644 index 20cc6b6..0000000 --- a/source/smb/LMhash.c +++ /dev/null @@ -1,169 +0,0 @@ -/* ========================================================================== ** - * - * LMhash.c - * - * Copyright: - * Copyright (C) 2004 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * - * $Id: LMhash.c,v 0.1 2004/05/30 02:26:31 crh Exp $ - * - * -------------------------------------------------------------------------- ** - * - * Description: - * - * Implemention of the LAN Manager hash (LM hash) and LM response - * algorithms. - * - * -------------------------------------------------------------------------- ** - * - * License: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * -------------------------------------------------------------------------- ** - * - * Notes: - * - * This module implements the LM hash. The NT hash is simply the MD4() of - * the password, so we don't need a separate implementation of that. This - * module also implements the LM response, which can be combined with the - * NT hash to produce the NTLM response. - * - * This implementation was created based on the description in my own book. - * The book description was, in turn, written after studying many existing - * examples in various documentation. Jeremy Allison and Andrew Tridgell - * deserve lots of credit for having figured out the secrets of Lan Manager - * authentication many years ago. - * - * See: - * Implementing CIFS - the Common Internet File System - * by your truly. ISBN 0-13-047116-X, Prentice Hall PTR., August 2003 - * Section 15.3, in particular. - * (Online at: http://ubiqx.org/cifs/SMB.html#SMB.8.3) - * - * ========================================================================== ** - */ - -#include "DES.h" -#include "LMhash.h" - - -/* -------------------------------------------------------------------------- ** - * Static Constants: - * - * SMB_LMhash_Magic - This is the plaintext "magic string" that is used to - * generate the LM Hash from the user's password. This - * value was a Microsoft "secret" for many years. - */ - -static const uchar SMB_LMhash_Magic[8] = - { 'K', 'G', 'S', '!', '@', '#', '$', '%' }; - - -/* -------------------------------------------------------------------------- ** - * Functions: - */ - -uchar *auth_LMhash( uchar *dst, const uchar *pwd, const int pwdlen ) - /* ------------------------------------------------------------------------ ** - * Generate an LM Hash from the input password. - * - * Input: dst - Pointer to a location to which to write the LM Hash. - * Requires 16 bytes minimum. - * pwd - Source password. Should be in OEM charset (extended - * ASCII) format in all upper-case, but this - * implementation doesn't really care. See the notes - * below. - * pwdlen - Length, in bytes, of the password. Normally, this - * will be strlen( pwd ). - * - * Output: Pointer to the resulting LM hash (same as ). - * - * Notes: This function does not convert the input password to upper - * case. The upper-case conversion should be done before the - * password gets this far. DOS codepage handling and such - * should be taken into consideration. Rather than attempt to - * work out all those details here, the function assumes that - * the password is in the correct form before it reaches this - * point. - * - * ------------------------------------------------------------------------ ** - */ - { - int i, - max14; - uint8_t tmp_pwd[14] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; - - /* Copy at most 14 bytes of into . - * If the password is less than 14 bytes long - * the rest will be nul padded. - */ - max14 = pwdlen > 14 ? 14 : pwdlen; - for( i = 0; i < max14; i++ ) - tmp_pwd[i] = pwd[i]; - - /* The password is split into two 7-byte keys, each of which - * are used to DES-encrypt the magic string. The results are - * concatonated to produce the 16-byte LM Hash. - */ - (void)auth_DEShash( dst, tmp_pwd, SMB_LMhash_Magic ); - (void)auth_DEShash( &dst[8], &tmp_pwd[7], SMB_LMhash_Magic ); - - /* Return a pointer to the result. - */ - return( dst ); - } /* auth_LMhash */ - - -uchar *auth_LMresponse( uchar *dst, const uchar *hash, const uchar *challenge ) - /* ------------------------------------------------------------------------ ** - * Generate the LM (or NTLM) response from the password hash and challenge. - * - * Input: dst - Pointer to memory into which to write the response. - * Must have 24 bytes available. - * hash - Pointer to the 16-byte password hash. - * challenge - Pointer to the 8-byte challenge. - * - * Output: A pointer to the 24-byte response (same as ). - * - * Notes: The function does not check the lengths of the input or output - * parameters. The byte sizes given above must be respected by - * calling function. - * - * ------------------------------------------------------------------------ ** - */ - { - uchar tmp[7] = - { hash[14], hash[15], 0,0,0,0,0 }; /* 3rd key is nul-padded. */ - - /* It's painfully simple... - * The challenge is DES encrypted three times. - * The first time, the first 7 bytes of the hash are used. - * The second time, the second 7 bytes of the hash are used. - * The third time, the two remaining hash bytes plus five nuls are used. - * The three 8-byte results are concatonated to form the 24-byte response. - */ - (void)auth_DEShash( dst, hash, challenge ); - (void)auth_DEShash( &dst[8], &hash[7], challenge ); - (void)auth_DEShash( &dst[16], tmp, challenge ); - - /* Return the result. - */ - return( dst ); - } /* auth_LMresponse */ - -/* ========================================================================== */ diff --git a/source/smb/LMhash.h b/source/smb/LMhash.h deleted file mode 100644 index ad94f6a..0000000 --- a/source/smb/LMhash.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef AUTH_LMHASH_H -#define AUTH_LMHASH_H -/* ========================================================================== ** - * - * LMhash.h - * - * Copyright: - * Copyright (C) 2004 by Christopher R. Hertel - * - * Email: crh@ubiqx.mn.org - * - * $Id: LMhash.h,v 0.1 2004/05/30 02:26:31 crh Exp $ - * - * -------------------------------------------------------------------------- ** - * - * Description: - * - * Implemention of the LAN Manager hash (LM hash) and LM response - * algorithms. - * - * -------------------------------------------------------------------------- ** - * - * License: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * -------------------------------------------------------------------------- ** - * - * Notes: - * - * This module implements the LM hash. The NT hash is simply the MD4() of - * the password, so we don't need a separate implementation of that. This - * module also implements the LM response, which can be combined with the - * NT hash to produce the NTLM response. - * - * This implementation was created based on the description in my own book. - * The book description was, in turn, written after studying many existing - * examples in various documentation. Jeremy Allison and Andrew Tridgell - * deserve lots of credit for having figured out the secrets of Lan Manager - * authentication many years ago. - * - * See: - * Implementing CIFS - the Common Internet File System - * by your truly. ISBN 0-13-047116-X, Prentice Hall PTR., August 2003 - * Section 15.3, in particular. - * (Online at: http://ubiqx.org/cifs/SMB.html#SMB.8.3) - * - * ========================================================================== ** - */ - - -/* -------------------------------------------------------------------------- ** - * Functions: - */ - -uchar *auth_LMhash( uchar *dst, const uchar *pwd, const int pwdlen ); - /* ------------------------------------------------------------------------ ** - * Generate an LM Hash from the input password. - * - * Input: dst - Pointer to a location to which to write the LM Hash. - * Requires 16 bytes minimum. - * pwd - Source password. Should be in OEM charset (extended - * ASCII) format in all upper-case, but this - * implementation doesn't really care. See the notes - * below. - * pwdlen - Length, in bytes, of the password. Normally, this - * will be strlen( pwd ). - * - * Output: Pointer to the resulting LM hash (same as ). - * - * Notes: This function does not convert the input password to upper - * case. The upper-case conversion should be done before the - * password gets this far. DOS codepage handling and such - * should be taken into consideration. Rather than attempt to - * work out all those details here, the function assumes that - * the password is in the correct form before it reaches this - * point. - * - * ------------------------------------------------------------------------ ** - */ - - -uchar *auth_LMresponse( uchar *dst, const uchar *hash, const uchar *challenge ); - /* ------------------------------------------------------------------------ ** - * Generate the LM (or NTLM) response from the password hash and challenge. - * - * Input: dst - Pointer to memory into which to write the response. - * Must have 24 bytes available. - * hash - Pointer to the 16-byte password hash. - * challenge - Pointer to the 8-byte challenge. - * - * Output: A pointer to the 24-byte response (same as ). - * - * Notes: The function does not check the lengths of the input or output - * parameters. The byte sizes given above must be respected by - * calling function. - * - * ------------------------------------------------------------------------ ** - */ - - -/* ========================================================================== */ -#endif /* AUTH_LMHASH_H */ diff --git a/source/smb/readme1st.txt b/source/smb/readme1st.txt deleted file mode 100644 index 8e6e1bc..0000000 --- a/source/smb/readme1st.txt +++ /dev/null @@ -1,112 +0,0 @@ -TinySMB-GC 0.1 -May 2006 - -Developer Documentation - -What is TinySMB-GC? - -TinySMB-GC is a minimal implementation of the SMB protocol for the Nintendo Gamecube. - -What does it do? - -Essentially, TinySMB-GC enables network share support. This means that it will allow the -GameCube to connect to a shared folder on a Windows XP or linux samba box, and perform -basic file functions. - -Known Restrictions - -TinySMB-GC only supports the LM1.2X002 protocol. THIS IS NOT THE MOST SECURE! -However, it does NOT transmit your password over the wire, so it's reasonably safe. - -How do I use it? - -TinySMB-GC is developed with devkitPPC and libOGC, therefore you should be using this -development environment. Put simply, it won't work with anything else! - -TinySMB-GC uses the TCP-raw form of SMB on port 445. - -The Functions. - -int SMB_Init (char *user, /*** The logon user - MUST have share access rights ***/ - char *password, /*** PLEASE USE PASSWORD SECURITY! ***/ - char *client, /*** Machine ID, whatever you want to call the GC ***/ - char *server, /*** Machine ID of share server ***/ - char *share, /*** Share ID ***/ - char *IP); /*** IP of share server ***/ - -SMB_Init is used to establish the connection, authenticate and attach to the share. -Obviously, this must be called successfully before any other function. - -void SMB_Destroy (); - -SMB_Destroy takes care of releasing the internal socket of TinySMB-GC and should be -called when the SMB functions are no longer required. - -int SMB_FindFirst (char *filename, /*** The file mask to search for ***/ - unsigned short flags, /*** Search criteria flags ***/ - SMBDIRENTRY * sdir); /*** An SMBDIRENTRY to hold directory information ***/ - -Similar to MS-Windows, to search for a file or directory, use this function to determine if the -file already exists. The SMBDIRENTRY simply holds basic information on each entry retrieved. - -int SMB_FindNext (SMBDIRENTRY * sdir); - -Called to continue a search started with SMB_FindFirst. - -int SMB_FindClose (); - -When all searches have completed, call SMB_FindClose to dispense with the search handle. - -SMBFILE SMB_Open (char *filename, /*** The filename to open ***/ - unsigned short access, /*** Access method ***/ - unsigned short creation); /*** Creation flags ***/ - -This call will open a file on the share. Both reading and writing are supported. -Look at smb.h for information on the access and creation flags. - -void SMB_Close (SMBFILE sfid); - -Close a file previously opened with SMB_Open - -int SMB_Read (char *buffer, int size, int offset, SMBFILE sfile); - -Read from the file opened with SMB_Open. - -int SMB_Write (char *buffer, int size, int offset, SMBFILE sfile); - -Write to the file opened with SMB_Open. - -NOTE: The offset value provides the missing seek function. However, the onus -is on the developer to maintain the offset value when reading / writing -sequentially. - -You should also be aware that these functions should only be used to read/write -blocks up to 62Kbytes. Although it allows reading and writing of 4Gb files, it -does not support blocks larger then 16-bit - go figure! - -Credits - -TinySMB-GC Copyright softdev@tehskeen.com - Please respect this copyright! - NOTE WELL: This software is released under GPL 2.1 - YOU MAY NOT STEAL IT AND HIDE IT IN YOUR - CLOSED SOURCE PRODUCT. - -libOGC shagkur - -devkitPPC wntrmute - -CIFS Info Christopher R Hertel - http://www.ubiqx.com - Storage Networking Industry Association - http://www.snia.com - Ethereal - Packet Capture - http://www.ethereal.com - -Thanks - -Cedy_NL, for testing and helping get this off the ground. -brakken, web hosting and promotion. - -Everyone who has participated in the Genesis Plus Project - keep up the good work ! - \ No newline at end of file diff --git a/source/smb/smb.c b/source/smb/smb.c deleted file mode 100644 index 4d9a5b8..0000000 --- a/source/smb/smb.c +++ /dev/null @@ -1,932 +0,0 @@ -/**************************************************************************** - * TinySMB-GC - * - * Nintendo Gamecube SaMBa implementation. - * - * Copyright softdev@tehskeen.com - * - * Authentication modules, LMhash and DES are - * - * Copyright Christopher R Hertel. - * http://www.ubiqx.org - * - * You WILL find Ethereal, available from http://www.ethereal.com - * invaluable for debugging each new SAMBA implementation. - * - * Recommended Reading - * Implementing CIFS - Christopher R Hertel - * SNIA CIFS Documentation - http://www.snia.org - * - * License: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - ****************************************************************************/ - -#include -#include -#include "smb.h" -#include "DES.h" -#include "LMhash.h" -#include - -/** - * A few little bits for libOGC - */ -typedef int SOCKET; -#define recv net_recv -#define send net_send -#define closesocket net_close -#define connect net_connect -#define setsockopt net_setsockopt -#define socket net_socket - -/** - * Client and server SMB - */ -NBTSMB c; -NBTSMB s; -SMBSESSION session; -SOCKET smbsock; -static struct sockaddr_in smbs; -static int smbcheckbytes = 0; - -/** - * SMB Endian aware supporting functions - * - * SMB always uses Intel Little-Endian values, so htons etc are - * of little or no use :) ... Thanks M$ - */ -/*** get unsigned char ***/ -static unsigned char -getUChar (unsigned char *buffer, int offset) -{ - return buffer[offset]; -} - -/*** set unsigned char ***/ -static void -setUChar (unsigned char *buffer, int offset, unsigned char value) -{ - buffer[offset] = value; -} - -/*** get unsigned short ***/ -static unsigned short -getUShort (unsigned char *buffer, int offset) -{ - unsigned short t; - t = buffer[offset]; - t |= (buffer[offset + 1] << 8); - - return t; -} - -/*** set unsigned short ***/ -static void -setUShort (unsigned char *buffer, int offset, unsigned short value) -{ - buffer[offset] = value & 0xff; - buffer[offset + 1] = (value & 0xff00) >> 8; -} - -/*** get unsigned int ***/ -static unsigned int -getUInt (unsigned char *buffer, int offset) -{ - unsigned int t; - - t = buffer[offset]; - t |= (buffer[offset + 1] << 8); - t |= (buffer[offset + 2] << 16); - t |= (buffer[offset + 3] << 24); - - return t; -} - -/*** set unsigned int ***/ -static void -setUInt (unsigned char *buffer, int offset, int value) -{ - buffer[offset] = value & 0xff; - buffer[offset + 1] = (value & 0xff00) >> 8; - buffer[offset + 2] = (value & 0xff0000) >> 16; - buffer[offset + 3] = (value & 0xff000000) >> 24; -} - -/** - * MakeSMBHdr - * - * Generate the SMB header for each request. - * Uses 'c' NBTSMB - */ -static void -MakeSMBHdr (unsigned char command) -{ - int pos = 0; - - /*** Clear client packet ***/ - memset (&c, 0, sizeof (c)); - - /*** Add protocol SMB ***/ - setUInt (c.smb, pos, SMB_PROTO); - pos += 4; - setUChar (c.smb, pos, command); - pos++; - pos++; /*** Error class ***/ - pos++; /*** Reserved ***/ - pos += 2; /*** Error Code ***/ - setUChar (c.smb, pos, 0x8); - pos++; /*** Flags == 8 == Case Insensitive ***/ - setUShort (c.smb, pos, 0x1); - pos += 2; /*** Flags2 == 1 == LFN ***/ - pos += 2; /*** Process ID High ***/ - pos += 8; /*** Signature ***/ - pos += 2; /*** Reserved ***/ - setUShort (c.smb, pos, session.TID); - pos += 2; - setUShort (c.smb, pos, session.PID); - pos += 2; - setUShort (c.smb, pos, session.UID); - pos += 2; - setUShort (c.smb, pos, session.MID); -} - -/** - * MakeTRANS2Hdr - */ -static void -MakeTRANS2Hdr (unsigned char subcommand) -{ - setUChar (c.smb, T2_WORD_CNT, 15); - setUShort (c.smb, T2_MAXPRM_CNT, 10); - setUShort (c.smb, T2_MAXBUFFER, session.MaxBuffer); - setUChar (c.smb, T2_SSETUP_CNT, 1); - setUShort (c.smb, T2_SUB_CMD, subcommand); -} - -/** - * SMBCheck - * - * Do very basic checking on the return SMB - */ -static int -SMBCheck (unsigned char command, int readlen) -{ - int ret; - - memset (&s, 0, sizeof (s)); - - smbcheckbytes = ret = recv (smbsock, (char *) &s, readlen, 0); - - if (ret < 12) - return 0; - - /*** Do basic SMB Header checks ***/ - ret = getUInt (s.smb, 0); - if (ret != SMB_PROTO) - return BAD_PROTOCOL; - - if (getUChar (s.smb, 4) != command) - return SMB_BAD_COMMAND; - - ret = getUInt (s.smb, SMB_OFFSET_NTSTATUS); - - if (ret) - return SMB_ERROR; - - return SMB_SUCCESS; - -} - -/** - * SMB_NegotiateProtocol - * - * The only protocol we admit to is 'DOS LANMAN 2.1' - */ -static int -SMB_NegotiateProtocol () -{ - int pos; - int bcpos; - int ret; - char proto[] = "\2LM1.2X002"; /*** Seems to work with Samba and XP Home ***/ - unsigned short bytecount; - - /*** Clear session variables ***/ - memset (&session, 0, sizeof (session)); - session.PID = 0xdead; - session.MID = 1; - - MakeSMBHdr (SMB_NEG_PROTOCOL); - pos = SMB_HEADER; - - pos++; /*** Add word count ***/ - bcpos = pos; - pos += 2; /*** Byte count - when known ***/ - - strcpy (&c.smb[pos], proto); - - pos += strlen (proto) + 1; - - /*** Update byte count ***/ - setUShort (c.smb, bcpos, (pos - bcpos) - 2); - - /*** Set NBT information ***/ - c.msg = SESS_MSG; - c.length = htons (pos); - - pos += 4; - ret = send (smbsock, (char *) &c, pos, 0); - - /*** Check response ***/ - if (SMBCheck (SMB_NEG_PROTOCOL, sizeof (s)) == SMB_SUCCESS) - { - pos = SMB_HEADER; - /*** Collect information ***/ - if (getUChar (s.smb, pos) != 13) - return SMB_PROTO_FAIL; - - pos++; - if (getUShort (s.smb, pos)) - return SMB_PROTO_FAIL; - - pos += 2; - if (getUShort (s.smb, pos) != 3) - return SMB_NOT_USER; - - pos += 2; - session.MaxBuffer = getUShort (s.smb, pos); - pos += 2; - if (session.MaxBuffer > 2916) - session.MaxBuffer = 2916; - session.MaxMpx = getUShort (s.smb, pos); - pos += 2; - session.MaxVCS = getUShort (s.smb, pos); - pos += 2; - pos += 2; /*** Raw Mode ***/ - pos += 4; /*** Session Key ***/ - pos += 6; /*** Time information ***/ - if (getUShort (s.smb, pos) != 8) - return SMB_BAD_KEYLEN; - - pos += 2; - pos += 2; /*** Reserved ***/ - - bytecount = getUShort (s.smb, pos); - pos += 2; - - /*** Copy challenge key ***/ - memcpy (&session.challenge, &s.smb[pos], 8); - pos += 8; - /*** Primary domain ***/ - strcpy (session.p_domain, &s.smb[pos]); - - return SMB_SUCCESS; - } - - return 0; - -} - -/** - * SMB_SetupAndX - * - * Setup the SMB session, including authentication with the - * magic 'LM Response' - */ -static int -SMB_SetupAndX (char *user, char *password) -{ - int pos; - int bcpos; - char pwd[24], LMh[24], LMr[24]; - int i, ret; - - MakeSMBHdr (SMB_SETUP_ANDX); - pos = SMB_HEADER; - - setUChar (c.smb, pos, 10); - pos++; /*** Word Count ***/ - setUChar (c.smb, pos, 0xff); - pos++; /*** Next AndX ***/ - pos++; /*** Reserved ***/ - pos += 2; /*** Next AndX Offset ***/ - setUShort (c.smb, pos, session.MaxBuffer); - pos += 2; - setUShort (c.smb, pos, session.MaxMpx); - pos += 2; - setUShort (c.smb, pos, session.MaxVCS); - pos += 2; - pos += 4; /*** Session key, unknown at this point ***/ - setUShort (c.smb, pos, 24); - pos += 2; /*** Password length ***/ - pos += 4; /*** Reserved ***/ - bcpos = pos; - pos += 2; /*** Byte count ***/ - - /*** The magic 'LM Response' ***/ - strcpy (pwd, password); - for (i = 0; i < strlen (pwd); i++) - pwd[i] = toupper (pwd[i]); - - auth_LMhash (LMh, pwd, strlen (pwd)); - auth_LMresponse (LMr, LMh, session.challenge); - - /*** Build information ***/ - memcpy (&c.smb[pos], LMr, 24); - pos += 24; - - /*** Account ***/ - strcpy (pwd, user); - for (i = 0; i < strlen (user); i++) - pwd[i] = toupper (pwd[i]); - memcpy (&c.smb[pos], pwd, strlen (pwd)); - pos += strlen (pwd) + 1; - - /*** Primary Domain ***/ - memcpy (&c.smb[pos], &session.p_domain, strlen (session.p_domain)); - pos += strlen (session.p_domain) + 1; - - /*** Native OS ***/ - strcpy (pwd, "Unix (libOGC)"); - memcpy (&c.smb[pos], pwd, strlen (pwd)); - pos += strlen (pwd) + 1; - - /*** Native LAN Manager ***/ - strcpy (pwd, "Nintendo GameCube 0.1"); - memcpy (&c.smb[pos], pwd, strlen (pwd)); - pos += strlen (pwd) + 1; - - /*** Update byte count ***/ - setUShort (c.smb, bcpos, (pos - bcpos) - 2); - - c.msg = SESS_MSG; - c.length = htons (pos); - pos += 4; - - ret = send (smbsock, (char *) &c, pos, 0); - - if (SMBCheck (SMB_SETUP_ANDX, sizeof (s)) == SMB_SUCCESS) - { - /*** Collect UID ***/ - session.UID = getUShort (s.smb, SMB_OFFSET_UID); - - return SMB_SUCCESS; - } - - return 0; -} - -/** - * SMB_TreeAndX - * - * Finally, connect to the remote share - */ -static int -SMB_TreeAndX (char *server, char *share) -{ - int pos, bcpos, ret; - char path[256]; - - MakeSMBHdr (SMB_TREEC_ANDX); - pos = SMB_HEADER; - - setUChar (c.smb, pos, 4); - pos++; /*** Word Count ***/ - setUChar (c.smb, pos, 0xff); - pos++; /*** Next AndX ***/ - pos++; /*** Reserved ***/ - pos += 2; /*** Next AndX Offset ***/ - pos += 2; /*** Flags ***/ - setUShort (c.smb, pos, 1); - pos += 2; /*** Password Length ***/ - bcpos = pos; - pos += 2; - pos++; /*** NULL Password ***/ - - /*** Build server share path ***/ - strcpy (path, "\\\\"); - strcat (path, server); - strcat (path, "\\"); - strcat (path, share); - for (ret = 0; ret < strlen (path); ret++) - path[ret] = toupper (path[ret]); - - memcpy (&c.smb[pos], path, strlen (path)); - pos += strlen (path) + 1; - - /*** Service ***/ - strcpy (path, "?????"); - memcpy (&c.smb[pos], path, strlen (path)); - pos += strlen (path) + 1; - - /*** Update byte count ***/ - setUShort (c.smb, bcpos, (pos - bcpos) - 2); - - c.msg = SESS_MSG; - c.length = htons (pos); - pos += 4; - - ret = send (smbsock, (char *) &c, pos, 0); - - if (SMBCheck (SMB_TREEC_ANDX, sizeof (s)) == SMB_SUCCESS) - { - /*** Collect Tree ID ***/ - session.TID = getUShort (s.smb, SMB_OFFSET_TID); - return SMB_SUCCESS; - } - - return 0; -} - -/** - * SMB_FindFirst - * - * Uses TRANS2 to support long filenames - */ -int -SMB_FindFirst (char *filename, unsigned short flags, SMBDIRENTRY * sdir) -{ - int pos; - int ret; - int bpos; - - MakeSMBHdr (SMB_TRANS2); - MakeTRANS2Hdr (SMB_FIND_FIRST2); - pos = T2_BYTE_CNT + 2; - bpos = pos; - pos += 3; /*** Padding ***/ - - setUShort (c.smb, pos, flags); - pos += 2; /*** Flags ***/ - setUShort (c.smb, pos, 1); - pos += 2; /*** Count ***/ - setUShort (c.smb, pos, 6); - pos += 2; /*** Internal Flags ***/ - setUShort (c.smb, pos, 260); - pos += 2; /*** Level of Interest ***/ - pos += 4; /*** Storage Type == 0 ***/ - memcpy (&c.smb[pos], filename, strlen (filename)); - pos += strlen (filename) + 1; /*** Include padding ***/ - - /*** Update counts ***/ - setUShort (c.smb, T2_PRM_CNT, 13 + strlen (filename)); - setUShort (c.smb, T2_SPRM_CNT, 13 + strlen (filename)); - setUShort (c.smb, T2_SPRM_OFS, 68); - setUShort (c.smb, T2_SDATA_OFS, 81 + strlen (filename)); - setUShort (c.smb, T2_BYTE_CNT, pos - bpos); - - c.msg = SESS_MSG; - c.length = htons (pos); - - pos += 4; - - ret = send (smbsock, (char *) &c, pos, 0); - session.sid = 0; - session.count = 0; - session.eos = 1; - - if (SMBCheck (SMB_TRANS2, sizeof (s)) == SMB_SUCCESS) - { - /*** Get parameter offset ***/ - pos = getUShort (s.smb, SMB_HEADER + 9); - session.sid = getUShort (s.smb, pos); - pos += 2; - session.count = getUShort (s.smb, pos); - pos += 2; - session.eos = getUShort (s.smb, pos); - pos += 2; - pos += 46; - - if (session.count) - { - sdir->size_low = getUInt (s.smb, pos); - pos += 4; - sdir->size_high = getUInt (s.smb, pos); - pos += 4; - pos += 8; - sdir->attributes = getUInt (s.smb, pos); - pos += 38; - strcpy (sdir->name, &s.smb[pos]); - - return SMB_SUCCESS; - } - } - - return 0; - -} - -/** - * SMB_FindNext - */ -int -SMB_FindNext (SMBDIRENTRY * sdir) -{ - int pos; - int ret; - int bpos; - - if (session.eos) - return 0; - - if (session.sid == 0) - return 0; - - MakeSMBHdr (SMB_TRANS2); - MakeTRANS2Hdr (SMB_FIND_NEXT2); - pos = T2_BYTE_CNT + 2; - bpos = pos; - pos += 3; /*** Padding ***/ - - setUShort (c.smb, pos, session.sid); - pos += 2; /*** Search ID ***/ - setUShort (c.smb, pos, 1); - pos += 2; /*** Count ***/ - setUShort (c.smb, pos, 260); - pos += 2; /*** Level of Interest ***/ - pos += 4; /*** Storage Type == 0 ***/ - setUShort (c.smb, pos, 12); - pos += 2; /*** Search flags ***/ - pos++; - - /*** Update counts ***/ - setUShort (c.smb, T2_PRM_CNT, 13); - setUShort (c.smb, T2_SPRM_CNT, 13); - setUShort (c.smb, T2_SPRM_OFS, 68); - setUShort (c.smb, T2_SDATA_OFS, 81); - setUShort (c.smb, T2_BYTE_CNT, pos - bpos); - - c.msg = SESS_MSG; - c.length = htons (pos); - - pos += 4; - - ret = send (smbsock, (char *) &c, pos, 0); - - if (SMBCheck (SMB_TRANS2, sizeof (s)) == SMB_SUCCESS) - { - /*** Get parameter offset ***/ - pos = getUShort (s.smb, SMB_HEADER + 9); - session.count = getUShort (s.smb, pos); - pos += 2; - session.eos = getUShort (s.smb, pos); - pos += 2; - pos += 44; - - if (session.count) - { - sdir->size_low = getUInt (s.smb, pos); - pos += 4; - sdir->size_high = getUInt (s.smb, pos); - pos += 4; - pos += 8; - sdir->attributes = getUInt (s.smb, pos); - pos += 38; - strcpy (sdir->name, &s.smb[pos]); - - return SMB_SUCCESS; - } - } - - return 0; - -} - -/** - * SMB_FindClose - */ -int -SMB_FindClose () -{ - int pos = SMB_HEADER; - int ret; - - if (session.sid == 0) - return 0; - - MakeSMBHdr (SMB_FIND_CLOSE2); - - setUChar (c.smb, pos, 1); - pos++; /*** Word Count ***/ - setUShort (c.smb, pos, session.sid); - pos += 2; - pos += 2; /*** Byte Count ***/ - - c.msg = SESS_MSG; - c.length = htons (pos); - pos += 4; - ret = send (smbsock, (char *) &c, pos, 0); - - return SMBCheck (SMB_FIND_CLOSE2, sizeof (s)); - -} - -/** - * SMB_Open - */ -SMBFILE -SMB_Open (char *filename, unsigned short access, unsigned short creation) -{ - int pos = SMB_HEADER; - int bpos, ret; - char realfile[256]; - unsigned short fid; - - MakeSMBHdr (SMB_OPEN_ANDX); - - setUChar (c.smb, pos, 15); - pos++; /*** Word Count ***/ - setUChar (c.smb, pos, 0xff); - pos++; /*** Next AndX ***/ - pos += 3; /*** Next AndX Offset ***/ - - pos += 2; /*** Flags ***/ - setUShort (c.smb, pos, access); - pos += 2; /*** Access mode ***/ - setUShort (c.smb, pos, 0x6); - pos += 2; /*** Type of file ***/ - pos += 2; /*** Attributes ***/ - pos += 4; /*** File time - don't care - let server decide ***/ - setUShort (c.smb, pos, creation); - pos += 2; /*** Creation flags ***/ - pos += 4; /*** Allocation size ***/ - pos += 8; /*** Reserved ***/ - pos += 2; /*** Byte Count ***/ - bpos = pos; - - if (filename[0] != '\\') - { - strcpy (realfile, "\\"); - strcat (realfile, filename); - } - else - strcpy (realfile, filename); - - memcpy (&c.smb[pos], realfile, strlen (realfile)); - pos += strlen (realfile) + 1; - - setUShort (c.smb, bpos - 2, (pos - bpos)); - - c.msg = SESS_MSG; - c.length = htons (pos); - - pos += 4; - ret = send (smbsock, (char *) &c, pos, 0); - - if (SMBCheck (SMB_OPEN_ANDX, sizeof (s)) == SMB_SUCCESS) - { - /*** Check file handle ***/ - fid = getUShort (s.smb, SMB_HEADER + 5); - - if (fid) - return fid; - } - - return 0; -} - -/** - * SMB_Close - */ -void -SMB_Close (SMBFILE sfid) -{ - int pos, ret; - - MakeSMBHdr (SMB_CLOSE); - pos = SMB_HEADER; - - setUChar (c.smb, pos, 3); - pos++; /** Word Count **/ - setUShort (c.smb, pos, sfid); - pos += 2; - setUInt (c.smb, pos, 0xffffffff); - pos += 4; /*** Last Write ***/ - pos += 2; /*** Byte Count ***/ - - c.msg = SESS_MSG; - c.length = htons (pos); - pos += 4; - ret = send (smbsock, (char *) &c, pos, 0); - - SMBCheck (SMB_CLOSE, sizeof (s)); -} - -/** - * SMB_Read - */ -int -SMB_Read (char *buffer, int size, int offset, SMBFILE sfile) -{ - int pos, ret, ofs; - unsigned short length = 0; - - MakeSMBHdr (SMB_READ_ANDX); - pos = SMB_HEADER; - - /*** Don't let the size exceed! ***/ - if (size > 62 * 1024) - return 0; - - setUChar (c.smb, pos, 10); - pos++; /*** Word count ***/ - setUChar (c.smb, pos, 0xff); - pos++; - pos += 3; /*** Reserved, Next AndX Offset ***/ - setUShort (c.smb, pos, sfile); - pos += 2; /*** FID ***/ - setUInt (c.smb, pos, offset); - pos += 4; /*** Offset ***/ - - setUShort (c.smb, pos, size & 0xffff); - pos += 2; - setUShort (c.smb, pos, size & 0xffff); - pos += 2; - setUInt (c.smb, pos, 0); - pos += 4; - pos += 2; /*** Remaining ***/ - pos += 2; /*** Byte count ***/ - - c.msg = SESS_MSG; - c.length = htons (pos); - - pos += 4; - ret = send (smbsock, (char *) &c, pos, 0); - - /*** SMBCheck should now only read up to the end of a standard header ***/ - if (SMBCheck (SMB_READ_ANDX, SMB_HEADER + 27 + 4) == SMB_SUCCESS) - { - /*** Retrieve data length for this packet ***/ - length = getUShort (s.smb, SMB_HEADER + 11); - /*** Retrieve offset to data ***/ - ofs = getUShort (s.smb, SMB_HEADER + 13); - - /*** Default offset, with no padding is 59, so grab any outstanding padding ***/ - if (ofs > 59) - { - char pad[1024]; - ret = recv (smbsock, pad, ofs - 59, 0); - } - - /*** Finally, go grab the data ***/ - ofs = 0; - - if (length) - { - while (((ret = recv (smbsock, buffer + ofs, length, 0)) > 0)) - { - ofs += ret; - if (ofs == length) - break; - } - } - - return ofs; - - } - - return 0; - -} - -/** - * SMB_Write - */ -int -SMB_Write (char *buffer, int size, int offset, SMBFILE sfile) -{ - int pos, ret; - int blocks64; - - MakeSMBHdr (SMB_WRITE_ANDX); - pos = SMB_HEADER; - - setUChar (c.smb, pos, 12); - pos++; /*** Word Count ***/ - setUChar (c.smb, pos, 0xff); - pos += 2; /*** Next AndX ***/ - pos += 2; /*** Next AndX Offset ***/ - - setUShort (c.smb, pos, sfile); - pos += 2; - setUInt (c.smb, pos, offset); - pos += 4; - pos += 4; /*** Reserved ***/ - pos += 2; /*** Write Mode ***/ - pos += 2; /*** Remaining ***/ - - blocks64 = size >> 16; - - setUShort (c.smb, pos, blocks64); - pos += 2; /*** Length High ***/ - setUShort (c.smb, pos, size & 0xffff); - pos += 2; /*** Length Low ***/ - setUShort (c.smb, pos, 59); - pos += 2; /*** Data Offset ***/ - setUShort (c.smb, pos, size & 0xffff); - pos += 2; /*** Data Byte Count ***/ - - c.msg = SESS_MSG; - c.length = htons (pos + size); - - /*** Will this fit in a single send? ***/ - if (size <= 2916) - { - memcpy (&c.smb[pos], buffer, size); - pos += size; - } - else - { - memcpy (&c.smb[pos], buffer, 2916); - pos += 2916; - } - - pos += 4; - - /*** Send Header Information ***/ - ret = send (smbsock, (char *) &c, pos, 0); - - if (size > 2916) - { - /*** Send the data ***/ - ret = send (smbsock, buffer + 2916, size - 2916, 0); - } - - if (SMBCheck (SMB_WRITE_ANDX, sizeof (s)) == SMB_SUCCESS) - { - return (int) getUShort (s.smb, SMB_HEADER + 5); - } - - return 0; - -} - -/**************************************************************************** - * Primary setup, logon and connection all in one :) - ****************************************************************************/ -int -SMB_Init (char *user, char *password, char *client, - char *server, char *share, char *IP) -{ - int ret; - int nodelay; - - /*** Create the global socket ***/ - smbsock = socket (AF_INET, SOCK_STREAM, IPPROTO_IP); - - /*** Switch off Nagle, ON TCP_NODELAY ***/ - nodelay = 1; - ret = setsockopt (smbsock, IPPROTO_TCP, TCP_NODELAY, - (char *) &nodelay, sizeof (char)); - - /*** Attempt to connect to the server IP ***/ - memset (&smbs, 0, sizeof (client)); - smbs.sin_family = AF_INET; - smbs.sin_port = htons (445); - smbs.sin_addr.s_addr = inet_addr (IP); - - ret = connect (smbsock, (struct sockaddr *) &smbs, sizeof (smbs)); - - if (ret) - { - closesocket (smbsock); - return 0; - } - - if (SMB_NegotiateProtocol () == SMB_SUCCESS) - { - if (SMB_SetupAndX (user, password) == SMB_SUCCESS) - { - if (SMB_TreeAndX (server, share) == SMB_SUCCESS) - return SMB_SUCCESS; - } - } - - return 0; - -} - -/**************************************************************************** - * SMB_Destroy - * - * Probably NEVER called on GameCube, but here for completeness - ****************************************************************************/ -void -SMB_Destroy () -{ - if (smbsock) - closesocket (smbsock); -} diff --git a/source/smb/smb.h b/source/smb/smb.h deleted file mode 100644 index a755cd9..0000000 --- a/source/smb/smb.h +++ /dev/null @@ -1,219 +0,0 @@ -/**************************************************************************** - * TinySMB-GC - * - * Nintendo Gamecube SaMBa implementation. - * - * Copyright softdev@tehskeen.com - * - * Authentication modules, LMhash and DES are - * - * Copyright Christopher R Hertel. - * http://www.ubiqx.org - * - * You WILL find Ethereal, available from http://www.ethereal.com - * invaluable for debugging each new SAMBA implementation. - * - * Recommended Reading - * Implementing CIFS - Christopher R Hertel - * SNIA CIFS Documentation - http://www.snia.org - * - * License: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - ****************************************************************************/ -#ifndef NBTSMB_INC -#define NBTSMB_INC -#include -#include -#include - -/** - * NBT/SMB Wrapper - */ -typedef struct -{ - unsigned char msg; /*** NBT Message ***/ - unsigned char flags; /*** Not much here really ***/ - unsigned short length; /*** Length, excluding NBT ***/ - char smb[2916]; /*** GC Actual is 2920 bytes ***/ -} -NBTSMB; - -/** - * Session Information - */ -typedef struct -{ - unsigned short TID; - unsigned short PID; - unsigned short UID; - unsigned short MID; - unsigned short sKey; - unsigned short MaxBuffer; - unsigned short MaxMpx; - unsigned short MaxVCS; - unsigned char challenge[10]; - char p_domain[64]; - unsigned short sid; - unsigned short count; - unsigned short eos; -} -SMBSESSION; - -/*** SMB_FILEENTRY - SMB Long Filename Directory Entry - ***/ -typedef struct -{ - unsigned int size_low; - unsigned int size_high; - unsigned int attributes; - char name[256]; -} -SMBDIRENTRY; - -/*** - * SMB File Handle - */ -typedef unsigned short SMBFILE; - -#define SMB_HEADER 32 /*** SMB Headers are always 32 bytes long ***/ -#define SMB_PROTO 0x424d53ff - -/** - * Field offsets. - */ -#define SMB_OFFSET_CMD 4 -#define SMB_OFFSET_NTSTATUS 5 -#define SMB_OFFSET_ECLASS 5 -#define SMB_OFFSET_ECODE 7 -#define SMB_OFFSET_FLAGS 9 -#define SMB_OFFSET_FLAGS2 10 -#define SMB_OFFSET_EXTRA 12 -#define SMB_OFFSET_TID 24 -#define SMB_OFFSET_PID 26 -#define SMB_OFFSET_UID 28 -#define SMB_OFFSET_MID 30 - -/** - * Message / Commands - */ -#define SESS_MSG 0x00 -#define SMB_NEG_PROTOCOL 0x72 -#define SMB_SETUP_ANDX 0x73 -#define SMB_TREEC_ANDX 0x75 - -/** - * SMBTrans2 - */ -#define SMB_TRANS2 0x32 - -#define SMB_OPEN2 0 -#define SMB_FIND_FIRST2 1 -#define SMB_FIND_NEXT2 2 -#define SMB_QUERY_FS_INFO 3 -#define SMB_QUERY_PATH_INFO 5 -#define SMB_SET_PATH_INFO 6 -#define SMB_QUERY_FILE_INFO 7 -#define SMB_SET_FILE_INFO 8 -#define SMB_CREATE_DIR 13 -#define SMB_FIND_CLOSE2 0x34 - -/** - * File I/O - */ -#define SMB_OPEN_ANDX 0x2d -#define SMB_WRITE_ANDX 0x2f -#define SMB_READ_ANDX 0x2e -#define SMB_CLOSE 4 - -/** - * SMB File Access Modes - */ -#define SMB_OPEN_READING 0 -#define SMB_OPEN_WRITING 1 -#define SMB_OPEN_READWRITE 2 -#define SMB_OPEN_COMPATIBLE 0 -#define SMB_DENY_READWRITE 0x10 -#define SMB_DENY_WRITE 0x20 -#define SMB_DENY_READ 0x30 -#define SMB_DENY_NONE 0x40 - -/** - * SMB File Open Function - */ -#define SMB_OF_OPEN 1 -#define SMB_OF_TRUNCATE 2 -#define SMB_OF_CREATE 16 - -/** - * FileSearch - */ -#define SMB_SRCH_DIRECTORY 16 -#define SMB_SRCH_READONLY 1 -#define SMB_SRCH_HIDDEN 2 -#define SMB_SRCH_SYSTEM 4 -#define SMB_SRCH_VOLUME 8 - -/** - * SMB Error codes - */ -#define SMB_SUCCESS 1 -#define BAD_PROTOCOL -1 -#define SMB_ERROR -2 -#define SMB_BAD_COMMAND -3 -#define SMB_PROTO_FAIL -4 -#define SMB_NOT_USER -5 -#define SMB_BAD_KEYLEN -6 - -/** - * TRANS2 Offsets - */ -#define T2_WORD_CNT SMB_HEADER -#define T2_PRM_CNT T2_WORD_CNT + 1 -#define T2_DATA_CNT T2_PRM_CNT + 2 -#define T2_MAXPRM_CNT T2_DATA_CNT + 2 -#define T2_MAXBUFFER T2_MAXPRM_CNT + 2 -#define T2_SETUP_CNT T2_MAXBUFFER + 2 -#define T2_SPRM_CNT T2_SETUP_CNT + 10 -#define T2_SPRM_OFS T2_SPRM_CNT + 2 -#define T2_SDATA_CNT T2_SPRM_OFS + 2 -#define T2_SDATA_OFS T2_SDATA_CNT + 2 -#define T2_SSETUP_CNT T2_SDATA_OFS + 2 -#define T2_SUB_CMD T2_SSETUP_CNT + 2 -#define T2_BYTE_CNT T2_SUB_CMD + 2 - -/** - * Prototypes - */ - -/*** Session ***/ -int SMB_Init (char *user, char *password, char *client, - char *server, char *share, char *IP); -void SMB_Destroy (); - -/*** File Find ***/ -int SMB_FindFirst (char *filename, unsigned short flags, SMBDIRENTRY * sdir); -int SMB_FindNext (SMBDIRENTRY * sdir); -int SMB_FindClose (); - -/*** File I/O ***/ -SMBFILE SMB_Open (char *filename, unsigned short access, - unsigned short creation); -void SMB_Close (SMBFILE sfid); -int SMB_Read (char *buffer, int size, int offset, SMBFILE sfile); -int SMB_Write (char *buffer, int size, int offset, SMBFILE sfile); - -#endif