mirror of
https://github.com/samba-team/samba.git
synced 2025-08-03 04:22:09 +03:00
initial kerberos/ADS/SPNEGO support in libsmb and smbclient. To
activate you need to:
- install krb5 libraries
- run configure
- build smbclient
- run kinit to get a TGT
- run smbclient with the -k option to choose kerberos auth
(This used to be commit d330575856
)
This commit is contained in:
@ -124,7 +124,7 @@ UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
|
||||
|
||||
PARAM_OBJ = param/loadparm.o param/params.o
|
||||
|
||||
LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
|
||||
LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o libsmb/clikrb5.o libsmb/asn1.o \
|
||||
libsmb/clirap.o libsmb/clierror.o libsmb/climessage.o \
|
||||
libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \
|
||||
libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \
|
||||
|
@ -180,3 +180,4 @@
|
||||
#undef HAVE_STPCPY
|
||||
#undef I18N_SWAT
|
||||
#undef I18N_DEFAULT_PREF_LANG
|
||||
#undef HAVE_KRB5
|
||||
|
@ -42,6 +42,7 @@ static pstring workgroup;
|
||||
static char *cmdstr;
|
||||
static BOOL got_pass;
|
||||
static int io_bufsize = 64512;
|
||||
static BOOL use_kerberos;
|
||||
extern struct in_addr ipzero;
|
||||
|
||||
static int name_type = 0x20;
|
||||
@ -946,6 +947,22 @@ static BOOL do_mkdir(char *name)
|
||||
return(True);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
show 8.3 name of a file
|
||||
****************************************************************************/
|
||||
static BOOL do_altname(char *name)
|
||||
{
|
||||
fstring altname;
|
||||
if (!NT_STATUS_IS_OK(cli_qpathinfo_alt_name(cli, name, altname))) {
|
||||
d_printf("%s getting alt name for %s\n",
|
||||
cli_errstr(cli),name);
|
||||
return(False);
|
||||
}
|
||||
d_printf("%s\n", altname);
|
||||
|
||||
return(True);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Exit client.
|
||||
@ -999,6 +1016,27 @@ static int cmd_mkdir(void)
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
show alt name
|
||||
****************************************************************************/
|
||||
static void cmd_altname(void)
|
||||
{
|
||||
pstring name;
|
||||
fstring buf;
|
||||
char *p=buf;
|
||||
|
||||
pstrcpy(name,cur_dir);
|
||||
|
||||
if (!next_token_nr(NULL,p,NULL,sizeof(buf))) {
|
||||
d_printf("altname <file>\n");
|
||||
return;
|
||||
}
|
||||
pstrcat(name,p);
|
||||
|
||||
do_altname(name);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
put a single file
|
||||
****************************************************************************/
|
||||
@ -1816,6 +1854,7 @@ struct
|
||||
{"tar",cmd_tar,"tar <c|x>[IXFqbgNan] current directory to/from <file name>",{COMPL_NONE,COMPL_NONE}},
|
||||
{"tarmode",cmd_tarmode,"<full|inc|reset|noreset> tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}},
|
||||
{"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}},
|
||||
{"altname",cmd_altname,"<file> show alt name",{COMPL_NONE,COMPL_NONE}},
|
||||
{"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}},
|
||||
{"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}},
|
||||
{"",NULL,NULL,{COMPL_NONE,COMPL_NONE}}
|
||||
@ -2075,6 +2114,10 @@ struct cli_state *do_connect(const char *server, const char *share)
|
||||
|
||||
c->protocol = max_protocol;
|
||||
|
||||
if (use_kerberos) {
|
||||
c->use_spnego = True;
|
||||
}
|
||||
|
||||
if (!cli_session_request(c, &calling, &called)) {
|
||||
char *p;
|
||||
d_printf("session request to %s failed (%s)\n",
|
||||
@ -2198,6 +2241,7 @@ static void usage(char *pname)
|
||||
d_printf("\t-h Print this help message.\n");
|
||||
d_printf("\t-I dest IP use this IP to connect to\n");
|
||||
d_printf("\t-E write messages to stderr instead of stdout\n");
|
||||
d_printf("\t-k use kerberos (active directory) authentication\n");
|
||||
d_printf("\t-U username set the network username\n");
|
||||
d_printf("\t-L host get a list of shares available on a host\n");
|
||||
d_printf("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n");
|
||||
@ -2488,7 +2532,7 @@ static int do_message_op(void)
|
||||
}
|
||||
|
||||
while ((opt =
|
||||
getopt(argc, argv,"s:O:R:M:i:Nn:d:Pp:l:hI:EU:L:t:m:W:T:D:c:b:A:")) != EOF) {
|
||||
getopt(argc, argv,"s:O:R:M:i:Nn:d:Pp:l:hI:EU:L:t:m:W:T:D:c:b:A:k")) != EOF) {
|
||||
switch (opt) {
|
||||
case 's':
|
||||
pstrcpy(servicesf, optarg);
|
||||
@ -2646,6 +2690,15 @@ static int do_message_op(void)
|
||||
case 'b':
|
||||
io_bufsize = MAX(1, atoi(optarg));
|
||||
break;
|
||||
case 'k':
|
||||
#if HAVE_KRB5
|
||||
use_kerberos = True;
|
||||
got_pass = True;
|
||||
#else
|
||||
d_printf("No kerberos support compiled in\n");
|
||||
exit(1);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
usage(pname);
|
||||
exit(1);
|
||||
|
1697
source3/configure
vendored
1697
source3/configure
vendored
File diff suppressed because it is too large
Load Diff
@ -38,6 +38,9 @@ AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_AWK
|
||||
|
||||
dnl needed before AC_TRY_COMPILE
|
||||
AC_ISC_POSIX
|
||||
|
||||
dnl Check if C compiler understands -c and -o at the same time
|
||||
AC_PROG_CC_C_O
|
||||
if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" = no"; then
|
||||
@ -317,6 +320,11 @@ fi
|
||||
AC_CHECK_LIB(dl, dlopen, [LIBS="$LIBS -ldl";
|
||||
AC_DEFINE(HAVE_LIBDL)])
|
||||
|
||||
############################################
|
||||
# we need krb5 for w2k ADS authentication
|
||||
AC_CHECK_LIB(krb5, krb5_mk_req_extended, [LIBS="$LIBS -lkrb5";
|
||||
AC_DEFINE(HAVE_KRB5)])
|
||||
|
||||
|
||||
############################################
|
||||
# check if the compiler can do immediate structures
|
||||
|
42
source3/include/asn1.h
Normal file
42
source3/include/asn1.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 3.0
|
||||
simple ASN1 code
|
||||
Copyright (C) Andrew Tridgell 2001
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
|
||||
struct nesting {
|
||||
off_t start;
|
||||
struct nesting *next;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8 *data;
|
||||
size_t length;
|
||||
off_t ofs;
|
||||
struct nesting *nesting;
|
||||
} ASN1_DATA;
|
||||
|
||||
|
||||
#define ASN1_APPLICATION(x) ((x)+0x60)
|
||||
#define ASN1_SEQUENCE(x) ((x)+0x30)
|
||||
#define ASN1_CONTEXT(x) ((x)+0xa0)
|
||||
#define ASN1_GENERAL_STRING 0x1b
|
||||
#define ASN1_OCTET_STRING 0x4
|
||||
#define ASN1_OID 0x6
|
||||
#define ASN1_BOOLEAN 0x1
|
@ -92,7 +92,7 @@ struct cli_state {
|
||||
struct in_addr dest_ip;
|
||||
|
||||
struct pwd_info pwd;
|
||||
unsigned char cryptkey[8];
|
||||
DATA_BLOB secblob; /* cryptkey or negTokenInit */
|
||||
uint32 sesskey;
|
||||
int serverzone;
|
||||
uint32 servertime;
|
||||
@ -128,6 +128,7 @@ struct cli_state {
|
||||
uint16 max_recv_frag;
|
||||
vuser_key key;
|
||||
uint32 ntlmssp_flags;
|
||||
BOOL use_spnego; /* until we do NTLMSSP we need to make this optional */
|
||||
|
||||
BOOL use_oplocks; /* should we use oplocks? */
|
||||
BOOL use_level_II_oplocks; /* should we use level II oplocks? */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* include/config.h.in. Generated automatically from configure.in by autoheader. */
|
||||
/* include/config.h.in. Generated automatically from configure.in by autoheader 2.13. */
|
||||
|
||||
/* Define if on AIX 3.
|
||||
System headers sometimes define this.
|
||||
@ -268,6 +268,7 @@
|
||||
#undef HAVE_STPCPY
|
||||
#undef I18N_SWAT
|
||||
#undef I18N_DEFAULT_PREF_LANG
|
||||
#undef HAVE_KRB5
|
||||
|
||||
/* The number of bytes in a int. */
|
||||
#undef SIZEOF_INT
|
||||
|
@ -661,7 +661,7 @@ extern int errno;
|
||||
|
||||
#include "msdfs.h"
|
||||
|
||||
#include "profile.h"
|
||||
#include "smbprofile.h"
|
||||
|
||||
#include "mapping.h"
|
||||
|
||||
@ -672,6 +672,8 @@ extern int errno;
|
||||
|
||||
#include "session.h"
|
||||
|
||||
#include "asn1.h"
|
||||
|
||||
#ifndef MAXCODEPAGELINES
|
||||
#define MAXCODEPAGELINES 256
|
||||
#endif
|
||||
|
@ -1230,6 +1230,7 @@ char *strdup(char *s);
|
||||
|
||||
#define FLAGS2_LONG_PATH_COMPONENTS 0x0001
|
||||
#define FLAGS2_EXTENDED_ATTRIBUTES 0x0002
|
||||
#define FLAGS2_EXTENDED_SECURITY 0x0800
|
||||
#define FLAGS2_DFS_PATHNAMES 0x1000
|
||||
#define FLAGS2_READ_PERMIT_NO_EXECUTE 0x2000
|
||||
#define FLAGS2_32_BIT_ERROR_CODES 0x4000
|
||||
@ -1552,6 +1553,13 @@ typedef struct user_struct
|
||||
int session_id; /* used by utmp and pam session code */
|
||||
} user_struct;
|
||||
|
||||
/* used to hold an arbitrary blob of data */
|
||||
typedef struct {
|
||||
uint8 *data;
|
||||
size_t length;
|
||||
} DATA_BLOB;
|
||||
|
||||
|
||||
#include "ntdomain.h"
|
||||
|
||||
#include "client.h"
|
||||
|
461
source3/include/smbprofile.h
Normal file
461
source3/include/smbprofile.h
Normal file
@ -0,0 +1,461 @@
|
||||
#ifndef _PROFILE_H_
|
||||
#define _PROFILE_H_
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 1.9.
|
||||
store smbd profiling information in shared memory
|
||||
Copyright (C) Andrew Tridgell 1999
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* Reasons for cache flush.
|
||||
*/
|
||||
|
||||
#define NUM_FLUSH_REASONS 8 /* Keep this in sync with the enum below. */
|
||||
enum flush_reason_enum { SEEK_FLUSH, READ_FLUSH, WRITE_FLUSH, READRAW_FLUSH,
|
||||
OPLOCK_RELEASE_FLUSH, CLOSE_FLUSH, SYNC_FLUSH, SIZECHANGE_FLUSH };
|
||||
|
||||
/* this file defines the profile structure in the profile shared
|
||||
memory area */
|
||||
|
||||
#define PROF_SHMEM_KEY ((key_t)0x07021999)
|
||||
#define PROF_SHM_MAGIC 0x6349985
|
||||
#define PROF_SHM_VERSION 5
|
||||
|
||||
/* time values in the following structure are in microseconds */
|
||||
|
||||
struct profile_stats {
|
||||
/* general counters */
|
||||
unsigned smb_count; /* how many SMB packets we have processed */
|
||||
unsigned uid_changes; /* how many times we change our effective uid */
|
||||
/* system call counters */
|
||||
unsigned syscall_opendir_count;
|
||||
unsigned syscall_opendir_time;
|
||||
unsigned syscall_readdir_count;
|
||||
unsigned syscall_readdir_time;
|
||||
unsigned syscall_mkdir_count;
|
||||
unsigned syscall_mkdir_time;
|
||||
unsigned syscall_rmdir_count;
|
||||
unsigned syscall_rmdir_time;
|
||||
unsigned syscall_closedir_count;
|
||||
unsigned syscall_closedir_time;
|
||||
unsigned syscall_open_count;
|
||||
unsigned syscall_open_time;
|
||||
unsigned syscall_close_count;
|
||||
unsigned syscall_close_time;
|
||||
unsigned syscall_read_count;
|
||||
unsigned syscall_read_time;
|
||||
unsigned syscall_read_bytes; /* bytes read with read syscall */
|
||||
unsigned syscall_write_count;
|
||||
unsigned syscall_write_time;
|
||||
unsigned syscall_write_bytes; /* bytes written with write syscall */
|
||||
unsigned syscall_lseek_count;
|
||||
unsigned syscall_lseek_time;
|
||||
unsigned syscall_rename_count;
|
||||
unsigned syscall_rename_time;
|
||||
unsigned syscall_fsync_count;
|
||||
unsigned syscall_fsync_time;
|
||||
unsigned syscall_stat_count;
|
||||
unsigned syscall_stat_time;
|
||||
unsigned syscall_fstat_count;
|
||||
unsigned syscall_fstat_time;
|
||||
unsigned syscall_lstat_count;
|
||||
unsigned syscall_lstat_time;
|
||||
unsigned syscall_unlink_count;
|
||||
unsigned syscall_unlink_time;
|
||||
unsigned syscall_chmod_count;
|
||||
unsigned syscall_chmod_time;
|
||||
unsigned syscall_fchmod_count;
|
||||
unsigned syscall_fchmod_time;
|
||||
unsigned syscall_chown_count;
|
||||
unsigned syscall_chown_time;
|
||||
unsigned syscall_fchown_count;
|
||||
unsigned syscall_fchown_time;
|
||||
unsigned syscall_chdir_count;
|
||||
unsigned syscall_chdir_time;
|
||||
unsigned syscall_getwd_count;
|
||||
unsigned syscall_getwd_time;
|
||||
unsigned syscall_utime_count;
|
||||
unsigned syscall_utime_time;
|
||||
unsigned syscall_ftruncate_count;
|
||||
unsigned syscall_ftruncate_time;
|
||||
unsigned syscall_fcntl_lock_count;
|
||||
unsigned syscall_fcntl_lock_time;
|
||||
unsigned syscall_readlink_count;
|
||||
unsigned syscall_readlink_time;
|
||||
unsigned syscall_symlink_count;
|
||||
unsigned syscall_symlink_time;
|
||||
/* stat cache counters */
|
||||
unsigned statcache_lookups;
|
||||
unsigned statcache_misses;
|
||||
unsigned statcache_hits;
|
||||
/* write cache counters */
|
||||
unsigned writecache_read_hits;
|
||||
unsigned writecache_abutted_writes;
|
||||
unsigned writecache_total_writes;
|
||||
unsigned writecache_non_oplock_writes;
|
||||
unsigned writecache_direct_writes;
|
||||
unsigned writecache_init_writes;
|
||||
unsigned writecache_flushed_writes[NUM_FLUSH_REASONS];
|
||||
unsigned writecache_num_perfect_writes;
|
||||
unsigned writecache_num_write_caches;
|
||||
unsigned writecache_allocated_write_caches;
|
||||
/* counters for individual SMB types */
|
||||
unsigned SMBmkdir_count; /* create directory */
|
||||
unsigned SMBmkdir_time;
|
||||
unsigned SMBrmdir_count; /* delete directory */
|
||||
unsigned SMBrmdir_time;
|
||||
unsigned SMBopen_count; /* open file */
|
||||
unsigned SMBopen_time;
|
||||
unsigned SMBcreate_count; /* create file */
|
||||
unsigned SMBcreate_time;
|
||||
unsigned SMBclose_count; /* close file */
|
||||
unsigned SMBclose_time;
|
||||
unsigned SMBflush_count; /* flush file */
|
||||
unsigned SMBflush_time;
|
||||
unsigned SMBunlink_count; /* delete file */
|
||||
unsigned SMBunlink_time;
|
||||
unsigned SMBmv_count; /* rename file */
|
||||
unsigned SMBmv_time;
|
||||
unsigned SMBgetatr_count; /* get file attributes */
|
||||
unsigned SMBgetatr_time;
|
||||
unsigned SMBsetatr_count; /* set file attributes */
|
||||
unsigned SMBsetatr_time;
|
||||
unsigned SMBread_count; /* read from file */
|
||||
unsigned SMBread_time;
|
||||
unsigned SMBwrite_count; /* write to file */
|
||||
unsigned SMBwrite_time;
|
||||
unsigned SMBlock_count; /* lock byte range */
|
||||
unsigned SMBlock_time;
|
||||
unsigned SMBunlock_count; /* unlock byte range */
|
||||
unsigned SMBunlock_time;
|
||||
unsigned SMBctemp_count; /* create temporary file */
|
||||
unsigned SMBctemp_time;
|
||||
/* SMBmknew stats are currently combined with SMBcreate */
|
||||
unsigned SMBmknew_count; /* make new file */
|
||||
unsigned SMBmknew_time;
|
||||
unsigned SMBchkpth_count; /* check directory path */
|
||||
unsigned SMBchkpth_time;
|
||||
unsigned SMBexit_count; /* process exit */
|
||||
unsigned SMBexit_time;
|
||||
unsigned SMBlseek_count; /* seek */
|
||||
unsigned SMBlseek_time;
|
||||
unsigned SMBlockread_count; /* Lock a range and read */
|
||||
unsigned SMBlockread_time;
|
||||
unsigned SMBwriteunlock_count; /* Unlock a range then write */
|
||||
unsigned SMBwriteunlock_time;
|
||||
unsigned SMBreadbraw_count; /* read a block of data with no smb header */
|
||||
unsigned SMBreadbraw_time;
|
||||
unsigned SMBreadBmpx_count; /* read block multiplexed */
|
||||
unsigned SMBreadBmpx_time;
|
||||
unsigned SMBreadBs_count; /* read block (secondary response) */
|
||||
unsigned SMBreadBs_time;
|
||||
unsigned SMBwritebraw_count; /* write a block of data with no smb header */
|
||||
unsigned SMBwritebraw_time;
|
||||
unsigned SMBwriteBmpx_count; /* write block multiplexed */
|
||||
unsigned SMBwriteBmpx_time;
|
||||
unsigned SMBwriteBs_count; /* write block (secondary request) */
|
||||
unsigned SMBwriteBs_time;
|
||||
unsigned SMBwritec_count; /* secondary write request */
|
||||
unsigned SMBwritec_time;
|
||||
unsigned SMBsetattrE_count; /* set file attributes expanded */
|
||||
unsigned SMBsetattrE_time;
|
||||
unsigned SMBgetattrE_count; /* get file attributes expanded */
|
||||
unsigned SMBgetattrE_time;
|
||||
unsigned SMBlockingX_count; /* lock/unlock byte ranges and X */
|
||||
unsigned SMBlockingX_time;
|
||||
unsigned SMBtrans_count; /* transaction - name, bytes in/out */
|
||||
unsigned SMBtrans_time;
|
||||
unsigned SMBtranss_count; /* transaction (secondary request/response) */
|
||||
unsigned SMBtranss_time;
|
||||
unsigned SMBioctl_count; /* IOCTL */
|
||||
unsigned SMBioctl_time;
|
||||
unsigned SMBioctls_count; /* IOCTL (secondary request/response) */
|
||||
unsigned SMBioctls_time;
|
||||
unsigned SMBcopy_count; /* copy */
|
||||
unsigned SMBcopy_time;
|
||||
unsigned SMBmove_count; /* move */
|
||||
unsigned SMBmove_time;
|
||||
unsigned SMBecho_count; /* echo */
|
||||
unsigned SMBecho_time;
|
||||
unsigned SMBwriteclose_count; /* write a file then close it */
|
||||
unsigned SMBwriteclose_time;
|
||||
unsigned SMBopenX_count; /* open and X */
|
||||
unsigned SMBopenX_time;
|
||||
unsigned SMBreadX_count; /* read and X */
|
||||
unsigned SMBreadX_time;
|
||||
unsigned SMBwriteX_count; /* write and X */
|
||||
unsigned SMBwriteX_time;
|
||||
unsigned SMBtrans2_count; /* TRANS2 protocol set */
|
||||
unsigned SMBtrans2_time;
|
||||
unsigned SMBtranss2_count; /* TRANS2 protocol set, secondary command */
|
||||
unsigned SMBtranss2_time;
|
||||
unsigned SMBfindclose_count; /* Terminate a TRANSACT2_FINDFIRST */
|
||||
unsigned SMBfindclose_time;
|
||||
unsigned SMBfindnclose_count; /* Terminate a TRANSACT2_FINDNOTIFYFIRST */
|
||||
unsigned SMBfindnclose_time;
|
||||
unsigned SMBtcon_count; /* tree connect */
|
||||
unsigned SMBtcon_time;
|
||||
unsigned SMBtdis_count; /* tree disconnect */
|
||||
unsigned SMBtdis_time;
|
||||
unsigned SMBnegprot_count; /* negotiate protocol */
|
||||
unsigned SMBnegprot_time;
|
||||
unsigned SMBsesssetupX_count; /* Session Set Up & X (including User Logon) */
|
||||
unsigned SMBsesssetupX_time;
|
||||
unsigned SMBulogoffX_count; /* user logoff */
|
||||
unsigned SMBulogoffX_time;
|
||||
unsigned SMBtconX_count; /* tree connect and X*/
|
||||
unsigned SMBtconX_time;
|
||||
unsigned SMBdskattr_count; /* get disk attributes */
|
||||
unsigned SMBdskattr_time;
|
||||
unsigned SMBsearch_count; /* search directory */
|
||||
unsigned SMBsearch_time;
|
||||
/* SBMffirst stats combined with SMBsearch */
|
||||
unsigned SMBffirst_count; /* find first */
|
||||
unsigned SMBffirst_time;
|
||||
/* SBMfunique stats combined with SMBsearch */
|
||||
unsigned SMBfunique_count; /* find unique */
|
||||
unsigned SMBfunique_time;
|
||||
unsigned SMBfclose_count; /* find close */
|
||||
unsigned SMBfclose_time;
|
||||
unsigned SMBnttrans_count; /* NT transact */
|
||||
unsigned SMBnttrans_time;
|
||||
unsigned SMBnttranss_count; /* NT transact secondary */
|
||||
unsigned SMBnttranss_time;
|
||||
unsigned SMBntcreateX_count; /* NT create and X */
|
||||
unsigned SMBntcreateX_time;
|
||||
unsigned SMBntcancel_count; /* NT cancel */
|
||||
unsigned SMBntcancel_time;
|
||||
unsigned SMBsplopen_count; /* open print spool file */
|
||||
unsigned SMBsplopen_time;
|
||||
unsigned SMBsplwr_count; /* write to print spool file */
|
||||
unsigned SMBsplwr_time;
|
||||
unsigned SMBsplclose_count; /* close print spool file */
|
||||
unsigned SMBsplclose_time;
|
||||
unsigned SMBsplretq_count; /* return print queue */
|
||||
unsigned SMBsplretq_time;
|
||||
unsigned SMBsends_count; /* send single block message */
|
||||
unsigned SMBsends_time;
|
||||
unsigned SMBsendb_count; /* send broadcast message */
|
||||
unsigned SMBsendb_time;
|
||||
unsigned SMBfwdname_count; /* forward user name */
|
||||
unsigned SMBfwdname_time;
|
||||
unsigned SMBcancelf_count; /* cancel forward */
|
||||
unsigned SMBcancelf_time;
|
||||
unsigned SMBgetmac_count; /* get machine name */
|
||||
unsigned SMBgetmac_time;
|
||||
unsigned SMBsendstrt_count; /* send start of multi-block message */
|
||||
unsigned SMBsendstrt_time;
|
||||
unsigned SMBsendend_count; /* send end of multi-block message */
|
||||
unsigned SMBsendend_time;
|
||||
unsigned SMBsendtxt_count; /* send text of multi-block message */
|
||||
unsigned SMBsendtxt_time;
|
||||
unsigned SMBinvalid_count; /* invalid command */
|
||||
unsigned SMBinvalid_time;
|
||||
/* Pathworks setdir command */
|
||||
unsigned pathworks_setdir_count;
|
||||
unsigned pathworks_setdir_time;
|
||||
/* These are the TRANS2 sub commands */
|
||||
unsigned Trans2_open_count;
|
||||
unsigned Trans2_open_time;
|
||||
unsigned Trans2_findfirst_count;
|
||||
unsigned Trans2_findfirst_time;
|
||||
unsigned Trans2_findnext_count;
|
||||
unsigned Trans2_findnext_time;
|
||||
unsigned Trans2_qfsinfo_count;
|
||||
unsigned Trans2_qfsinfo_time;
|
||||
unsigned Trans2_setfsinfo_count;
|
||||
unsigned Trans2_setfsinfo_time;
|
||||
unsigned Trans2_qpathinfo_count;
|
||||
unsigned Trans2_qpathinfo_time;
|
||||
unsigned Trans2_setpathinfo_count;
|
||||
unsigned Trans2_setpathinfo_time;
|
||||
unsigned Trans2_qfileinfo_count;
|
||||
unsigned Trans2_qfileinfo_time;
|
||||
unsigned Trans2_setfileinfo_count;
|
||||
unsigned Trans2_setfileinfo_time;
|
||||
unsigned Trans2_fsctl_count;
|
||||
unsigned Trans2_fsctl_time;
|
||||
unsigned Trans2_ioctl_count;
|
||||
unsigned Trans2_ioctl_time;
|
||||
unsigned Trans2_findnotifyfirst_count;
|
||||
unsigned Trans2_findnotifyfirst_time;
|
||||
unsigned Trans2_findnotifynext_count;
|
||||
unsigned Trans2_findnotifynext_time;
|
||||
unsigned Trans2_mkdir_count;
|
||||
unsigned Trans2_mkdir_time;
|
||||
unsigned Trans2_session_setup_count;
|
||||
unsigned Trans2_session_setup_time;
|
||||
unsigned Trans2_get_dfs_referral_count;
|
||||
unsigned Trans2_get_dfs_referral_time;
|
||||
unsigned Trans2_report_dfs_inconsistancy_count;
|
||||
unsigned Trans2_report_dfs_inconsistancy_time;
|
||||
/* These are the NT transact sub commands. */
|
||||
unsigned NT_transact_create_count;
|
||||
unsigned NT_transact_create_time;
|
||||
unsigned NT_transact_ioctl_count;
|
||||
unsigned NT_transact_ioctl_time;
|
||||
unsigned NT_transact_set_security_desc_count;
|
||||
unsigned NT_transact_set_security_desc_time;
|
||||
unsigned NT_transact_notify_change_count;
|
||||
unsigned NT_transact_notify_change_time;
|
||||
unsigned NT_transact_rename_count;
|
||||
unsigned NT_transact_rename_time;
|
||||
unsigned NT_transact_query_security_desc_count;
|
||||
unsigned NT_transact_query_security_desc_time;
|
||||
/* These are ACL manipulation calls */
|
||||
unsigned get_nt_acl_count;
|
||||
unsigned get_nt_acl_time;
|
||||
unsigned fget_nt_acl_count;
|
||||
unsigned fget_nt_acl_time;
|
||||
unsigned set_nt_acl_count;
|
||||
unsigned set_nt_acl_time;
|
||||
unsigned fset_nt_acl_count;
|
||||
unsigned fset_nt_acl_time;
|
||||
unsigned chmod_acl_count;
|
||||
unsigned chmod_acl_time;
|
||||
unsigned fchmod_acl_count;
|
||||
unsigned fchmod_acl_time;
|
||||
/* These are nmbd stats */
|
||||
unsigned name_release_count;
|
||||
unsigned name_release_time;
|
||||
unsigned name_refresh_count;
|
||||
unsigned name_refresh_time;
|
||||
unsigned name_registration_count;
|
||||
unsigned name_registration_time;
|
||||
unsigned node_status_count;
|
||||
unsigned node_status_time;
|
||||
unsigned name_query_count;
|
||||
unsigned name_query_time;
|
||||
unsigned host_announce_count;
|
||||
unsigned host_announce_time;
|
||||
unsigned workgroup_announce_count;
|
||||
unsigned workgroup_announce_time;
|
||||
unsigned local_master_announce_count;
|
||||
unsigned local_master_announce_time;
|
||||
unsigned master_browser_announce_count;
|
||||
unsigned master_browser_announce_time;
|
||||
unsigned lm_host_announce_count;
|
||||
unsigned lm_host_announce_time;
|
||||
unsigned get_backup_list_count;
|
||||
unsigned get_backup_list_time;
|
||||
unsigned reset_browser_count;
|
||||
unsigned reset_browser_time;
|
||||
unsigned announce_request_count;
|
||||
unsigned announce_request_time;
|
||||
unsigned lm_announce_request_count;
|
||||
unsigned lm_announce_request_time;
|
||||
unsigned domain_logon_count;
|
||||
unsigned domain_logon_time;
|
||||
unsigned sync_browse_lists_count;
|
||||
unsigned sync_browse_lists_time;
|
||||
unsigned run_elections_count;
|
||||
unsigned run_elections_time;
|
||||
unsigned election_count;
|
||||
unsigned election_time;
|
||||
};
|
||||
|
||||
struct profile_header {
|
||||
int prof_shm_magic;
|
||||
int prof_shm_version;
|
||||
struct profile_stats stats;
|
||||
};
|
||||
|
||||
extern struct profile_header *profile_h;
|
||||
extern struct profile_stats *profile_p;
|
||||
extern struct timeval profile_starttime;
|
||||
extern struct timeval profile_endtime;
|
||||
extern struct timeval profile_starttime_nested;
|
||||
extern struct timeval profile_endtime_nested;
|
||||
extern BOOL do_profile_flag;
|
||||
extern BOOL do_profile_times;
|
||||
|
||||
/* these are helper macros - do not call them directly in the code
|
||||
* use the DO_PROFILE_* START_PROFILE and END_PROFILE ones
|
||||
* below which test for the profile flage first
|
||||
*/
|
||||
#define INC_PROFILE_COUNT(x) profile_p->x++
|
||||
#define DEC_PROFILE_COUNT(x) profile_p->x--
|
||||
#define ADD_PROFILE_COUNT(x,y) profile_p->x += (y)
|
||||
#define PROFILE_TIME \
|
||||
((profile_endtime.tv_sec - profile_starttime.tv_sec) *1000000 + \
|
||||
((int)profile_endtime.tv_usec - (int)profile_starttime.tv_usec))
|
||||
#define PROFILE_TIME_NESTED \
|
||||
((profile_endtime_nested.tv_sec - profile_starttime_nested.tv_sec) *1000000 + \
|
||||
((int)profile_endtime_nested.tv_usec - (int)profile_starttime_nested.tv_usec))
|
||||
|
||||
#ifdef WITH_PROFILE
|
||||
#define DO_PROFILE_INC(x) \
|
||||
if (do_profile_flag) { \
|
||||
INC_PROFILE_COUNT(x); \
|
||||
}
|
||||
#define DO_PROFILE_DEC(x) \
|
||||
if (do_profile_flag) { \
|
||||
DEC_PROFILE_COUNT(x); \
|
||||
}
|
||||
#define DO_PROFILE_DEC_INC(x,y) \
|
||||
if (do_profile_flag) { \
|
||||
DEC_PROFILE_COUNT(x); \
|
||||
INC_PROFILE_COUNT(y); \
|
||||
}
|
||||
#define DO_PROFILE_ADD(x,n) \
|
||||
if (do_profile_flag) { \
|
||||
ADD_PROFILE_COUNT(x,n); \
|
||||
}
|
||||
#define START_PROFILE(x) \
|
||||
if (do_profile_flag) { \
|
||||
if (do_profile_times) \
|
||||
GetTimeOfDay(&profile_starttime); \
|
||||
INC_PROFILE_COUNT(x##_count); \
|
||||
}
|
||||
#define START_PROFILE_NESTED(x) \
|
||||
if (do_profile_flag) { \
|
||||
if (do_profile_times) \
|
||||
GetTimeOfDay(&profile_starttime_nested); \
|
||||
INC_PROFILE_COUNT(x##_count); \
|
||||
}
|
||||
#define START_PROFILE_BYTES(x,n) \
|
||||
if (do_profile_flag) { \
|
||||
if (do_profile_times) \
|
||||
GetTimeOfDay(&profile_starttime); \
|
||||
INC_PROFILE_COUNT(x##_count); \
|
||||
ADD_PROFILE_COUNT(x##_bytes,n); \
|
||||
}
|
||||
#define END_PROFILE(x) \
|
||||
if (do_profile_times) { \
|
||||
GetTimeOfDay(&profile_endtime); \
|
||||
ADD_PROFILE_COUNT(x##_time,PROFILE_TIME); \
|
||||
}
|
||||
#define END_PROFILE_NESTED(x) \
|
||||
if (do_profile_times) { \
|
||||
GetTimeOfDay(&profile_endtime_nested); \
|
||||
ADD_PROFILE_COUNT(x##_time,PROFILE_TIME_NESTED); \
|
||||
}
|
||||
#else
|
||||
#define DO_PROFILE_INC(x)
|
||||
#define DO_PROFILE_DEC(x)
|
||||
#define DO_PROFILE_DEC_INC(x,y)
|
||||
#define DO_PROFILE_ADD(x,n)
|
||||
#define START_PROFILE(x)
|
||||
#define START_PROFILE_NESTED(x)
|
||||
#define START_PROFILE_BYTES(x,n)
|
||||
#define END_PROFILE(x)
|
||||
#define END_PROFILE_NESTED(x)
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1893,6 +1893,32 @@ BOOL unix_wild_match(char *pattern, char *string)
|
||||
return unix_do_match(p2, s2) == 0;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
construct a data blob, must be freed with data_blob_free()
|
||||
*******************************************************************/
|
||||
DATA_BLOB data_blob(void *p, size_t length)
|
||||
{
|
||||
DATA_BLOB ret;
|
||||
|
||||
if (!p) {
|
||||
ZERO_STRUCT(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret.data = memdup(p, length);
|
||||
ret.length = length;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
free a data blob
|
||||
*******************************************************************/
|
||||
void data_blob_free(DATA_BLOB d)
|
||||
{
|
||||
SAFE_FREE(d.data);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __INSURE__
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -573,3 +573,20 @@ void file_lines_slashcont(char **lines)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
save a lump of data into a file. Mostly used for debugging
|
||||
*/
|
||||
BOOL file_save(const char *fname, void *packet, size_t length)
|
||||
{
|
||||
int fd;
|
||||
fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
|
||||
if (fd == -1) {
|
||||
return False;
|
||||
}
|
||||
if (write(fd, packet, length) != length) {
|
||||
return False;
|
||||
}
|
||||
close(fd);
|
||||
return True;
|
||||
}
|
||||
|
139
source3/libsmb/asn1.c
Normal file
139
source3/libsmb/asn1.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 3.0
|
||||
simple SPNEGO routines
|
||||
Copyright (C) Andrew Tridgell 2001
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
void asn1_free(ASN1_DATA *data)
|
||||
{
|
||||
free(data->data);
|
||||
}
|
||||
|
||||
BOOL asn1_check_empty(ASN1_DATA *data)
|
||||
{
|
||||
if (data->nesting) return False;
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL asn1_write(ASN1_DATA *data, const void *p, int len)
|
||||
{
|
||||
if (data->length < data->ofs+len) {
|
||||
data->data = Realloc(data->data, data->ofs+len);
|
||||
if (!data->data) return False;
|
||||
data->length = data->ofs+len;
|
||||
}
|
||||
memcpy(data->data + data->ofs, p, len);
|
||||
data->ofs += len;
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL asn1_write_uint8(ASN1_DATA *data, uint8 v)
|
||||
{
|
||||
return asn1_write(data, &v, 1);
|
||||
}
|
||||
|
||||
BOOL asn1_push_tag(ASN1_DATA *data, uint8 tag)
|
||||
{
|
||||
struct nesting *nesting;
|
||||
|
||||
asn1_write_uint8(data, tag);
|
||||
nesting = (struct nesting *)malloc(sizeof(struct nesting));
|
||||
if (!nesting) return False;
|
||||
|
||||
nesting->start = data->ofs;
|
||||
nesting->next = data->nesting;
|
||||
data->nesting = nesting;
|
||||
asn1_write_uint8(data, 0xff);
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL asn1_pop_tag(ASN1_DATA *data)
|
||||
{
|
||||
struct nesting *nesting;
|
||||
size_t len;
|
||||
|
||||
nesting = data->nesting;
|
||||
|
||||
if (!nesting) {
|
||||
return False;
|
||||
}
|
||||
len = data->ofs - (nesting->start+1);
|
||||
if (len > 127) {
|
||||
data->data[nesting->start] = 0x82;
|
||||
asn1_write_uint8(data, 0);
|
||||
asn1_write_uint8(data, 0);
|
||||
memmove(data->data+nesting->start+3, data->data+nesting->start+1, len);
|
||||
data->data[nesting->start+1] = len>>8;
|
||||
data->data[nesting->start+2] = len&0xff;
|
||||
} else {
|
||||
data->data[nesting->start] = len;
|
||||
}
|
||||
|
||||
data->nesting = nesting->next;
|
||||
free(nesting);
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
BOOL asn1_write_OID(ASN1_DATA *data, const char *OID)
|
||||
{
|
||||
unsigned v, v2;
|
||||
char *p = (char *)OID;
|
||||
|
||||
asn1_push_tag(data, ASN1_OID);
|
||||
v = strtol(p, &p, 10);
|
||||
v2 = strtol(p, &p, 10);
|
||||
asn1_write_uint8(data, 40*v + v2);
|
||||
|
||||
while (*p) {
|
||||
v = strtol(p, &p, 10);
|
||||
if (v >= (1<<28)) asn1_write_uint8(data, 0x80 | ((v>>28)&0xff));
|
||||
if (v >= (1<<21)) asn1_write_uint8(data, 0x80 | ((v>>21)&0xff));
|
||||
if (v >= (1<<14)) asn1_write_uint8(data, 0x80 | ((v>>14)&0xff));
|
||||
if (v >= (1<<7)) asn1_write_uint8(data, 0x80 | ((v>>7)&0xff));
|
||||
asn1_write_uint8(data, v&0x7f);
|
||||
}
|
||||
asn1_pop_tag(data);
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL asn1_write_OctetString(ASN1_DATA *data, const void *p, size_t length)
|
||||
{
|
||||
asn1_push_tag(data, ASN1_OCTET_STRING);
|
||||
asn1_write(data, p, length);
|
||||
asn1_pop_tag(data);
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL asn1_write_GeneralString(ASN1_DATA *data, const char *s)
|
||||
{
|
||||
asn1_push_tag(data, ASN1_GENERAL_STRING);
|
||||
asn1_write(data, s, strlen(s));
|
||||
asn1_pop_tag(data);
|
||||
return True;
|
||||
}
|
||||
|
||||
BOOL asn1_write_BOOLEAN(ASN1_DATA *data, BOOL v)
|
||||
{
|
||||
asn1_write_uint8(data, ASN1_BOOLEAN);
|
||||
asn1_write_uint8(data, v);
|
||||
return True;
|
||||
}
|
||||
|
@ -31,23 +31,365 @@ static struct {
|
||||
prots[] =
|
||||
{
|
||||
{PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
|
||||
{PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
|
||||
{PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
|
||||
{PROTOCOL_LANMAN1,"LANMAN1.0"},
|
||||
{PROTOCOL_LANMAN1,"Windows for Workgroups 3.1a"},
|
||||
{PROTOCOL_LANMAN2,"LM1.2X002"},
|
||||
{PROTOCOL_LANMAN2,"Samba"},
|
||||
{PROTOCOL_NT1,"NT LANMAN 1.0"},
|
||||
{PROTOCOL_NT1,"LANMAN2.1"},
|
||||
{PROTOCOL_NT1,"NT LM 0.12"},
|
||||
{-1,NULL}
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
do an old lanman2 style session setup
|
||||
****************************************************************************/
|
||||
static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user,
|
||||
char *pass, int passlen)
|
||||
{
|
||||
fstring pword;
|
||||
char *p;
|
||||
|
||||
if (passlen > sizeof(pword)-1) {
|
||||
return False;
|
||||
}
|
||||
|
||||
/* if in share level security then don't send a password now */
|
||||
if (!(cli->sec_mode & 1)) {
|
||||
passlen = 0;
|
||||
}
|
||||
|
||||
if (passlen > 0 && (cli->sec_mode & 2) && passlen != 24) {
|
||||
/* Encrypted mode needed, and non encrypted password supplied. */
|
||||
passlen = 24;
|
||||
clistr_push(cli, pword, pass, -1, STR_TERMINATE);
|
||||
SMBencrypt((uchar *)pword,cli->secblob.data,(uchar *)pword);
|
||||
} else if ((cli->sec_mode & 2) && passlen == 24) {
|
||||
/* Encrypted mode needed, and encrypted password supplied. */
|
||||
memcpy(pword, pass, passlen);
|
||||
} else if (passlen > 0) {
|
||||
/* Plaintext mode needed, assume plaintext supplied. */
|
||||
passlen = clistr_push(cli, pword, pass, -1, STR_TERMINATE);
|
||||
}
|
||||
|
||||
/* send a session setup command */
|
||||
memset(cli->outbuf,'\0',smb_size);
|
||||
set_message(cli->outbuf,10, 0, True);
|
||||
CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
|
||||
cli_setup_packet(cli);
|
||||
|
||||
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
|
||||
SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
|
||||
SSVAL(cli->outbuf,smb_vwv3,2);
|
||||
SSVAL(cli->outbuf,smb_vwv4,1);
|
||||
SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
|
||||
SSVAL(cli->outbuf,smb_vwv7,passlen);
|
||||
|
||||
p = smb_buf(cli->outbuf);
|
||||
memcpy(p,pword,passlen);
|
||||
p += passlen;
|
||||
p += clistr_push(cli, p, user, -1, STR_UPPER|STR_TERMINATE);
|
||||
cli_setup_bcc(cli, p);
|
||||
|
||||
cli_send_smb(cli);
|
||||
if (!cli_receive_smb(cli))
|
||||
return False;
|
||||
|
||||
show_msg(cli->inbuf);
|
||||
|
||||
if (cli_is_error(cli)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
/* use the returned vuid from now on */
|
||||
cli->vuid = SVAL(cli->inbuf,smb_uid);
|
||||
fstrcpy(cli->user_name, user);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
work out suitable capabilities to offer the server
|
||||
****************************************************************************/
|
||||
static uint32 cli_session_setup_capabilities(struct cli_state *cli)
|
||||
{
|
||||
uint32 capabilities = CAP_NT_SMBS;
|
||||
|
||||
/* Set the CLI_FORCE_DOSERR environment variable to test
|
||||
client routines using DOS errors instead of STATUS32
|
||||
ones. This intended only as a temporary hack. */
|
||||
if (!getenv("CLI_FORCE_DOSERR")) {
|
||||
capabilities |= CAP_STATUS32;
|
||||
}
|
||||
|
||||
if (cli->use_level_II_oplocks) {
|
||||
capabilities |= CAP_LEVEL_II_OPLOCKS;
|
||||
}
|
||||
|
||||
if (cli->capabilities & CAP_UNICODE) {
|
||||
capabilities |= CAP_UNICODE;
|
||||
}
|
||||
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
do a NT1 guest session setup
|
||||
****************************************************************************/
|
||||
static BOOL cli_session_setup_guest(struct cli_state *cli)
|
||||
{
|
||||
char *p;
|
||||
uint32 capabilities = cli_session_setup_capabilities(cli);
|
||||
|
||||
set_message(cli->outbuf,13,0,True);
|
||||
CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
|
||||
cli_setup_packet(cli);
|
||||
|
||||
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
|
||||
SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
|
||||
SSVAL(cli->outbuf,smb_vwv3,2);
|
||||
SSVAL(cli->outbuf,smb_vwv4,cli->pid);
|
||||
SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
|
||||
SSVAL(cli->outbuf,smb_vwv7,0);
|
||||
SSVAL(cli->outbuf,smb_vwv8,0);
|
||||
SIVAL(cli->outbuf,smb_vwv11,capabilities);
|
||||
p = smb_buf(cli->outbuf);
|
||||
p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* username */
|
||||
p += clistr_push(cli, p, "", -1, STR_TERMINATE); /* workgroup */
|
||||
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
|
||||
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
|
||||
cli_setup_bcc(cli, p);
|
||||
|
||||
cli_send_smb(cli);
|
||||
if (!cli_receive_smb(cli))
|
||||
return False;
|
||||
|
||||
show_msg(cli->inbuf);
|
||||
|
||||
if (cli_is_error(cli)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
cli->vuid = SVAL(cli->inbuf,smb_uid);
|
||||
|
||||
p = smb_buf(cli->inbuf);
|
||||
p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
|
||||
fstrcpy(cli->user_name, "");
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
do a NT1 plaintext session setup
|
||||
****************************************************************************/
|
||||
static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user,
|
||||
char *pass, char *workgroup)
|
||||
{
|
||||
uint32 capabilities = cli_session_setup_capabilities(cli);
|
||||
fstring pword;
|
||||
int passlen;
|
||||
char *p;
|
||||
|
||||
passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
|
||||
|
||||
set_message(cli->outbuf,13,0,True);
|
||||
CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
|
||||
cli_setup_packet(cli);
|
||||
|
||||
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
|
||||
SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
|
||||
SSVAL(cli->outbuf,smb_vwv3,2);
|
||||
SSVAL(cli->outbuf,smb_vwv4,cli->pid);
|
||||
SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
|
||||
SSVAL(cli->outbuf,smb_vwv7,passlen);
|
||||
SSVAL(cli->outbuf,smb_vwv8,0);
|
||||
SIVAL(cli->outbuf,smb_vwv11,capabilities);
|
||||
p = smb_buf(cli->outbuf);
|
||||
memcpy(p, pword, passlen);
|
||||
p += passlen;
|
||||
p += clistr_push(cli, p, user, -1, STR_TERMINATE); /* username */
|
||||
p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE); /* workgroup */
|
||||
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
|
||||
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
|
||||
cli_setup_bcc(cli, p);
|
||||
|
||||
cli_send_smb(cli);
|
||||
if (!cli_receive_smb(cli))
|
||||
return False;
|
||||
|
||||
show_msg(cli->inbuf);
|
||||
|
||||
if (cli_is_error(cli)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
cli->vuid = SVAL(cli->inbuf,smb_uid);
|
||||
p = smb_buf(cli->inbuf);
|
||||
p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
fstrcpy(cli->user_name, user);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
do a NT1 NTLM/LM encrypted session setup
|
||||
****************************************************************************/
|
||||
static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
|
||||
char *pass, int passlen,
|
||||
char *ntpass, int ntpasslen,
|
||||
char *workgroup)
|
||||
{
|
||||
uint32 capabilities = cli_session_setup_capabilities(cli);
|
||||
fstring pword, ntpword;
|
||||
char *p;
|
||||
|
||||
if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (passlen != 24) {
|
||||
/* non encrypted password supplied. */
|
||||
passlen = 24;
|
||||
ntpasslen = 24;
|
||||
clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
|
||||
clistr_push(cli, ntpword, ntpass, sizeof(ntpword), STR_TERMINATE);
|
||||
SMBencrypt((uchar *)pword,cli->secblob.data,(uchar *)pword);
|
||||
SMBNTencrypt((uchar *)ntpword,cli->secblob.data,(uchar *)ntpword);
|
||||
} else {
|
||||
memcpy(pword, pass, passlen);
|
||||
memcpy(ntpword, ntpass, ntpasslen);
|
||||
}
|
||||
|
||||
/* send a session setup command */
|
||||
memset(cli->outbuf,'\0',smb_size);
|
||||
|
||||
set_message(cli->outbuf,13,0,True);
|
||||
CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
|
||||
cli_setup_packet(cli);
|
||||
|
||||
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
|
||||
SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
|
||||
SSVAL(cli->outbuf,smb_vwv3,2);
|
||||
SSVAL(cli->outbuf,smb_vwv4,cli->pid);
|
||||
SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
|
||||
SSVAL(cli->outbuf,smb_vwv7,passlen);
|
||||
SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
|
||||
SIVAL(cli->outbuf,smb_vwv11,capabilities);
|
||||
p = smb_buf(cli->outbuf);
|
||||
memcpy(p,pword,passlen); p += passlen;
|
||||
memcpy(p,ntpword,ntpasslen); p += ntpasslen;
|
||||
p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
|
||||
p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
|
||||
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
|
||||
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
|
||||
cli_setup_bcc(cli, p);
|
||||
|
||||
cli_send_smb(cli);
|
||||
if (!cli_receive_smb(cli))
|
||||
return False;
|
||||
|
||||
show_msg(cli->inbuf);
|
||||
|
||||
if (cli_is_error(cli)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
/* use the returned vuid from now on */
|
||||
cli->vuid = SVAL(cli->inbuf,smb_uid);
|
||||
|
||||
p = smb_buf(cli->inbuf);
|
||||
p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
|
||||
fstrcpy(cli->user_name, user);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
#if HAVE_KRB5
|
||||
/****************************************************************************
|
||||
do a spnego encrypted session setup
|
||||
****************************************************************************/
|
||||
static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user,
|
||||
char *pass, char *workgroup)
|
||||
{
|
||||
uint32 capabilities = cli_session_setup_capabilities(cli);
|
||||
char *p;
|
||||
DATA_BLOB blob2, negTokenTarg;
|
||||
|
||||
negTokenTarg = spnego_gen_negTokenTarg(cli);
|
||||
|
||||
capabilities |= CAP_EXTENDED_SECURITY;
|
||||
|
||||
/* send a session setup command */
|
||||
memset(cli->outbuf,'\0',smb_size);
|
||||
|
||||
set_message(cli->outbuf,12,0,True);
|
||||
CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
|
||||
cli_setup_packet(cli);
|
||||
|
||||
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
|
||||
SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
|
||||
SSVAL(cli->outbuf,smb_vwv3,2);
|
||||
SSVAL(cli->outbuf,smb_vwv4,0);
|
||||
SIVAL(cli->outbuf,smb_vwv5,0);
|
||||
SSVAL(cli->outbuf,smb_vwv7,negTokenTarg.length);
|
||||
SIVAL(cli->outbuf,smb_vwv10,capabilities);
|
||||
p = smb_buf(cli->outbuf);
|
||||
memcpy(p, negTokenTarg.data, negTokenTarg.length);
|
||||
p += negTokenTarg.length;
|
||||
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
|
||||
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
|
||||
cli_setup_bcc(cli, p);
|
||||
|
||||
cli_send_smb(cli);
|
||||
if (!cli_receive_smb(cli))
|
||||
return False;
|
||||
|
||||
show_msg(cli->inbuf);
|
||||
|
||||
if (cli_is_error(cli)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
/* use the returned vuid from now on */
|
||||
cli->vuid = SVAL(cli->inbuf,smb_uid);
|
||||
|
||||
p = smb_buf(cli->inbuf);
|
||||
|
||||
blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
|
||||
|
||||
p += blob2.length;
|
||||
p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
|
||||
|
||||
fstrcpy(cli->user_name, user);
|
||||
|
||||
data_blob_free(negTokenTarg);
|
||||
|
||||
/* we don't need this blob until we do NTLMSSP */
|
||||
data_blob_free(blob2);
|
||||
|
||||
return True;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
Send a session setup. The username and workgroup is in UNIX character
|
||||
format and must be converted to DOS codepage format before sending. If the
|
||||
password is in plaintext, the same should be done.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL cli_session_setup(struct cli_state *cli,
|
||||
char *user,
|
||||
char *pass, int passlen,
|
||||
@ -55,7 +397,6 @@ BOOL cli_session_setup(struct cli_state *cli,
|
||||
char *workgroup)
|
||||
{
|
||||
char *p;
|
||||
fstring pword, ntpword;
|
||||
fstring user2;
|
||||
|
||||
/* allow for workgroups as part of the username */
|
||||
@ -69,146 +410,45 @@ BOOL cli_session_setup(struct cli_state *cli,
|
||||
if (cli->protocol < PROTOCOL_LANMAN1)
|
||||
return True;
|
||||
|
||||
if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
|
||||
return False;
|
||||
/* now work out what sort of session setup we are going to
|
||||
do. I have split this into separate functions to make the
|
||||
flow a bit easier to understand (tridge) */
|
||||
|
||||
/* if its an older server then we have to use the older request format */
|
||||
if (cli->protocol < PROTOCOL_NT1) {
|
||||
return cli_session_setup_lanman2(cli, user, pass, passlen);
|
||||
}
|
||||
|
||||
if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0')) {
|
||||
/* Null session connect. */
|
||||
pword[0] = '\0';
|
||||
ntpword[0] = '\0';
|
||||
} else {
|
||||
if ((cli->sec_mode & 2) && passlen != 24) {
|
||||
/*
|
||||
* Encrypted mode needed, and non encrypted password supplied.
|
||||
*/
|
||||
passlen = 24;
|
||||
ntpasslen = 24;
|
||||
clistr_push(cli, pword, pass, -1, STR_TERMINATE);
|
||||
fstrcpy(ntpword, ntpass);;
|
||||
SMBencrypt((uchar *)pword,(uchar *)cli->cryptkey,(uchar *)pword);
|
||||
SMBNTencrypt((uchar *)ntpword,(uchar *)cli->cryptkey,(uchar *)ntpword);
|
||||
} else if ((cli->sec_mode & 2) && passlen == 24) {
|
||||
/*
|
||||
* Encrypted mode needed, and encrypted password supplied.
|
||||
*/
|
||||
memcpy(pword, pass, passlen);
|
||||
if(ntpasslen == 24) {
|
||||
memcpy(ntpword, ntpass, ntpasslen);
|
||||
} else {
|
||||
fstrcpy(ntpword, "");
|
||||
ntpasslen = 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Plaintext mode needed, assume plaintext supplied.
|
||||
*/
|
||||
passlen = clistr_push(cli, pword, pass, -1, STR_TERMINATE);
|
||||
fstrcpy(ntpword, "");
|
||||
ntpasslen = 0;
|
||||
}
|
||||
/* if no user is supplied then we have to do an anonymous connection.
|
||||
passwords are ignored */
|
||||
if (!user || !*user) {
|
||||
return cli_session_setup_guest(cli);
|
||||
}
|
||||
|
||||
/* if in share level security then don't send a password now */
|
||||
if (!(cli->sec_mode & 1)) {
|
||||
fstrcpy(pword, "");
|
||||
passlen=1;
|
||||
fstrcpy(ntpword, "");
|
||||
ntpasslen=1;
|
||||
}
|
||||
|
||||
/* send a session setup command */
|
||||
memset(cli->outbuf,'\0',smb_size);
|
||||
|
||||
if (cli->protocol < PROTOCOL_NT1)
|
||||
{
|
||||
set_message(cli->outbuf,10, 0, True);
|
||||
CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
|
||||
cli_setup_packet(cli);
|
||||
|
||||
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
|
||||
SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
|
||||
SSVAL(cli->outbuf,smb_vwv3,2);
|
||||
SSVAL(cli->outbuf,smb_vwv4,1);
|
||||
SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
|
||||
SSVAL(cli->outbuf,smb_vwv7,passlen);
|
||||
p = smb_buf(cli->outbuf);
|
||||
memcpy(p,pword,passlen);
|
||||
p += passlen;
|
||||
p += clistr_push(cli, p, user, -1, STR_UPPER|STR_TERMINATE);
|
||||
cli_setup_bcc(cli, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 capabilities;
|
||||
|
||||
capabilities = CAP_NT_SMBS;
|
||||
|
||||
/* Set the CLI_FORCE_DOSERR environment variable to test
|
||||
client routines using DOS errors instead of STATUS32
|
||||
ones. This intended only as a temporary hack. */
|
||||
|
||||
if (!getenv("CLI_FORCE_DOSERR")) {
|
||||
capabilities |= CAP_STATUS32;
|
||||
}
|
||||
|
||||
if (cli->use_level_II_oplocks) {
|
||||
capabilities |= CAP_LEVEL_II_OPLOCKS;
|
||||
}
|
||||
if (cli->capabilities & CAP_UNICODE) {
|
||||
capabilities |= CAP_UNICODE;
|
||||
}
|
||||
set_message(cli->outbuf,13,0,True);
|
||||
CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
|
||||
cli_setup_packet(cli);
|
||||
|
||||
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
|
||||
SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
|
||||
SSVAL(cli->outbuf,smb_vwv3,2);
|
||||
SSVAL(cli->outbuf,smb_vwv4,cli->pid);
|
||||
SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
|
||||
SSVAL(cli->outbuf,smb_vwv7,passlen);
|
||||
SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
|
||||
SIVAL(cli->outbuf,smb_vwv11,capabilities);
|
||||
p = smb_buf(cli->outbuf);
|
||||
memcpy(p,pword,passlen);
|
||||
p += SVAL(cli->outbuf,smb_vwv7);
|
||||
memcpy(p,ntpword,ntpasslen);
|
||||
p += SVAL(cli->outbuf,smb_vwv8);
|
||||
p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
|
||||
p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
|
||||
p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
|
||||
p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
|
||||
cli_setup_bcc(cli, p);
|
||||
/* if the server is share level then send a plaintext null
|
||||
password at this point. The password is sent in the tree
|
||||
connect */
|
||||
if ((cli->sec_mode & 1) == 0) {
|
||||
return cli_session_setup_plaintext(cli, user, "", workgroup);
|
||||
}
|
||||
|
||||
cli_send_smb(cli);
|
||||
if (!cli_receive_smb(cli))
|
||||
return False;
|
||||
/* if the server doesn't support encryption then we have to use plaintext. The
|
||||
second password is ignored */
|
||||
if ((cli->sec_mode & 2) == 0) {
|
||||
return cli_session_setup_plaintext(cli, user, pass, workgroup);
|
||||
}
|
||||
|
||||
show_msg(cli->inbuf);
|
||||
#if HAVE_KRB5
|
||||
/* if the server supports extended security then use SPNEGO */
|
||||
if (cli->capabilities & CAP_EXTENDED_SECURITY) {
|
||||
return cli_session_setup_spnego(cli, user, pass, workgroup);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cli_is_error(cli)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
/* use the returned vuid from now on */
|
||||
cli->vuid = SVAL(cli->inbuf,smb_uid);
|
||||
|
||||
if (cli->protocol >= PROTOCOL_NT1) {
|
||||
/*
|
||||
* Save off some of the connected server
|
||||
* info.
|
||||
*/
|
||||
char *q = smb_buf(cli->inbuf);
|
||||
q += clistr_pull(cli, cli->server_os, q, sizeof(fstring), -1, STR_TERMINATE);
|
||||
q += clistr_pull(cli, cli->server_type, q, sizeof(fstring), -1, STR_TERMINATE);
|
||||
q += clistr_pull(cli, cli->server_domain, q, sizeof(fstring), -1, STR_TERMINATE);
|
||||
}
|
||||
|
||||
fstrcpy(cli->user_name, user);
|
||||
|
||||
return True;
|
||||
/* otherwise do a NT1 style session setup */
|
||||
return cli_session_setup_nt1(cli, user,
|
||||
pass, passlen, ntpass, ntpasslen,
|
||||
workgroup);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -256,8 +496,7 @@ BOOL cli_send_tconX(struct cli_state *cli,
|
||||
*/
|
||||
passlen = 24;
|
||||
clistr_push(cli, dos_pword, pass, -1, STR_TERMINATE);
|
||||
|
||||
SMBencrypt((uchar *)dos_pword,(uchar *)cli->cryptkey,(uchar *)pword);
|
||||
SMBencrypt((uchar *)dos_pword,cli->secblob.data,(uchar *)pword);
|
||||
} else {
|
||||
if((cli->sec_mode & 3) == 0) {
|
||||
/*
|
||||
@ -404,6 +643,11 @@ BOOL cli_negprot(struct cli_state *cli)
|
||||
|
||||
CVAL(smb_buf(cli->outbuf),0) = 2;
|
||||
|
||||
if (cli->use_spnego) {
|
||||
SSVAL(cli->outbuf, smb_flg2,
|
||||
SVAL(cli->outbuf, smb_flg2) | FLAGS2_EXTENDED_SECURITY);
|
||||
}
|
||||
|
||||
cli_send_smb(cli);
|
||||
if (!cli_receive_smb(cli))
|
||||
return False;
|
||||
@ -427,7 +671,7 @@ BOOL cli_negprot(struct cli_state *cli)
|
||||
cli->serverzone *= 60;
|
||||
/* this time arrives in real GMT */
|
||||
cli->servertime = interpret_long_date(cli->inbuf+smb_vwv11+1);
|
||||
memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
|
||||
cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
|
||||
cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
|
||||
if (cli->capabilities & CAP_RAW_MODE) {
|
||||
cli->readbraw_supported = True;
|
||||
@ -449,7 +693,7 @@ BOOL cli_negprot(struct cli_state *cli)
|
||||
cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
|
||||
cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
|
||||
cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
|
||||
memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
|
||||
cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
|
||||
} else {
|
||||
/* the old core protocol */
|
||||
cli->sec_mode = 0;
|
||||
@ -481,7 +725,6 @@ BOOL cli_session_request(struct cli_state *cli,
|
||||
if (cli->port == 445) return True;
|
||||
|
||||
/* send a session request (RFC 1002) */
|
||||
|
||||
memcpy(&(cli->calling), calling, sizeof(*calling));
|
||||
memcpy(&(cli->called ), called , sizeof(*called ));
|
||||
|
||||
@ -758,7 +1001,7 @@ BOOL cli_establish_connection(struct cli_state *cli,
|
||||
unsigned char lm_sess_pwd[24];
|
||||
|
||||
/* creates (storing a copy of) and then obtains a 24 byte password OWF */
|
||||
pwd_make_lm_nt_owf(&(cli->pwd), cli->cryptkey);
|
||||
pwd_make_lm_nt_owf(&(cli->pwd), cli->secblob.data);
|
||||
pwd_get_lm_nt_owf(&(cli->pwd), lm_sess_pwd, nt_sess_pwd);
|
||||
|
||||
/* attempt encrypted session */
|
||||
|
@ -112,6 +112,10 @@ void cli_setup_packet(struct cli_state *cli)
|
||||
if (cli->capabilities & CAP_STATUS32) {
|
||||
flags2 |= FLAGS2_32_BIT_ERROR_CODES;
|
||||
}
|
||||
if (cli->use_spnego) {
|
||||
/* once we have NTLMSSP we can enable this unconditionally */
|
||||
flags2 |= FLAGS2_EXTENDED_SECURITY;
|
||||
}
|
||||
SSVAL(cli->outbuf,smb_flg2, flags2);
|
||||
}
|
||||
}
|
||||
@ -215,15 +219,17 @@ void cli_shutdown(struct cli_state *cli)
|
||||
SAFE_FREE(cli->outbuf);
|
||||
SAFE_FREE(cli->inbuf);
|
||||
|
||||
data_blob_free(cli->secblob);
|
||||
|
||||
if (cli->mem_ctx)
|
||||
talloc_destroy(cli->mem_ctx);
|
||||
|
||||
#ifdef WITH_SSL
|
||||
if (cli->fd != -1)
|
||||
sslutil_disconnect(cli->fd);
|
||||
if (cli->fd != -1)
|
||||
sslutil_disconnect(cli->fd);
|
||||
#endif /* WITH_SSL */
|
||||
if (cli->fd != -1)
|
||||
close(cli->fd);
|
||||
close(cli->fd);
|
||||
memset(cli, 0, sizeof(*cli));
|
||||
}
|
||||
|
||||
|
267
source3/libsmb/clikrb5.c
Normal file
267
source3/libsmb/clikrb5.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 3.0
|
||||
simple kerberos5/SPNEGO routines
|
||||
Copyright (C) Andrew Tridgell 2001
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
#if HAVE_KRB5
|
||||
#include <krb5.h>
|
||||
|
||||
#define OID_SPNEGO "1 3 6 1 5 5 2"
|
||||
#define OID_KERBEROS5 "1 2 840 113554 1 2 2"
|
||||
|
||||
static krb5_error_code krb5_mk_req2(krb5_context context,
|
||||
krb5_auth_context *auth_context,
|
||||
const krb5_flags ap_req_options,
|
||||
const char *service,
|
||||
krb5_data *in_data,
|
||||
krb5_ccache ccache,
|
||||
krb5_data *outbuf)
|
||||
{
|
||||
krb5_error_code retval;
|
||||
krb5_principal server;
|
||||
krb5_creds * credsp;
|
||||
krb5_creds creds;
|
||||
char *realm;
|
||||
|
||||
/* we should really get the realm from the negTargInit packet,
|
||||
but this will do until I've done the asn1 decoder for that */
|
||||
if ((retval = krb5_get_default_realm(context, &realm))) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = krb5_build_principal(context, &server, strlen(realm),
|
||||
realm, service, NULL);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* obtain ticket & session key */
|
||||
memset((char *)&creds, 0, sizeof(creds));
|
||||
if ((retval = krb5_copy_principal(context, server, &creds.server)))
|
||||
goto cleanup_princ;
|
||||
|
||||
if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
|
||||
goto cleanup_creds;
|
||||
|
||||
if ((retval = krb5_get_credentials(context, 0,
|
||||
ccache, &creds, &credsp)))
|
||||
goto cleanup_creds;
|
||||
|
||||
retval = krb5_mk_req_extended(context, auth_context, ap_req_options,
|
||||
in_data, credsp, outbuf);
|
||||
|
||||
krb5_free_creds(context, credsp);
|
||||
|
||||
cleanup_creds:
|
||||
krb5_free_cred_contents(context, &creds);
|
||||
|
||||
cleanup_princ:
|
||||
krb5_free_principal(context, server);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
get a kerberos5 ticket for the given service
|
||||
*/
|
||||
static DATA_BLOB krb5_get_ticket(char *service)
|
||||
{
|
||||
krb5_error_code retval;
|
||||
krb5_data packet, inbuf;
|
||||
krb5_ccache ccdef;
|
||||
krb5_context context;
|
||||
krb5_auth_context auth_context = NULL;
|
||||
DATA_BLOB ret;
|
||||
|
||||
retval = krb5_init_context(&context);
|
||||
if (retval) {
|
||||
DEBUG(1,("krb5_init_context failed\n"));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
inbuf.length = 0;
|
||||
|
||||
if ((retval = krb5_cc_default(context, &ccdef))) {
|
||||
DEBUG(1,("krb5_cc_default failed\n"));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if ((retval = krb5_mk_req2(context,
|
||||
&auth_context,
|
||||
AP_OPTS_MUTUAL_REQUIRED,
|
||||
service,
|
||||
&inbuf, ccdef, &packet))) {
|
||||
DEBUG(1,("krb5_mk_req2 failed\n"));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ret = data_blob(packet.data, packet.length);
|
||||
/* XXX need to free up a bunch of krb5 stuff here */
|
||||
|
||||
return ret;
|
||||
|
||||
failed:
|
||||
return data_blob(NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
generate a negTokenInit packet given a GUID, a list of supported
|
||||
OIDs (the mechanisms) and a principle name string
|
||||
*/
|
||||
ASN1_DATA spnego_gen_negTokenInit(uint8 guid[16],
|
||||
const char *OIDs[],
|
||||
const char *principle)
|
||||
{
|
||||
int i;
|
||||
ASN1_DATA data;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
asn1_write(&data, guid, 16);
|
||||
asn1_push_tag(&data,ASN1_APPLICATION(0));
|
||||
asn1_write_OID(&data,OID_SPNEGO);
|
||||
asn1_push_tag(&data,ASN1_CONTEXT(0));
|
||||
asn1_push_tag(&data,ASN1_SEQUENCE(0));
|
||||
|
||||
asn1_push_tag(&data,ASN1_CONTEXT(0));
|
||||
asn1_push_tag(&data,ASN1_SEQUENCE(0));
|
||||
for (i=0; OIDs[i]; i++) {
|
||||
asn1_write_OID(&data,OIDs[i]);
|
||||
}
|
||||
asn1_pop_tag(&data);
|
||||
asn1_pop_tag(&data);
|
||||
|
||||
asn1_push_tag(&data, ASN1_CONTEXT(3));
|
||||
asn1_push_tag(&data, ASN1_SEQUENCE(0));
|
||||
asn1_push_tag(&data, ASN1_CONTEXT(0));
|
||||
asn1_write_GeneralString(&data,principle);
|
||||
asn1_pop_tag(&data);
|
||||
asn1_pop_tag(&data);
|
||||
asn1_pop_tag(&data);
|
||||
|
||||
asn1_pop_tag(&data);
|
||||
asn1_pop_tag(&data);
|
||||
|
||||
asn1_pop_tag(&data);
|
||||
|
||||
asn1_check_empty(&data);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
generate a negTokenTarg packet given a list of OIDs and a security blob
|
||||
*/
|
||||
static ASN1_DATA gen_negTokenTarg(const char *OIDs[], ASN1_DATA blob)
|
||||
{
|
||||
int i;
|
||||
ASN1_DATA data;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
asn1_push_tag(&data, ASN1_APPLICATION(0));
|
||||
asn1_write_OID(&data,OID_SPNEGO);
|
||||
asn1_push_tag(&data, ASN1_CONTEXT(0));
|
||||
asn1_push_tag(&data, ASN1_SEQUENCE(0));
|
||||
|
||||
asn1_push_tag(&data, ASN1_CONTEXT(0));
|
||||
asn1_push_tag(&data, ASN1_SEQUENCE(0));
|
||||
for (i=0; OIDs[i]; i++) {
|
||||
asn1_write_OID(&data,OIDs[i]);
|
||||
}
|
||||
asn1_pop_tag(&data);
|
||||
asn1_pop_tag(&data);
|
||||
|
||||
asn1_push_tag(&data, ASN1_CONTEXT(2));
|
||||
asn1_write_OctetString(&data,blob.data,blob.length);
|
||||
asn1_pop_tag(&data);
|
||||
|
||||
asn1_pop_tag(&data);
|
||||
asn1_pop_tag(&data);
|
||||
|
||||
asn1_pop_tag(&data);
|
||||
|
||||
asn1_check_empty(&data);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
generate a krb5 GSS-API wrapper packet given a ticket
|
||||
*/
|
||||
static ASN1_DATA spnego_gen_krb5_wrap(DATA_BLOB ticket)
|
||||
{
|
||||
ASN1_DATA data;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
|
||||
asn1_push_tag(&data, ASN1_APPLICATION(0));
|
||||
asn1_write_OID(&data, OID_KERBEROS5);
|
||||
asn1_write_BOOLEAN(&data, 0);
|
||||
asn1_write(&data, ticket.data, ticket.length);
|
||||
asn1_pop_tag(&data);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
|
||||
kerberos session setup
|
||||
*/
|
||||
DATA_BLOB spnego_gen_negTokenTarg(struct cli_state *cli)
|
||||
{
|
||||
char *p;
|
||||
fstring service;
|
||||
DATA_BLOB tkt, ret;
|
||||
ASN1_DATA tkt_wrapped, targ;
|
||||
const char *krb_mechs[] =
|
||||
{"1 2 840 48018 1 2 2", "1 3 6 1 4 1 311 2 2 10", NULL};
|
||||
|
||||
/* the service name is the WINS name of the server in lowercase with
|
||||
a $ on the end */
|
||||
fstrcpy(service, cli->desthost);
|
||||
p = strchr_m(service, '.');
|
||||
if (p) *p = 0;
|
||||
fstrcat(service, "$");
|
||||
strlower(service);
|
||||
|
||||
/* get a kerberos ticket for the service */
|
||||
tkt = krb5_get_ticket(service);
|
||||
|
||||
/* wrap that up in a nice GSS-API wrapping */
|
||||
tkt_wrapped = spnego_gen_krb5_wrap(tkt);
|
||||
|
||||
/* and wrap that in a shiny SPNEGO wrapper */
|
||||
targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
|
||||
|
||||
ret = data_blob(targ.data, targ.length);
|
||||
|
||||
asn1_free(&tkt_wrapped);
|
||||
asn1_free(&targ);
|
||||
data_blob_free(tkt);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else /* HAVE_KRB5 */
|
||||
void clikrb5_dummy(void) {}
|
||||
#endif
|
@ -122,7 +122,7 @@ END {
|
||||
gotstart = 1;
|
||||
}
|
||||
|
||||
if( $0 ~ /^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element|^NT_DEVICEMODE|^enum.*\(|^NT_USER_TOKEN|^SAM_ACCOUNT/ ) {
|
||||
if( $0 ~ /^DATA_BLOB|^ASN1_DATA|^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element|^NT_DEVICEMODE|^enum.*\(|^NT_USER_TOKEN|^SAM_ACCOUNT/ ) {
|
||||
gotstart = 1;
|
||||
}
|
||||
|
||||
|
@ -128,8 +128,8 @@ static int reply_lanman2(char *outbuf)
|
||||
if (!cli) {
|
||||
generate_next_challenge(cryptkey);
|
||||
} else {
|
||||
memcpy(cryptkey, cli->cryptkey, 8);
|
||||
set_challenge(cli->cryptkey);
|
||||
memcpy(cryptkey, cli->secblob.data, 8);
|
||||
set_challenge(cryptkey);
|
||||
}
|
||||
}
|
||||
|
||||
@ -191,8 +191,8 @@ static int reply_nt1(char *outbuf)
|
||||
if (!cli) {
|
||||
generate_next_challenge(cryptkey);
|
||||
} else {
|
||||
memcpy(cryptkey, cli->cryptkey, 8);
|
||||
set_challenge(cli->cryptkey);
|
||||
memcpy(cryptkey, cli->secblob.data, 8);
|
||||
set_challenge(cryptkey);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user