tinysmb now used from libogc

This commit is contained in:
dborth 2008-08-10 03:15:16 +00:00
parent 6ff361a2cd
commit e6f129332f
7 changed files with 0 additions and 2452 deletions

View File

@ -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 <map>. This also
* represents the number of bytes to be copied to <dst>.
*
* Output: none.
*
* Notes: <src> and <dst> must not point to the same location.
*
* - No checks are done to ensure that there is enough room
* in <dst>, or that the bit numbers in <map> do not exceed
* the bits available in <src>. A good reason to make this
* function static (private).
*
* - The <mapsize> 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 <numbits> 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 <numbits> 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 <keep>.
* If it's set, copy it to bit 27.
*/
if( keep & 0x80 )
SETBIT( key, 27 );
/* Rotate the <keep> byte too, in case <numbits> 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 <i>.
*/
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.
*
* - <dst> may safely point to the same location as <a> or <b>.
*
* ------------------------------------------------------------------------ **
*/
{
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 <dst>) or NULL if
* either <src> or <dst> were NULL.
*
* Notes: There are no checks done to ensure that <dst> and <key> point
* to sufficient space. Please be carefull.
*
* The two pointers, <dst> and <key> may point to the same
* memory location. Internally, a temporary buffer is used and
* the results are copied back to <dst>.
*
* 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 <auth_DEShash()>
* 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 <dst>).
*
* 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 <src> 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 <key> is
* derived from the LM or NTLM hash, and the challenge is used
* as the <src> 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 <dst> until the very last
* step, so it's okay if <dst> points to the same memory as
* <key> or <src>.
*
* ------------------------------------------------------------------------ **
*/
{
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 */
/* ========================================================================== */

View File

@ -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 <stdio.h>
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 <dst>) or NULL if
* either <src> or <dst> were NULL.
*
* Notes: There are no checks done to ensure that <dst> and <key> point
* to sufficient space. Please be carefull.
*
* The two pointers, <dst> and <key> may point to the same
* memory location. Internally, a temporary buffer is used and
* the results are copied back to <dst>.
*
* 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 <auth_DEShash()>
* 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 <dst>).
*
* 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 <src> 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 <key> is
* derived from the LM or NTLM hash, and the challenge is used
* as the <src> 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 <dst> until the very last
* step, so it's okay if <dst> points to the same memory as
* <key> or <src>.
*
* ------------------------------------------------------------------------ **
*/
/* ========================================================================== */
#endif /* AUTH_DES_H */

View File

@ -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 <dst>).
*
* 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 <pwd> into <tmp_pwd>.
* 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 <dst>).
*
* 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 */
/* ========================================================================== */

View File

@ -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 <dst>).
*
* 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 <dst>).
*
* 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 */

View File

@ -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 !

View File

@ -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 <gccore.h>
#include <network.h>
#include "smb.h"
#include "DES.h"
#include "LMhash.h"
#include <ctype.h>
/**
* 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);
}

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* 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