mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-12-25 18:51:50 +01:00
tinysmb now used from libogc
This commit is contained in:
parent
6ff361a2cd
commit
e6f129332f
726
source/smb/DES.c
726
source/smb/DES.c
@ -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 */
|
||||
|
||||
/* ========================================================================== */
|
179
source/smb/DES.h
179
source/smb/DES.h
@ -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 */
|
@ -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 */
|
||||
|
||||
/* ========================================================================== */
|
@ -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 */
|
@ -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 !
|
||||
|
932
source/smb/smb.c
932
source/smb/smb.c
@ -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);
|
||||
}
|
219
source/smb/smb.h
219
source/smb/smb.h
@ -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
|
Loading…
Reference in New Issue
Block a user