summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apache1x/mod_httpauth.c15
-rw-r--r--apache2x/Makefile38
-rw-r--r--apache2x/Makefile.am31
-rw-r--r--apache2x/mod_httpauth.c28
-rw-r--r--apache2x/modules.mk4
-rw-r--r--common/buffer.c1
-rw-r--r--common/hash.c1
-rw-r--r--common/sock_any.c6
-rw-r--r--configure.in41
-rw-r--r--daemon/Makefile.am18
-rw-r--r--daemon/httpauthd.c27
-rw-r--r--daemon/httpauthd.h2
-rw-r--r--daemon/smbval/byteorder.h79
-rw-r--r--daemon/smbval/rfcnb-common.h37
-rw-r--r--daemon/smbval/rfcnb-error.h50
-rw-r--r--daemon/smbval/rfcnb-io.h30
-rw-r--r--daemon/smbval/rfcnb-io.inc.c292
-rw-r--r--daemon/smbval/rfcnb-priv.h120
-rw-r--r--daemon/smbval/rfcnb-util.h43
-rw-r--r--daemon/smbval/rfcnb-util.inc.c257
-rw-r--r--daemon/smbval/rfcnb.h49
-rw-r--r--daemon/smbval/session.inc.c221
-rw-r--r--daemon/smbval/smbdes.inc.c329
-rw-r--r--daemon/smbval/smbencrypt.inc.c76
-rw-r--r--daemon/smbval/smblib-common.h205
-rw-r--r--daemon/smbval/smblib-priv.h672
-rw-r--r--daemon/smbval/smblib-util.inc.c248
-rw-r--r--daemon/smbval/smblib.inc.c380
-rw-r--r--daemon/smbval/std-defines.h52
-rw-r--r--daemon/smbval/std-includes.h54
-rw-r--r--doc/httpauthd.conf.544
-rw-r--r--tools/mkha1.c1
32 files changed, 3379 insertions, 72 deletions
diff --git a/apache1x/mod_httpauth.c b/apache1x/mod_httpauth.c
index 2aa34b8..b399c5d 100644
--- a/apache1x/mod_httpauth.c
+++ b/apache1x/mod_httpauth.c
@@ -66,9 +66,11 @@ httpauth_context_t;
#define AUTH_PREFIX_BASIC "Basic"
#define AUTH_PREFIX_DIGEST "Digest"
+#define AUTH_PREFIX_NTLM "NTLM"
#define AUTH_TYPE_BASIC 1 << 1
#define AUTH_TYPE_DIGEST 1 << 2
+#define AUTH_TYPE_NTLM 1 << 3
#define AUTH_TYPE_ANY 0x0000FFFF
#define HTTPAUTH_AUTHTYPE "HTTPAUTH"
@@ -117,6 +119,8 @@ static const char* set_types(cmd_parms* cmd, void* config, const char* val)
type = AUTH_TYPE_BASIC;
else if(strcasecmp(val, AUTH_PREFIX_DIGEST) == 0)
type = AUTH_TYPE_DIGEST;
+ else if(strcasecmp(val, AUTH_PREFIX_NTLM) == 0)
+ type = AUTH_TYPE_NTLM;
else if(strcasecmp(val, "any"))
type = AUTH_TYPE_ANY;
else
@@ -144,7 +148,7 @@ static const command_rec httpauth_cmds[] =
{ "HttpAuthHandler", set_handler, NULL, OR_AUTHCFG, TAKE1,
"The handler that httpauthd should use to authenticate" },
{ "HttpAuthTypes", set_types, NULL, OR_AUTHCFG, ITERATE,
- "The types of authentiction allowed (Basic, Digest, ...)" },
+ "The types of authentiction allowed (Basic, Digest, NTLM ...)" },
{ "HttpAuthDigestDomain", set_domain, NULL, OR_AUTHCFG, RAW_ARGS,
"The domain for which digest authentication is relevant" },
{ NULL, NULL, NULL, 0, 0, NULL }
@@ -412,6 +416,10 @@ int read_copy_headers(httpauth_context_t* ctx, int ccode, request_rec* r)
!(ctx->types & AUTH_TYPE_DIGEST))
continue;
+ else if(strncasecmp(line, AUTH_PREFIX_NTLM, strlen(AUTH_PREFIX_NTLM)) == 0 &&
+ !(ctx->types & AUTH_TYPE_NTLM))
+ continue;
+
/* Only allow unknown if we don't have it */
else if(!(ctx->types & AUTH_TYPE_ANY))
continue;
@@ -608,6 +616,11 @@ int write_request(httpauth_context_t* ctx, request_rec* r)
const array_header* hdrs_arr;
const table_entry* elts;
+ /*
+ * TODO: We need to use a valid connection id for
+ * NTLM connections to work properly.
+ */
+
/* Send the request header to httpauthd */
t = ap_pstrcat(r->pool, "AUTH XXX ", r->method,
" ", r->unparsed_uri, "\n", NULL);
diff --git a/apache2x/Makefile b/apache2x/Makefile
deleted file mode 100644
index 65dc435..0000000
--- a/apache2x/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-##
-## Makefile -- Build procedure for sample httpauth Apache module
-## Autogenerated via ``apxs -n httpauth -g''.
-##
-
-builddir=.
-top_srcdir=/etc/httpd
-top_builddir=/etc/httpd
-include /usr/lib/httpd/build/special.mk
-
-# the used tools
-APXS=apxs
-APACHECTL=apachectl
-
-# additional defines, includes and libraries
-#DEFS=-Dmy_define=my_value
-INCLUDES=-I../ -I../common/
-#LIBS=-Lmy/lib/dir -lmylib
-
-all: local-shared-build
-
-install: install-modules
-
-clean:
- -rm -f mod_httpauth.o mod_httpauth.lo mod_httpauth.slo mod_httpauth.la
-
-# install and activate shared object by reloading Apache to
-# force a reload of the shared object file
-reload: install restart
-
-# the general Apache start/restart/stop procedures
-start:
- $(APACHECTL) start
-restart:
- $(APACHECTL) restart
-stop:
- $(APACHECTL) stop
-
diff --git a/apache2x/Makefile.am b/apache2x/Makefile.am
new file mode 100644
index 0000000..4b959cb
--- /dev/null
+++ b/apache2x/Makefile.am
@@ -0,0 +1,31 @@
+
+DEF=
+INC=-I../ -I../common/
+
+all: mod_httpauth.so
+
+
+mod_httpauth.so: mod_httpauth.c ../common/sock_any.c
+ $(APXS) -c -Wc,-g -Wc,-O0 $(DEF) $(INC) $(LIB) mod_httpauth.c
+ $(SH_LINK) -rpath $(libexecdir) -module -avoid-version mod_httpauth.lo
+
+# install the DSO file into the Apache installation
+# and activate it in the Apache configuration
+install: all
+ $(APXS) -i -a -c -Wc,-g -Wc,-O0 $(DEF) $(INC) $(LIB) mod_httpauth.c
+
+# cleanup
+clean:
+ -rm -f mod_httpauth.o mod_httpauth.so
+
+# reload the module by installing and restarting Apache
+reload: install restart
+
+# the general Apache start/restart/stop procedures
+start:
+ $(APACHECTL) start
+restart:
+ $(APACHECTL) restart
+stop:
+ $(APACHECTL) stop
+
diff --git a/apache2x/mod_httpauth.c b/apache2x/mod_httpauth.c
index b225e5b..ff4494e 100644
--- a/apache2x/mod_httpauth.c
+++ b/apache2x/mod_httpauth.c
@@ -45,6 +45,8 @@
#include <apr_strings.h>
#include <apr_lib.h>
+#include <unistd.h>
+
#include "sock_any.h"
#include "stringx.h"
@@ -67,9 +69,11 @@ httpauth_context_t;
#define AUTH_PREFIX_BASIC "Basic"
#define AUTH_PREFIX_DIGEST "Digest"
+#define AUTH_PREFIX_NTLM "NTLM"
#define AUTH_TYPE_BASIC 1 << 1
#define AUTH_TYPE_DIGEST 1 << 2
+#define AUTH_TYPE_NTLM 1 << 3
#define AUTH_TYPE_ANY 0x0000FFFF
#define HTTPAUTH_AUTHTYPE "HTTPAUTH"
@@ -118,6 +122,8 @@ static const char* set_types(cmd_parms* cmd, void* config, const char* val)
type = AUTH_TYPE_BASIC;
else if(strcasecmp(val, AUTH_PREFIX_DIGEST) == 0)
type = AUTH_TYPE_DIGEST;
+ else if(strcasecmp(val, AUTH_PREFIX_NTLM) == 0)
+ type = AUTH_TYPE_NTLM;
else if(strcasecmp(val, "any"))
type = AUTH_TYPE_ANY;
else
@@ -145,7 +151,7 @@ static const command_rec httpauth_cmds[] =
AP_INIT_TAKE1( "HttpAuthHandler", set_handler, NULL, OR_AUTHCFG,
"The handler that httpauthd should use to authenticate" ),
AP_INIT_ITERATE( "HttpAuthTypes", set_types, NULL, OR_AUTHCFG,
- "The types of authentiction allowed (Basic, Digest, ...)" ),
+ "The types of authentiction allowed (Basic, Digest, NTLM ...)" ),
AP_INIT_RAW_ARGS( "HttpAuthDigestDomain", set_domain, NULL, OR_AUTHCFG,
"The domain for which digest authentication is relevant" ),
{ NULL }
@@ -484,7 +490,6 @@ int write_data(httpauth_context_t* ctx, server_rec* s, const char* data)
int connect_socket(httpauth_context_t* ctx, request_rec* r)
{
struct sockaddr_any sany;
- apr_status_t st;
int ret = -1;
disconnect_socket(ctx, r->server);
@@ -611,13 +616,22 @@ finally:
int write_request(httpauth_context_t* ctx, request_rec* r)
{
+ char pidid[40];
+ char connid[40];
int i, c = 0;
const char* t;
const apr_array_header_t* hdrs_arr;
const apr_table_entry_t* elts;
+ /* A unique per connection id */
+ snprintf(connid, sizeof(connid), "0x%X", (unsigned int)r->connection);
+ connid[sizeof(connid) - 1] = 0;
+ snprintf(pidid, sizeof(pidid), "%d", (unsigned int)getpid());
+ pidid[sizeof(pidid) - 1] = 0;
+ t = apr_pstrcat(r->pool, pidid, ":", connid, NULL);
+
/* Send the request header to httpauthd */
- t = apr_pstrcat(r->pool, "AUTH XXX ", r->method,
+ t = apr_pstrcat(r->pool, "AUTH ", t, " ", r->method,
" ", r->unparsed_uri, "\n", NULL);
if(write_data(ctx, r->server, t) == -1)
@@ -650,6 +664,10 @@ int write_request(httpauth_context_t* ctx, request_rec* r)
!(ctx->types & AUTH_TYPE_DIGEST))
continue;
+ else if(strncasecmp(t, AUTH_PREFIX_NTLM, strlen(AUTH_PREFIX_NTLM)) == 0 &&
+ !(ctx->types & AUTH_TYPE_NTLM))
+ continue;
+
/* Only allow unknown if we don't have it */
else if(!(ctx->types & AUTH_TYPE_ANY))
continue;
@@ -774,7 +792,7 @@ static int httpauth_access(request_rec *r)
static void register_hooks(apr_pool_t *p)
{
- static const char* cfg_post[] = { "http_core.c", NULL };
+ /* static const char* cfg_post[] = { "http_core.c", NULL }; */
ap_hook_check_user_id(httpauth_authenticate, NULL, NULL, APR_HOOK_MIDDLE);
ap_hook_auth_checker(httpauth_access, NULL, NULL, APR_HOOK_MIDDLE);
@@ -783,7 +801,7 @@ static void register_hooks(apr_pool_t *p)
module AP_MODULE_DECLARE_DATA httpauth_module =
{
STANDARD20_MODULE_STUFF,
- httpauth_dir_config, /* dir config creater */
+ httpauth_dir_config, /* dir config creater */
NULL, /* dir merger --- default is to override */
NULL, /* server config */
NULL, /* merge server config */
diff --git a/apache2x/modules.mk b/apache2x/modules.mk
deleted file mode 100644
index c3c9110..0000000
--- a/apache2x/modules.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-mod_httpauth.la: mod_httpauth.slo
- $(SH_LINK) -rpath $(libexecdir) -module -avoid-version mod_httpauth.lo
-DISTCLEAN_TARGETS = modules.mk
-shared = mod_httpauth.la
diff --git a/common/buffer.c b/common/buffer.c
index 3d427e5..1ca4c6b 100644
--- a/common/buffer.c
+++ b/common/buffer.c
@@ -43,6 +43,7 @@
#include <errno.h>
#include <syslog.h>
#include <string.h>
+#include <stdlib.h>
#include <stdio.h>
/* -----------------------------------------------------------------------
diff --git a/common/hash.c b/common/hash.c
index e36883f..13a9371 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -53,6 +53,7 @@
#include <sys/types.h>
#include <stdlib.h>
+#include <string.h>
#include "hash.h"
#ifdef HSH_TIMESTAMP
diff --git a/common/sock_any.c b/common/sock_any.c
index 0018318..7876e20 100644
--- a/common/sock_any.c
+++ b/common/sock_any.c
@@ -36,12 +36,14 @@
*
*/
-#include <stdlib.h>
-#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
+
+#include <stdlib.h>
+#include <errno.h>
#include <netdb.h>
#include <string.h>
+#include <stdio.h>
#include "sock_any.h"
diff --git a/configure.in b/configure.in
index 433cc4a..e882a7c 100644
--- a/configure.in
+++ b/configure.in
@@ -36,8 +36,8 @@ dnl Nate Nielsen <nielsen@memberwebs.com>
dnl
dnl Process this file with autoconf to produce a configure script.
-AC_INIT(httpauth, 0.4.93, nielsen@memberwebs.com)
-AM_INIT_AUTOMAKE(httpauth, 0.4.93)
+AC_INIT(httpauth, 0.4.94, nielsen@memberwebs.com)
+AM_INIT_AUTOMAKE(httpauth, 0.4.94)
LDFLAGS="$LDFLAGS -L/usr/local/lib"
CFLAGS="$CFLAGS -I/usr/local/include -g -O0"
@@ -66,6 +66,7 @@ fi
AC_ARG_WITH(ldap, [ --with-ldap with LDAP support])
AC_ARG_WITH(pgsql, [ --with-pgsql with Postgres support])
AC_ARG_WITH(ldap, [ --with-mysql with MYSQL support])
+AC_ARG_ENABLE(ntlm, [ --enable-ntlm enable NTLM support])
# TODO: Figure out why we need this wierd hack
ACX_PTHREAD( , [echo "ERROR: Pthread support not found."; exit 1] )
@@ -101,7 +102,7 @@ AC_CHECK_FUNCS([strlwr])
AM_CONDITIONAL(WITH_LDAP, test -n "$with_ldap")
if test -n "$with_ldap"; then
- echo "enabling LDAP support"
+ echo "enabling LDAP support"
if test "$with_ldap" != "yes"; then
LDFLAGS="$LDFLAGS -L$with_ldap/lib"
@@ -162,12 +163,42 @@ if test -n "$with_mysql"; then
AC_DEFINE_UNQUOTED(WITH_MYSQL, 1, [With MYSQL Support] )
fi
+# NTLM Support
+AM_CONDITIONAL(WITH_NTLM, test -n "$enable_ntlm")
+if test -n "$enable_ntlm"; then
+ echo "enabling NTLM support"
+ AC_DEFINE_UNQUOTED(WITH_NTLM, 1, [With NTLM Support] )
+fi
+
# Have to resolve this for the path below
if test "${prefix}" = "NONE"; then
- prefix=$ac_default_prefix
+ prefix=$ac_default_prefix
+fi
+
+# APACHE Build stuff
+
+AC_PATH_PROG(APXS, apxs, "failed")
+if test "$APXS" = "failed"; then
+ AC_PATH_PROG(APXS2, apxs2, "apxs")
+ APXS=$APXS2
fi
+AC_SUBST(APXS)
+
+AC_PATH_PROG(APACHECTL, apachectl, "failed")
+if test "$APACHECTL" = "failed"; then
+ AC_PATH_PROG(APACHE2CTL, apache2ctl, "apachectl")
+ APACHECTL=$APACHE2CTL
+fi
+
+AC_SUBST(APACHECTL)
+
+
AC_DEFINE_UNQUOTED(CONF_PREFIX, "`eval echo ${sysconfdir}`", [Installation Prefix] )
-AC_CONFIG_FILES([Makefile daemon/Makefile doc/Makefile tools/Makefile])
+AC_CONFIG_FILES([Makefile
+ daemon/Makefile
+ doc/Makefile
+ tools/Makefile
+ apache2x/Makefile])
AC_OUTPUT
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 0e871fa..7c18b49 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -7,12 +7,18 @@ PGSQL_SOURCES = pgsql.c
MYSQL_SOURCES = mysql.c
+NTLM_SOURCES = ntlm.c ntlmssp.h ntlmssp.c
+
EXTRA_SRC =
if WITH_LDAP
EXTRA_SRC += $(LDAP_SOURCES)
endif
+if WITH_NTLM
+EXTRA_SRC += $(NTLM_SOURCES)
+endif
+
if WITH_PGSQL
EXTRA_SRC += $(PGSQL_SOURCES)
endif
@@ -22,14 +28,14 @@ EXTRA_SRC += $(MYSQL_SOURCES)
endif
httpauthd_SOURCES = httpauthd.c httpauthd.h usuals.h bd.h bd.c misc.c basic.h basic.c \
- digest.h digest.c defaults.h simple.c dummy.c \
+ digest.h digest.c defaults.h simple.c dummy.c \
../common/compat.h ../common/compat.c ../common/buffer.h ../common/buffer.c \
- ../common/hash.h ../common/hash.c ../common/md5.h ../common/md5.c \
- ../common/sha1.h ../common/sha1.c ../common/sock_any.c ../common/sock_any.h \
- ../common/stringx.c ../common/stringx.h $(EXTRA_SRC)
+ ../common/hash.h ../common/hash.c ../common/md5.h ../common/md5.c \
+ ../common/sha1.h ../common/sha1.c ../common/sock_any.c ../common/sock_any.h \
+ ../common/stringx.c ../common/stringx.h $(EXTRA_SRC)
httpauthd_CFLAGS = -D_THREAD_SAFE -pthread -DLinux \
- -I${top_srcdir}/common/ -I${top_srcdir}
+ -I${top_srcdir}/common/ -I${top_srcdir}
httpauthd_LDFLAGS = -pthread
-EXTRA_DIST = $(LDAP_SOURCES) $(PGSQL_SOURCES) $(MYSQL_SOURCES)
+EXTRA_DIST = $(LDAP_SOURCES) $(NTLM_SOURCES) $(PGSQL_SOURCES) $(MYSQL_SOURCES)
diff --git a/daemon/httpauthd.c b/daemon/httpauthd.c
index b26eb60..d4d70ea 100644
--- a/daemon/httpauthd.c
+++ b/daemon/httpauthd.c
@@ -69,6 +69,7 @@
extern ha_handler_t simple_handler;
extern ha_handler_t dummy_handler;
extern ha_handler_t ldap_handler;
+extern ha_handler_t ntlm_handler;
extern ha_handler_t pgsql_handler;
extern ha_handler_t mysql_handler;
@@ -78,6 +79,9 @@ ha_handler_t* g_handlerlist[] =
#if WITH_LDAP
&ldap_handler,
#endif
+#if WITH_NTLM
+ &ntlm_handler,
+#endif
#if WITH_PGSQL
&pgsql_handler,
#endif
@@ -85,7 +89,7 @@ ha_handler_t* g_handlerlist[] =
&mysql_handler,
#endif
&simple_handler,
- &dummy_handler
+ &dummy_handler
};
typedef struct httpauth_loaded
@@ -356,7 +360,7 @@ int main(int argc, char* argv[])
siginterrupt(SIGTERM, 1);
/* Open the system log */
- openlog("httpauthd", 0, LOG_AUTHPRIV);
+ openlog("httpauthd", 0, LOG_DAEMON);
ha_messagex(NULL, LOG_DEBUG, "accepting connections");
@@ -1091,7 +1095,7 @@ static int httpauth_processor(int ifd, int ofd)
ha_buffer_t buf;
ha_request_t rq;
int result = -1;
- int r;
+ int r = 0;
ASSERT(ifd != -1);
ASSERT(ofd != -1);
@@ -1457,28 +1461,33 @@ static int config_parse(const char* file, ha_buffer_t* buf)
{
int types = 0;
char* t;
+ char* v;
strlwr(value);
+ v = value;
/* Split the line into tokens at the spaces */
- while(*value)
+ while(*v)
{
- value = trim_space(value);
- t = value;
+ v = trim_space(v);
+ t = v;
while(*t && !isspace(*t))
t++;
- if(strncmp(value, "basic", 5) == 0)
+ if(strncmp(v, "basic", 5) == 0)
types |= HA_TYPE_BASIC;
- else if(strncmp(value, "digest", 6) == 0)
+ else if(strncmp(v, "digest", 6) == 0)
types |= HA_TYPE_DIGEST;
+ else if(strncmp(v, "ntlm", 4) == 0)
+ types |= HA_TYPE_NTLM;
+
else
errx(1, "invalid type for '%s': %s (line %d)", name, value, line);
- value = t;
+ v = t;
}
if(types == 0)
diff --git a/daemon/httpauthd.h b/daemon/httpauthd.h
index 18869f8..a4e9f19 100644
--- a/daemon/httpauthd.h
+++ b/daemon/httpauthd.h
@@ -253,6 +253,8 @@ void ha_memerr(const ha_request_t* rq);
#define HA_TYPE_DIGEST 1 << 2
#define HA_PREFIX_DIGEST "Digest "
+#define HA_TYPE_NTLM 1 << 3
+#define HA_PREFIX_NTLM "NTLM "
/* -----------------------------------------------------------------------
* URI Parse Support
diff --git a/daemon/smbval/byteorder.h b/daemon/smbval/byteorder.h
new file mode 100644
index 0000000..2ccb051
--- /dev/null
+++ b/daemon/smbval/byteorder.h
@@ -0,0 +1,79 @@
+/* mod_ntlm file: $Id: byteorder.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef BYTEORDER_H
+#define BYTEORDER_H
+
+/*
+ * Unix SMB/Netbios implementation. Version 1.9. SMB Byte handling
+ * Copyright (C) Andrew Tridgell 1992-1995 This program is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License as published by the Free Software Foundation;
+ * either version 2 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details. You should have received a copy of the
+ * GNU General Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This file implements macros for machine independent short and int
+ * manipulation */
+
+#undef CAREFUL_ALIGNMENT
+
+#include <stdint.h>
+#define uint16 uint16_t
+
+/* we know that the 386 can handle misalignment and has the "right"
+ * byteorder */
+#ifdef __i386__
+#define CAREFUL_ALIGNMENT 0
+#endif
+
+#ifndef CAREFUL_ALIGNMENT
+#define CAREFUL_ALIGNMENT 1
+#endif
+
+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
+#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
+#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
+
+#if CAREFUL_ALIGNMENT
+#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
+#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
+#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
+#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
+#define SVALS(buf,pos) ((int16)SVAL(buf,pos))
+#define IVALS(buf,pos) ((int32)IVAL(buf,pos))
+#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val)))
+#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
+#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val)))
+#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val)))
+#else
+/* this handles things for architectures like the 386 that can handle
+ * alignment errors */
+/*
+ * WARNING: This section is dependent on the length of int16 and int32
+ * being correct */
+#define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos)))
+#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
+#define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos)))
+#define IVALS(buf,pos) (*(int32 *)((char *)(buf) + (pos)))
+#define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16)(val))
+#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
+#define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val))
+#define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val))
+#endif
+
+/* now the reverse routines - these are used in nmb packets (mostly) */
+#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
+#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
+
+#define RSVAL(buf,pos) SREV(SVAL(buf,pos))
+#define RIVAL(buf,pos) IREV(IVAL(buf,pos))
+#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
+#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
+
+#endif
+
diff --git a/daemon/smbval/rfcnb-common.h b/daemon/smbval/rfcnb-common.h
new file mode 100644
index 0000000..9ac45b9
--- /dev/null
+++ b/daemon/smbval/rfcnb-common.h
@@ -0,0 +1,37 @@
+/* mod_ntlm file: $Id: rfcnb-common.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef RFCNB_COMMON_H
+#define RFCNB_COMMON_H
+
+/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
+ *
+ * Version 1.0 RFCNB Common Structures etc Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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. */
+
+/* A data structure we need */
+
+typedef struct RFCNB_Pkt {
+
+ char *data; /* The data in this portion */
+ int len;
+ struct RFCNB_Pkt *next;
+
+} RFCNB_Pkt;
+
+#endif
+
diff --git a/daemon/smbval/rfcnb-error.h b/daemon/smbval/rfcnb-error.h
new file mode 100644
index 0000000..7e5d639
--- /dev/null
+++ b/daemon/smbval/rfcnb-error.h
@@ -0,0 +1,50 @@
+/* mod_ntlm file: $Id: rfcnb-error.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef RFCNB_ERROR_H
+#define RFCNB_ERROR_H
+
+/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
+ *
+ * Version 1.0 RFCNB Error Response Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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. */
+
+/* Error responses */
+
+#define RFCNBE_Bad -1 /* Bad response */
+#define RFCNBE_OK 0
+
+/* these should follow the spec ... is there one ? */
+
+#define RFCNBE_NoSpace 1 /* Could not allocate space for a struct */
+#define RFCNBE_BadName 2 /* Could not translate a name */
+#define RFCNBE_BadRead 3 /* Read sys call failed */
+#define RFCNBE_BadWrite 4 /* Write Sys call failed */
+#define RFCNBE_ProtErr 5 /* Protocol Error */
+#define RFCNBE_ConGone 6 /* Connection dropped */
+#define RFCNBE_BadHandle 7 /* Handle passed was bad */
+#define RFCNBE_BadSocket 8 /* Problems creating socket */
+#define RFCNBE_ConnectFailed 9 /* Connect failed */
+#define RFCNBE_CallRejNLOCN 10 /* Call rejected, not listening on CN */
+#define RFCNBE_CallRejNLFCN 11 /* Call rejected, not listening for CN */
+#define RFCNBE_CallRejCNNP 12 /* Call rejected, called name not present */
+#define RFCNBE_CallRejInfRes 13 /* Call rejetced, name ok, no resources */
+#define RFCNBE_CallRejUnSpec 14 /* Call rejected, unspecified error */
+#define RFCNBE_BadParam 15 /* Bad parameters passed ... */
+#define RFCNBE_Timeout 16 /* IO Timed out */
+
+#endif
diff --git a/daemon/smbval/rfcnb-io.h b/daemon/smbval/rfcnb-io.h
new file mode 100644
index 0000000..ade524b
--- /dev/null
+++ b/daemon/smbval/rfcnb-io.h
@@ -0,0 +1,30 @@
+/* mod_ntlm file: $Id: rfcnb-io.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef RFCNB_IO_H
+#define RFCNB_IO_H
+
+/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
+ *
+ * Version 1.0 RFCNB IO Routines Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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. */
+
+static int RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len);
+
+static int RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len);
+
+#endif
diff --git a/daemon/smbval/rfcnb-io.inc.c b/daemon/smbval/rfcnb-io.inc.c
new file mode 100644
index 0000000..61b5e2c
--- /dev/null
+++ b/daemon/smbval/rfcnb-io.inc.c
@@ -0,0 +1,292 @@
+/* mod_ntlm file: $Id: rfcnb-io.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
+
+
+/* UNIX RFCNB (RFC1001/RFC1002) NEtBIOS implementation
+ *
+ * Version 1.0 RFCNB IO Routines ...
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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 "std-includes.h"
+#include "rfcnb-priv.h"
+#include "rfcnb-util.h"
+#include "rfcnb-io.h"
+#include <sys/uio.h>
+#include <sys/signal.h>
+#include <string.h>
+
+static int RFCNB_Timeout = 0; /* Timeout in seconds ... */
+
+/* Discard the rest of an incoming packet as we do not have space for
+ * it in the buffer we allocated or were passed ... */
+static int
+RFCNB_Discard_Rest(struct RFCNB_Con *con, int len)
+{
+ char temp[100]; /* Read into here */
+ int rest, this_read, bytes_read;
+
+ /* len is the amount we should read */
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Discard_Rest called to discard: %i\n", len);
+#endif
+
+ rest = len;
+ while (rest > 0) {
+ this_read = (rest > sizeof(temp) ? sizeof(temp) : rest);
+ bytes_read = read(con->fd, temp, this_read);
+ if (bytes_read <= 0) { /* Error so return */
+ if (bytes_read < 0)
+ RFCNB_errno = RFCNBE_BadRead;
+ else
+ RFCNB_errno = RFCNBE_ConGone;
+
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ }
+ rest = rest - bytes_read;
+ }
+ return 0;
+}
+
+/* Send an RFCNB packet to the connection. We just send each of the
+ * blocks linked together ... If we can, try to send it as one iovec
+ * ... */
+static int
+RFCNB_Put_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
+{
+ int len_sent, tot_sent, this_len;
+ struct RFCNB_Pkt *pkt_ptr;
+ char *this_data;
+ int i;
+ struct iovec io_list[10]; /* We should never have more */
+ /* If we do, this will blow up ... */
+
+ /* Try to send the data ... We only send as many bytes as len
+ * claims */
+ /* We should try to stuff it into an IOVEC and send as one write */
+
+ pkt_ptr = pkt;
+ len_sent = tot_sent = 0; /* Nothing sent so far */
+ i = 0;
+
+ while ((pkt_ptr != NULL) & (i < 10)) { /* Watch that magic number! */
+ this_len = pkt_ptr->len;
+ this_data = pkt_ptr->data;
+ if ((tot_sent + this_len) > len)
+ this_len = len - tot_sent; /* Adjust so we don't send too
+ * much */
+
+ /* Now plug into the iovec ... */
+ io_list[i].iov_len = this_len;
+ io_list[i].iov_base = this_data;
+ i++;
+
+ tot_sent += this_len;
+
+ if (tot_sent == len)
+ break; /* Let's not send too much */
+
+ pkt_ptr = pkt_ptr->next;
+ }
+
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Frags = %i, tot_sent = %i\n", i, tot_sent);
+#endif
+
+ /* Set up an alarm if timeouts are set ... */
+
+ if (RFCNB_Timeout > 0)
+ alarm(RFCNB_Timeout);
+
+ if ((len_sent = writev(con->fd, io_list, i)) < 0) { /* An error */
+ con->rfc_errno = errno;
+ if (errno == EINTR) /* We were interrupted ... */
+ RFCNB_errno = RFCNBE_Timeout;
+ else
+ RFCNB_errno = RFCNBE_BadWrite;
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ }
+ if (len_sent < tot_sent) { /* Less than we wanted */
+ if (errno == EINTR) /* We were interrupted */
+ RFCNB_errno = RFCNBE_Timeout;
+ else
+ RFCNB_errno = RFCNBE_BadWrite;
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ }
+ if (RFCNB_Timeout > 0)
+ alarm(0); /* Reset that sucker */
+
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Len sent = %i ...\n", len_sent);
+ RFCNB_Print_Pkt(stderr, "sent", pkt, len_sent); /* Print what send... */
+#endif
+ return len_sent;
+}
+
+/* Read an RFCNB packet off the connection. We read the first 4
+ * bytes, that tells us the length, then read the rest. We should
+ * implement a timeout, but we don't just yet */
+static int
+RFCNB_Get_Pkt(struct RFCNB_Con *con, struct RFCNB_Pkt *pkt, int len)
+{
+ int read_len, pkt_len;
+ char hdr[RFCNB_Pkt_Hdr_Len]; /* Local space for the header */
+ struct RFCNB_Pkt *pkt_frag;
+ int more, this_time, offset, frag_len, this_len;
+ BOOL seen_keep_alive = TRUE;
+
+ /* Read that header straight into the buffer */
+ if (len < RFCNB_Pkt_Hdr_Len) { /* What a bozo */
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Trying to read less than a packet:");
+ perror("");
+#endif
+ RFCNB_errno = RFCNBE_BadParam;
+ return (RFCNBE_Bad);
+ }
+ /* We discard keep alives here ... */
+ if (RFCNB_Timeout > 0)
+ alarm(RFCNB_Timeout);
+
+ while (seen_keep_alive) {
+ if ((read_len = read(con->fd, hdr, sizeof(hdr))) < 0) { /* Problems */
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Reading the packet, we got:");
+ perror("");
+#endif
+ if (errno == EINTR)
+ RFCNB_errno = RFCNBE_Timeout;
+ else
+ RFCNB_errno = RFCNBE_BadRead;
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ }
+ /* Now we check out what we got */
+ if (read_len == 0) { /* Connection closed, send back eof? */
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Connection closed reading\n");
+#endif
+ if (errno == EINTR)
+ RFCNB_errno = RFCNBE_Timeout;
+ else
+ RFCNB_errno = RFCNBE_ConGone;
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ }
+ if (RFCNB_Pkt_Type(hdr) == RFCNB_SESSION_KEEP_ALIVE) {
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "RFCNB KEEP ALIVE received\n");
+#endif
+ } else {
+ seen_keep_alive = FALSE;
+ }
+ }
+
+ /* What if we got less than or equal to a hdr size in bytes? */
+ if (read_len < sizeof(hdr)) { /* We got a small packet */
+ /* Now we need to copy the hdr portion we got into the
+ * supplied packet */
+ memcpy(pkt->data, hdr, read_len); /* Copy data */
+#ifdef RFCNB_DEBUG
+ RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len);
+#endif
+ return read_len;
+ }
+ /* Now, if we got at least a hdr size, alloc space for rest, if we
+ * need it */
+ pkt_len = RFCNB_Pkt_Len(hdr);
+
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Reading Pkt: Length = %i\n", pkt_len);
+#endif
+
+ /* Now copy in the hdr */
+ memcpy(pkt->data, hdr, sizeof(hdr));
+
+ /* Get the rest of the packet ... first figure out how big our buf
+ * is? And make sure that we handle the fragments properly
+ * ... Sure should use an iovec ... */
+ if (len < pkt_len) /* Only get as much as we have space for */
+ more = len - RFCNB_Pkt_Hdr_Len;
+ else
+ more = pkt_len;
+
+ this_time = 0;
+
+ /* We read for each fragment ... */
+ if (pkt->len == read_len) { /* If this frag was exact size */
+ pkt_frag = pkt->next; /* Stick next lot in next frag */
+ offset = 0; /* then we start at 0 in next */
+ } else {
+ pkt_frag = pkt; /* Otherwise use rest of this frag */
+ offset = RFCNB_Pkt_Hdr_Len; /* Otherwise skip the header */
+ }
+
+ frag_len = pkt_frag->len;
+ if (more <= frag_len) /* If len left to get less than frag space */
+ this_len = more; /* Get the rest ... */
+ else
+ this_len = frag_len - offset;
+
+ while (more > 0) {
+ if ((this_time = read(con->fd, (pkt_frag->data) + offset,
+ this_len)) <= 0) { /* Problems */
+ if (errno == EINTR) {
+ RFCNB_errno = RFCNB_Timeout;
+ } else {
+ if (this_time < 0)
+ RFCNB_errno = RFCNBE_BadRead;
+ else
+ RFCNB_errno = RFCNBE_ConGone;
+ }
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+
+ }
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Frag_Len = %i, this_time = %i, this_len = %i, more = %i\n", frag_len,
+ this_time, this_len, more);
+#endif
+
+ read_len = read_len + this_time; /* How much have we read... */
+ /* Now set up the next part */
+ if (pkt_frag->next == NULL)
+ break; /* That's it here */
+
+ pkt_frag = pkt_frag->next;
+ this_len = pkt_frag->len;
+ offset = 0;
+
+ more = more - this_time;
+ }
+
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Pkt Len = %i, read_len = %i\n", pkt_len, read_len);
+ RFCNB_Print_Pkt(stderr, "rcvd", pkt, read_len + sizeof(hdr));
+#endif
+
+ if (read_len < (pkt_len + sizeof(hdr))) { /* Discard the rest */
+ return (RFCNB_Discard_Rest(con, (pkt_len + sizeof(hdr)) - read_len));
+ }
+ if (RFCNB_Timeout > 0)
+ alarm(0); /* Reset that sucker */
+
+ return (read_len + sizeof(RFCNB_Hdr));
+}
diff --git a/daemon/smbval/rfcnb-priv.h b/daemon/smbval/rfcnb-priv.h
new file mode 100644
index 0000000..e95fe02
--- /dev/null
+++ b/daemon/smbval/rfcnb-priv.h
@@ -0,0 +1,120 @@
+/* mod_ntlm file: $Id: rfcnb-priv.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef RFCNB_PRIV_H
+#define RFCNB_PRIV_H
+
+/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
+ *
+ * Version 1.0 RFCNB Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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. */
+
+/* Defines we need */
+
+#define GLOBAL extern
+
+#include "rfcnb-error.h"
+#include "rfcnb-common.h"
+#include "byteorder.h"
+
+#ifdef RFCNB_PORT
+#define RFCNB_Default_Port RFCNB_PORT
+#else
+#define RFCNB_Default_Port 139
+#endif
+
+#define RFCNB_MAX_STATS 1
+
+/* Protocol defines we need */
+
+#define RFCNB_SESSION_MESSAGE 0
+#define RFCNB_SESSION_REQUEST 0x81
+#define RFCNB_SESSION_ACK 0x82
+#define RFCNB_SESSION_REJ 0x83
+#define RFCNB_SESSION_RETARGET 0x84
+#define RFCNB_SESSION_KEEP_ALIVE 0x85
+
+/* Structures */
+
+typedef struct redirect_addr *redirect_ptr;
+
+struct redirect_addr {
+
+ struct in_addr ip_addr;
+ int port;
+ redirect_ptr next;
+
+};
+
+typedef struct RFCNB_Con {
+
+ int fd; /* File descripter for TCP/IP connection */
+ int rfc_errno; /* last error */
+ int timeout; /* How many milli-secs before IO times out
+ */
+ int redirects; /* How many times we were redirected */
+ struct redirect_addr *redirect_list; /* First is first address */
+ struct redirect_addr *last_addr;
+
+} RFCNB_Con;
+
+typedef char RFCNB_Hdr[4]; /* The header is 4 bytes long with */
+ /* char[0] as the type, char[1] the */
+ /* flags, and char[2..3] the length */
+
+/* Macros to extract things from the header. These are for portability
+ * between architecture types where we are worried about byte order */
+
+#define RFCNB_Pkt_Hdr_Len 4
+#define RFCNB_Pkt_Sess_Len 72
+#define RFCNB_Pkt_Retarg_Len 10
+#define RFCNB_Pkt_Nack_Len 5
+#define RFCNB_Pkt_Type_Offset 0
+#define RFCNB_Pkt_Flags_Offset 1
+#define RFCNB_Pkt_Len_Offset 2 /* Length is 2 bytes plus a flag
+ * bit */
+#define RFCNB_Pkt_N1Len_Offset 4
+#define RFCNB_Pkt_Called_Offset 5
+#define RFCNB_Pkt_N2Len_Offset 38
+#define RFCNB_Pkt_Calling_Offset 39
+#define RFCNB_Pkt_Error_Offset 4
+#define RFCNB_Pkt_IP_Offset 4
+#define RFCNB_Pkt_Port_Offset 8
+
+/* The next macro isolates the length of a packet, including the bit in
+ * the flags
+ * */
+
+#define RFCNB_Pkt_Len(p) (PVAL((p), 3) | (PVAL((p), 2) << 8) | \
+ ((PVAL((p), RFCNB_Pkt_Flags_Offset) & 0x01) << 16))
+
+#define RFCNB_Put_Pkt_Len(p, v) ((p)[1] = (((v) >> 16) & 1)); \
+ ((p)[2] = (((v) >> 8) & 0xFF)); \
+ ((p)[3] = ((v) & 0xFF));
+
+#define RFCNB_Pkt_Type(p) (CVAL((p), RFCNB_Pkt_Type_Offset))
+
+/* Static variables */
+
+/* Only declare this if not defined */
+
+#ifndef RFCNB_ERRNO
+static int RFCNB_errno;
+static int RFCNB_saved_errno; /* Save this from point of error */
+#endif
+
+#endif
diff --git a/daemon/smbval/rfcnb-util.h b/daemon/smbval/rfcnb-util.h
new file mode 100644
index 0000000..d5d2ef5
--- /dev/null
+++ b/daemon/smbval/rfcnb-util.h
@@ -0,0 +1,43 @@
+/* mod_ntlm file: $Id: rfcnb-util.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef RFCNB_UTIL_H
+#define RFCNB_UTIL_H
+
+/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
+ *
+ * Version 1.0 RFCNB Utility Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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. */
+
+static void RFCNB_CvtPad_Name(char *name1, char *name2);
+
+static struct RFCNB_Pkt *RFCNB_Alloc_Pkt(int n);
+
+static int RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP);
+
+static int RFCNB_Close(int socket);
+
+static int RFCNB_IP_Connect(struct in_addr Dest_IP, int port);
+
+static int RFCNB_Session_Req(struct RFCNB_Con *con,
+ char *Called_Name,
+ char *Calling_Name,
+ BOOL * redirect,
+ struct in_addr *Dest_IP,
+ int *port);
+
+#endif
diff --git a/daemon/smbval/rfcnb-util.inc.c b/daemon/smbval/rfcnb-util.inc.c
new file mode 100644
index 0000000..31e7e05
--- /dev/null
+++ b/daemon/smbval/rfcnb-util.inc.c
@@ -0,0 +1,257 @@
+/* mod_ntlm file: $Id: rfcnb-util.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
+
+/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
+ *
+ * Version 1.0 RFCNB Utility Routines ...
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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 <string.h>
+#include <malloc.h>
+#include <stdint.h>
+
+#include "std-includes.h"
+#include "rfcnb-priv.h"
+#include "rfcnb-util.h"
+#include "rfcnb-io.h"
+
+/* Convert name and pad to 16 chars as needed. Name 1 is a C string
+ * with null termination, name 2 may not be. If SysName is true, then
+ * put a <00> on end, else space> */
+static void
+RFCNB_CvtPad_Name(char *name1, char *name2)
+{
+ char c, c1, c2;
+ int i, len;
+
+ len = strlen(name1);
+ for (i = 0; i < 16; i++) {
+ if (i >= len) {
+ c1 = 'C';
+ c2 = 'A'; /* CA is a space */
+ } else {
+ c = name1[i];
+ c1 = (char) ((int) c / 16 + (int) 'A');
+ c2 = (char) ((int) c % 16 + (int) 'A');
+ }
+ name2[i * 2] = c1;
+ name2[i * 2 + 1] = c2;
+ }
+ name2[32] = 0; /* Put in the nll ... */
+}
+
+/* Get a packet of size n */
+static struct RFCNB_Pkt *
+RFCNB_Alloc_Pkt(int n)
+{
+ RFCNB_Pkt *pkt;
+
+ if ((pkt = (struct RFCNB_Pkt *) malloc(
+ sizeof(struct RFCNB_Pkt))) == NULL) {
+ RFCNB_errno = RFCNBE_NoSpace;
+ RFCNB_saved_errno = errno;
+ return NULL;
+ }
+ pkt->next = NULL;
+ pkt->len = n;
+
+ if (n == 0)
+ return pkt;
+
+ if ((pkt->data = (char *) malloc(n)) == NULL) {
+ RFCNB_errno = RFCNBE_NoSpace;
+ RFCNB_saved_errno = errno;
+ free(pkt);
+ return (NULL);
+ }
+ return pkt;
+}
+
+/* Free up a packet */
+static void
+RFCNB_Free_Pkt(struct RFCNB_Pkt *pkt)
+{
+ struct RFCNB_Pkt *pkt_next;
+ char *data_ptr;
+
+ while (pkt != NULL) {
+ pkt_next = pkt->next;
+ data_ptr = pkt->data;
+ if (data_ptr != NULL)
+ free(data_ptr);
+ free(pkt);
+ pkt = pkt_next;
+ }
+}
+
+/* Resolve a name into an address */
+static int
+RFCNB_Name_To_IP(char *host, struct in_addr *Dest_IP)
+{
+ int addr; /* Assumes IP4, 32 bit network addresses */
+ struct hostent *hp;
+
+ /* Use inet_addr to try to convert the address */
+ if ((addr = inet_addr(host)) == INADDR_NONE) { /* a good try :-) */
+ /* Now try a name look up with gethostbyname */
+ if ((hp = gethostbyname(host)) == NULL) { /* Not in DNS */
+ /* Try NetBIOS name lookup, how the hell do we do that? */
+ RFCNB_errno = RFCNBE_BadName; /* Is this right? */
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ } else { /* We got a name */
+ memcpy((void *) Dest_IP, (void *) hp->h_addr_list[0],
+ sizeof(struct in_addr));
+ }
+ } else { /* It was an IP address */
+ memcpy((void *) Dest_IP, (void *) &addr, sizeof(struct in_addr));
+ }
+ return 0;
+}
+
+/* Disconnect the TCP connection to the server */
+static int
+RFCNB_Close(int socket)
+{
+ close(socket);
+ /* If we want to do error recovery, here is where we put it */
+ return 0;
+}
+
+/* Connect to the server specified in the IP address. Not sure how to
+ * handle socket options etc. */
+static int
+RFCNB_IP_Connect(struct in_addr Dest_IP, int port)
+{
+ struct sockaddr_in Socket;
+ int fd;
+
+ /* Create a socket */
+ if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { /* Handle the error */
+ RFCNB_errno = RFCNBE_BadSocket;
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ }
+ bzero((char *) &Socket, sizeof(Socket));
+ memcpy((char *) &Socket.sin_addr, (char *) &Dest_IP, sizeof(Dest_IP));
+
+ Socket.sin_port = htons(port);
+ Socket.sin_family = PF_INET;
+
+ /* Now connect to the destination */
+ if (connect(fd, (struct sockaddr *) &Socket, sizeof(Socket)) < 0) {
+ /* Error */
+ close(fd);
+ RFCNB_errno = RFCNBE_ConnectFailed;
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ }
+ return fd;
+}
+
+/* handle the details of establishing the RFCNB session with remote end */
+static int
+RFCNB_Session_Req(struct RFCNB_Con *con,
+ char *Called_Name,
+ char *Calling_Name,
+ BOOL * redirect,
+ struct in_addr *Dest_IP,
+ int *port)
+{
+ char *sess_pkt;
+
+ /* Response packet should be no more than 9 bytes, make 16 jic */
+ char resp[16];
+ int len;
+ struct RFCNB_Pkt *pkt, res_pkt;
+
+ /* We build and send the session request, then read the response */
+ pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Sess_Len);
+ if (pkt == NULL) {
+ return RFCNBE_Bad; /* Leave the error that RFCNB_Alloc_Pkt gives) */
+ }
+ sess_pkt = pkt->data; /* Get pointer to packet proper */
+
+ sess_pkt[RFCNB_Pkt_Type_Offset] = RFCNB_SESSION_REQUEST;
+ RFCNB_Put_Pkt_Len(sess_pkt, RFCNB_Pkt_Sess_Len - RFCNB_Pkt_Hdr_Len);
+ sess_pkt[RFCNB_Pkt_N1Len_Offset] = 32;
+ sess_pkt[RFCNB_Pkt_N2Len_Offset] = 32;
+
+ RFCNB_CvtPad_Name(Called_Name, (sess_pkt + RFCNB_Pkt_Called_Offset));
+ RFCNB_CvtPad_Name(Calling_Name, (sess_pkt + RFCNB_Pkt_Calling_Offset));
+
+ /* Now send the packet */
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Sending packet: ");
+#endif
+ if ((len = RFCNB_Put_Pkt(con, pkt, RFCNB_Pkt_Sess_Len)) < 0)
+ return RFCNBE_Bad; /* Should be able to write that lot ... */
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Getting packet.\n");
+#endif
+
+ res_pkt.data = resp;
+ res_pkt.len = sizeof(resp);
+ res_pkt.next = NULL;
+
+ if ((len = RFCNB_Get_Pkt(con, &res_pkt, sizeof(resp))) < 0)
+ return RFCNBE_Bad;
+
+ /* Now analyze the packet ... */
+ switch (RFCNB_Pkt_Type(resp)) {
+ case RFCNB_SESSION_REJ: /* Didnt like us ... too bad */
+ /* Why did we get rejected ? */
+ switch (CVAL(resp, RFCNB_Pkt_Error_Offset)) {
+ case 0x80:
+ RFCNB_errno = RFCNBE_CallRejNLOCN;
+ break;
+ case 0x81:
+ RFCNB_errno = RFCNBE_CallRejNLFCN;
+ break;
+ case 0x82:
+ RFCNB_errno = RFCNBE_CallRejCNNP;
+ break;
+ case 0x83:
+ RFCNB_errno = RFCNBE_CallRejInfRes;
+ break;
+ case 0x8F:
+ RFCNB_errno = RFCNBE_CallRejUnSpec;
+ break;
+ default:
+ RFCNB_errno = RFCNBE_ProtErr;
+ break;
+ }
+ return (RFCNBE_Bad);
+ break;
+
+ case RFCNB_SESSION_ACK: /* Got what we wanted ... */
+ return (0);
+ break;
+
+ case RFCNB_SESSION_RETARGET: /* Go elsewhere */
+ *redirect = TRUE; /* Copy port and ip addr */
+ memcpy(Dest_IP, (resp + RFCNB_Pkt_IP_Offset),
+ sizeof(struct in_addr));
+ *port = SVAL(resp, RFCNB_Pkt_Port_Offset);
+ return 0;
+ break;
+ default: /* A protocol error */
+ RFCNB_errno = RFCNBE_ProtErr;
+ return (RFCNBE_Bad);
+ break;
+ }
+}
diff --git a/daemon/smbval/rfcnb.h b/daemon/smbval/rfcnb.h
new file mode 100644
index 0000000..8e1be40
--- /dev/null
+++ b/daemon/smbval/rfcnb.h
@@ -0,0 +1,49 @@
+/* mod_ntlm file: $Id: rfcnb.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef RFCNB_H
+#define RFCNB_H
+
+/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
+ *
+ * Version 1.0 RFCNB Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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. */
+
+/* Error responses */
+
+#include "rfcnb-error.h"
+#include "rfcnb-common.h"
+
+/* Defines we need */
+
+#define RFCNB_Default_Port 139
+
+/* Definition of routines we define */
+
+static void *RFCNB_Call(char *Called_Name, char *Calling_Name,
+ char *Called_Address, int port);
+
+static int RFCNB_Send(struct RFCNB_Con *Con_Handle,
+ struct RFCNB_Pkt *Data, int Length);
+
+static int RFCNB_Recv(void *Con_Handle, struct RFCNB_Pkt *Data, int Length);
+
+static int RFCNB_Hangup(struct RFCNB_Con *con_Handle);
+
+static struct RFCNB_Pkt *RFCNB_Alloc_Pkt(int n);
+
+#endif
diff --git a/daemon/smbval/session.inc.c b/daemon/smbval/session.inc.c
new file mode 100644
index 0000000..1ed4732
--- /dev/null
+++ b/daemon/smbval/session.inc.c
@@ -0,0 +1,221 @@
+/* mod_ntlm file: $Id: session.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
+
+
+/* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
+ *
+ * Version 1.0 Session Routines ...
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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 <malloc.h>
+#include <string.h>
+
+static int RFCNB_errno = 0;
+static int RFCNB_saved_errno = 0;
+#define RFCNB_ERRNO
+
+#include "std-includes.h"
+#include <netinet/tcp.h>
+#include "rfcnb-priv.h"
+#include "rfcnb-util.h"
+
+/* Set up a session with a remote name. We are passed Called_Name as a
+ * string which we convert to a NetBIOS name, ie space terminated, up to
+ * 16 characters only if we need to. If Called_Address is not empty, then
+ * we use it to connect to the remote end, but put in Called_Name ...
+ * Called Address can be a DNS based name, or a TCP/IP address ... */
+static void *
+RFCNB_Call(char *Called_Name, char *Calling_Name, char *Called_Address,
+ int port)
+{
+ struct RFCNB_Con *con;
+ struct in_addr Dest_IP;
+ int Client;
+ BOOL redirect;
+ struct redirect_addr *redir_addr;
+ char *Service_Address;
+
+ /* Now, we really should look up the port in /etc/services ... */
+ if (port == 0)
+ port = RFCNB_Default_Port;
+
+ /* Create a connection structure first */
+ if ((con = (struct RFCNB_Con *) malloc(
+ sizeof(struct RFCNB_Con))) == NULL) {
+ /* Error in size */
+ RFCNB_errno = RFCNBE_NoSpace;
+ RFCNB_saved_errno = errno;
+ return NULL;
+ }
+ con->fd = -0; /* no descriptor yet */
+ con->rfc_errno = 0; /* no error yet */
+ con->timeout = 0; /* no timeout */
+ con->redirects = 0;
+ con->redirect_list = NULL; /* Fix bug still in version 0.50 */
+
+ /* Resolve that name into an IP address */
+ Service_Address = Called_Name;
+ if (strcmp(Called_Address, "") != 0)
+ Service_Address = Called_Address;
+ if ((errno = RFCNB_Name_To_IP(Service_Address, &Dest_IP)) < 0) {
+ /* Error */
+ /* No need to modify RFCNB_errno as it was done by
+ * RFCNB_Name_To_IP */
+ return NULL;
+ }
+ /* Now connect to the remote end */
+ redirect = TRUE; /* Fudge this one so we go once through */
+ while (redirect) { /* Connect and get session info etc */
+ redirect = FALSE; /* Assume all OK */
+ /* Build the redirect info. First one is first addr called */
+ /* And tack it onto the list of addresses we called */
+ if ((redir_addr = (struct redirect_addr *) malloc(
+ sizeof(struct redirect_addr))) == NULL) {
+ /* Could not get space */
+ RFCNB_errno = RFCNBE_NoSpace;
+ RFCNB_saved_errno = errno;
+ return (NULL);
+ }
+ memcpy((char *) &(redir_addr->ip_addr),
+ (char *) &Dest_IP, sizeof(Dest_IP));
+ redir_addr->port = port;
+ redir_addr->next = NULL;
+
+ if (con->redirect_list == NULL) { /* Stick on head */
+ con->redirect_list = con->last_addr = redir_addr;
+ } else {
+ con->last_addr->next = redir_addr;
+ con->last_addr = redir_addr;
+ }
+
+ /* Now, make that connection */
+ if ((Client = RFCNB_IP_Connect(Dest_IP, port)) < 0) { /* Error */
+ /* No need to modify RFCNB_errno as it was done by
+ * RFCNB_IP_Connect */
+ return NULL;
+ }
+ con->fd = Client;
+
+ /* Now send and handle the RFCNB session request */
+ /* If we get a redirect, we will comeback with redirect true and
+ * a new IP address in DEST_IP */
+ if ((errno = RFCNB_Session_Req(con,
+ Called_Name,
+ Calling_Name,
+ &redirect, &Dest_IP, &port)) < 0) {
+ /* No need to modify RFCNB_errno as it was done by
+ * RFCNB_Session.. */
+ return NULL;
+ }
+ if (redirect) {
+ /* We have to close the connection, and then try again */
+ (con->redirects)++;
+ RFCNB_Close(con->fd); /* Close it */
+ }
+ }
+ return con;
+}
+
+/* We send a packet to the other end ... for the moment, we treat the
+ * data as a series of pointers to blocks of data ... we should check the
+ * length ... */
+static int
+RFCNB_Send(struct RFCNB_Con *Con_Handle, struct RFCNB_Pkt *udata, int Length)
+{
+ struct RFCNB_Pkt *pkt;
+ char *hdr;
+ int len;
+
+ /* Plug in the header and send the data */
+ pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
+ if (pkt == NULL) {
+ RFCNB_errno = RFCNBE_NoSpace;
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ }
+ pkt->next = udata; /* The user data we want to send */
+ hdr = pkt->data;
+
+ /* Following crap is for portability across multiple UNIX machines */
+ *(hdr + RFCNB_Pkt_Type_Offset) = RFCNB_SESSION_MESSAGE;
+ RFCNB_Put_Pkt_Len(hdr, Length);
+
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Sending packet: ");
+#endif
+
+ if ((len = RFCNB_Put_Pkt(Con_Handle, pkt,
+ Length + RFCNB_Pkt_Hdr_Len)) < 0) {
+ /* No need to change RFCNB_errno as it was done by put_pkt ... */
+ return RFCNBE_Bad; /* Should be able to write that lot ... */
+ }
+ /* Now we have sent that lot, let's get rid of the RFCNB Header
+ * and return */
+ pkt->next = NULL;
+
+ RFCNB_Free_Pkt(pkt);
+ return len;
+}
+
+/* We pick up a message from the internet ... We have to worry about
+ * non-message packets ... */
+static int
+RFCNB_Recv(void *con_Handle, struct RFCNB_Pkt *Data, int Length)
+{
+ struct RFCNB_Pkt *pkt;
+ int ret_len;
+
+ if (con_Handle == NULL) {
+ RFCNB_errno = RFCNBE_BadHandle;
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ }
+ /* Now get a packet from below. We allocate a header first */
+ /* Plug in the header and send the data */
+ pkt = RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len);
+
+ if (pkt == NULL) {
+ RFCNB_errno = RFCNBE_NoSpace;
+ RFCNB_saved_errno = errno;
+ return (RFCNBE_Bad);
+ }
+ pkt->next = Data; /* Plug in the data portion */
+
+ if ((ret_len = RFCNB_Get_Pkt(con_Handle, pkt,
+ Length + RFCNB_Pkt_Hdr_Len)) < 0) {
+#ifdef RFCNB_DEBUG
+ fprintf(stderr, "Bad packet return in RFCNB_Recv... \n");
+#endif
+ return RFCNBE_Bad;
+ }
+ /* We should check that we go a message and not a keep alive */
+ pkt->next = NULL;
+ RFCNB_Free_Pkt(pkt);
+ return ret_len;
+}
+
+/* We just disconnect from the other end, as there is nothing in the
+ * RFCNB protocol that specifies any exchange as far as I can see*/
+static int
+RFCNB_Hangup(struct RFCNB_Con *con_Handle)
+{
+ if (con_Handle != NULL) {
+ RFCNB_Close(con_Handle->fd); /* Could this fail? */
+ free(con_Handle);
+ }
+ return 0;
+}
diff --git a/daemon/smbval/smbdes.inc.c b/daemon/smbval/smbdes.inc.c
new file mode 100644
index 0000000..8ca9878
--- /dev/null
+++ b/daemon/smbval/smbdes.inc.c
@@ -0,0 +1,329 @@
+/* mod_ntlm file: $Id: smbdes.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
+
+
+/*
+ * Unix SMB/Netbios implementation. Version 1.9.
+ *
+ * a partial implementation of DES designed for use in the SMB
+ * authentication protocol
+ *
+ * Copyright (C) Andrew Tridgell 1997 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. */
+
+/* NOTES:
+ *
+ * This code makes no attempt to be fast! In fact, it is a very slow
+ * implementation
+ *
+ * This code is NOT a complete DES implementation. It implements only the
+ * minimum necessary for SMB authentication, as used by all SMB products
+ * (including every copy of Microsoft Windows95 ever sold)
+ *
+ * In particular, it can only do a unchained forward DES pass. This means
+ * it is not possible to use this code for encryption/decryption of data,
+ * instead it is only useful as a "hash" algorithm.
+ *
+ * There is no entry point into this code that allows normal DES
+ * operation.
+ *
+ * I believe this means that this code does not come under ITAR
+ * regulations but this is NOT a legal opinion. If you are concerned about
+ * the applicability of ITAR regulations to this code then you should
+ * confirm it for yourself (and maybe let me know if you come up with a
+ * different answer to the one above) */
+
+static int perm1[56] =
+{57, 49, 41, 33, 25, 17, 9,
+ 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27,
+ 19, 11, 3, 60, 52, 44, 36,
+ 63, 55, 47, 39, 31, 23, 15,
+ 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29,
+ 21, 13, 5, 28, 20, 12, 4};
+
+static int perm2[48] =
+{14, 17, 11, 24, 1, 5,
+ 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8,
+ 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55,
+ 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53,
+ 46, 42, 50, 36, 29, 32};
+
+static int perm3[64] =
+{58, 50, 42, 34, 26, 18, 10, 2,
+ 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6,
+ 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1,
+ 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5,
+ 63, 55, 47, 39, 31, 23, 15, 7};
+
+static int perm4[48] =
+{32, 1, 2, 3, 4, 5,
+ 4, 5, 6, 7, 8, 9,
+ 8, 9, 10, 11, 12, 13,
+ 12, 13, 14, 15, 16, 17,
+ 16, 17, 18, 19, 20, 21,
+ 20, 21, 22, 23, 24, 25,
+ 24, 25, 26, 27, 28, 29,
+ 28, 29, 30, 31, 32, 1};
+
+static int perm5[32] =
+{16, 7, 20, 21,
+ 29, 12, 28, 17,
+ 1, 15, 23, 26,
+ 5, 18, 31, 10,
+ 2, 8, 24, 14,
+ 32, 27, 3, 9,
+ 19, 13, 30, 6,
+ 22, 11, 4, 25};
+
+static int perm6[64] =
+{40, 8, 48, 16, 56, 24, 64, 32,
+ 39, 7, 47, 15, 55, 23, 63, 31,
+ 38, 6, 46, 14, 54, 22, 62, 30,
+ 37, 5, 45, 13, 53, 21, 61, 29,
+ 36, 4, 44, 12, 52, 20, 60, 28,
+ 35, 3, 43, 11, 51, 19, 59, 27,
+ 34, 2, 42, 10, 50, 18, 58, 26,
+ 33, 1, 41, 9, 49, 17, 57, 25};
+
+static int sc[16] =
+{1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
+
+static int sbox[8][4][16] =
+{
+ {
+ {14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
+ {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
+ {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
+ {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
+ {
+ {15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
+ {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
+ {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
+ {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
+ {
+ {10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
+ {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
+ {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
+ {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
+ {
+ {7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
+ {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
+ {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
+ {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
+ {
+ {2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
+ {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
+ {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
+ {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
+ {
+ {12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
+ {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
+ {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
+ {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
+ {
+ {4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
+ {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
+ {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
+ {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
+ {
+ {13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
+ {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
+ {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
+ {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}
+ }
+};
+
+static void
+permute(char *out, char *in, int *p, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ out[i] = in[p[i] - 1];
+}
+
+static void
+l_shift(char *d, int count, int n)
+{
+ char out[64];
+ int i;
+ for (i = 0; i < n; i++)
+ out[i] = d[(i + count) % n];
+ for (i = 0; i < n; i++)
+ d[i] = out[i];
+}
+
+static void
+concat(char *out, char *in1, char *in2, int l1, int l2)
+{
+ while (l1--)
+ *out++ = *in1++;
+ while (l2--)
+ *out++ = *in2++;
+}
+
+static void
+xor(char *out, char *in1, char *in2, int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ out[i] = in1[i] ^ in2[i];
+}
+
+static void
+dohash(char *out, char *in, char *key)
+{
+ int i, j, k;
+ char pk1[56];
+ char c[28];
+ char d[28];
+ char cd[56];
+ char ki[16][48];
+ char pd1[64];
+ char l[32], r[32];
+ char rl[64];
+
+ permute(pk1, key, perm1, 56);
+
+ for (i = 0; i < 28; i++)
+ c[i] = pk1[i];
+ for (i = 0; i < 28; i++)
+ d[i] = pk1[i + 28];
+
+ for (i = 0; i < 16; i++) {
+ l_shift(c, sc[i], 28);
+ l_shift(d, sc[i], 28);
+
+ concat(cd, c, d, 28, 28);
+ permute(ki[i], cd, perm2, 48);
+ }
+
+ permute(pd1, in, perm3, 64);
+
+ for (j = 0; j < 32; j++) {
+ l[j] = pd1[j];
+ r[j] = pd1[j + 32];
+ }
+
+ for (i = 0; i < 16; i++) {
+ char er[48];
+ char erk[48];
+ char b[8][6];
+ char cb[32];
+ char pcb[32];
+ char r2[32];
+
+ permute(er, r, perm4, 48);
+
+ xor(erk, er, ki[i], 48);
+
+ for (j = 0; j < 8; j++)
+ for (k = 0; k < 6; k++)
+ b[j][k] = erk[j * 6 + k];
+
+ for (j = 0; j < 8; j++) {
+ int m, n;
+ m = (b[j][0] << 1) | b[j][5];
+
+ n = (b[j][1] << 3) | (b[j][2] << 2) | (b[j][3] << 1) | b[j][4];
+
+ for (k = 0; k < 4; k++)
+ b[j][k] = (sbox[j][m][n] & (1 << (3 - k))) ? 1 : 0;
+ }
+
+ for (j = 0; j < 8; j++)
+ for (k = 0; k < 4; k++)
+ cb[j * 4 + k] = b[j][k];
+ permute(pcb, cb, perm5, 32);
+
+ xor(r2, l, pcb, 32);
+
+ for (j = 0; j < 32; j++)
+ l[j] = r[j];
+
+ for (j = 0; j < 32; j++)
+ r[j] = r2[j];
+ }
+
+ concat(rl, r, l, 32, 32);
+
+ permute(out, rl, perm6, 64);
+}
+
+static void
+str_to_key(unsigned char *str, unsigned char *key)
+{
+ int i;
+
+ key[0] = str[0] >> 1;
+ key[1] = ((str[0] & 0x01) << 6) | (str[1] >> 2);
+ key[2] = ((str[1] & 0x03) << 5) | (str[2] >> 3);
+ key[3] = ((str[2] & 0x07) << 4) | (str[3] >> 4);
+ key[4] = ((str[3] & 0x0F) << 3) | (str[4] >> 5);
+ key[5] = ((str[4] & 0x1F) << 2) | (str[5] >> 6);
+ key[6] = ((str[5] & 0x3F) << 1) | (str[6] >> 7);
+ key[7] = str[6] & 0x7F;
+ for (i = 0; i < 8; i++) {
+ key[i] = (key[i] << 1);
+ }
+}
+
+static void
+smbhash(unsigned char *out, unsigned char *in, unsigned char *key)
+{
+ int i;
+ char outb[64];
+ char inb[64];
+ char keyb[64];
+ unsigned char key2[8];
+
+ str_to_key(key, key2);
+
+ for (i = 0; i < 64; i++) {
+ inb[i] = (in[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
+ keyb[i] = (key2[i / 8] & (1 << (7 - (i % 8)))) ? 1 : 0;
+ outb[i] = 0;
+ }
+
+ dohash(outb, inb, keyb);
+
+ for (i = 0; i < 8; i++) {
+ out[i] = 0;
+ }
+
+ for (i = 0; i < 64; i++) {
+ if (outb[i])
+ out[i / 8] |= (1 << (7 - (i % 8)));
+ }
+}
+
+static void
+E_P16(unsigned char *p14, unsigned char *p16)
+{
+ unsigned char sp8[8] =
+ {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
+ smbhash(p16, sp8, p14);
+ smbhash(p16 + 8, sp8, p14 + 7);
+}
+
+static void
+E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
+{
+ smbhash(p24, c8, p21);
+ smbhash(p24 + 8, c8, p21 + 7);
+ smbhash(p24 + 16, c8, p21 + 14);
+}
diff --git a/daemon/smbval/smbencrypt.inc.c b/daemon/smbval/smbencrypt.inc.c
new file mode 100644
index 0000000..2cef4f9
--- /dev/null
+++ b/daemon/smbval/smbencrypt.inc.c
@@ -0,0 +1,76 @@
+/* mod_ntlm file: $Id: smbencrypt.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
+
+/*
+ * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and
+ * setup Copyright (C) Andrew Tridgell 1992-1997 Modified by Jeremy
+ * Allison 1995. This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details. You should have received
+ * a copy of the GNU General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+ * Cambridge, MA 02139, USA. */
+
+#include <string.h>
+#include <arpa/inet.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/vfs.h>
+#include <netinet/in.h>
+
+#include "smblib-priv.h"
+#define uchar unsigned char
+
+#include "byteorder.h"
+
+static char *StrnCpy(char *dest, char *src, int n);
+static void strupper(char *s);
+
+/*
+ * This implements the X/Open SMB password encryption It takes a password,
+ * a 8 byte "crypt key" and puts 24 bytes of encrypted password into p24 */
+static void
+SMBencrypt(uchar * passwd, uchar * c8, uchar * p24)
+{
+ uchar p14[15], p21[21];
+
+ memset(p21, '\0', 21);
+ memset(p14, '\0', 14);
+ StrnCpy((char *) p14, (char *) passwd, 14);
+
+ strupper((char *) p14);
+ E_P16(p14, p21);
+ E_P24(p21, c8, p24);
+}
+
+/****************************************************************************
+line strncpy but always null terminates. Make sure there is room!
+****************************************************************************/
+static char *
+StrnCpy(char *dest, char *src, int n)
+{
+ char *d = dest;
+ if (!dest)
+ return (NULL);
+ if (!src) {
+ *dest = 0;
+ return (dest);
+ }
+ while (n-- && (*d++ = *src++)) ;
+ *d = 0;
+ return (dest);
+}
+
+static void
+strupper(char *s)
+{
+ while (*s) {
+ if (islower((int) *s))
+ *s = toupper(*s);
+ s++;
+ }
+}
diff --git a/daemon/smbval/smblib-common.h b/daemon/smbval/smblib-common.h
new file mode 100644
index 0000000..e80096a
--- /dev/null
+++ b/daemon/smbval/smblib-common.h
@@ -0,0 +1,205 @@
+/* mod_ntlm file: $Id: smblib-common.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef SMBLIB_COMMON_H
+#define SMBLIB_COMMON_H
+
+/* UNIX SMBlib NetBIOS implementation
+ *
+ * Version 1.0 SMBlib Common Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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. */
+
+/* To get the error class we want the first 8 bits */
+/* Because we just grab 4bytes from the SMB header, we have to re-order */
+/* here, but it makes the NtStatus part easier in future */
+
+#define SMBlib_Error_Class(p) (p & 0x000000FF)
+
+/* To get the error code, we want the bottom 16 bits */
+
+#define SMBlib_Error_Code(p) (((unsigned int)p & 0xFFFF0000) >>16)
+
+/* Error CLASS codes and etc ... */
+
+#define SMBC_SUCCESS 0
+#define SMBC_ERRDOS 0x01
+#define SMBC_ERRSRV 0x02
+#define SMBC_ERRHRD 0x03
+#define SMBC_ERRCMD 0xFF
+
+/* Success error codes */
+
+#define SMBS_BUFFERED 0x54
+#define SMBS_LOGGED 0x55
+#define SMBS_DISPLAYED 0x56
+
+/* ERRDOS Error codes */
+
+#define SMBD_badfunc 0x01
+#define SMBD_badfile 0x02
+#define SMBD_badpath 0x03
+#define SMBD_nofids 0x04
+#define SMBD_noaccess 0x05
+#define SMBD_badfid 0x06
+#define SMBD_badmcb 0x07
+#define SMBD_nomem 0x08
+#define SMBD_badmem 0x09
+#define SMBD_badenv 0x0A
+#define SMBD_badformat 0x0B
+#define SMBD_badaccess 0x0C
+#define SMBD_baddata 0x0D
+#define SMBD_reserved 0x0E
+#define SMBD_baddrive 0x0F
+#define SMBD_remcd 0x10
+#define SMBD_diffdevice 0x11
+#define SMBD_nofiles 0x12
+#define SMBD_badshare 0x20
+#define SMBD_errlock 0x21
+#define SMBD_filexists 0x50
+
+/* Server errors ... */
+
+#define SMBV_error 0x01 /* Generic error */
+#define SMBV_badpw 0x02
+#define SMBV_badtype 0x03
+#define SMBV_access 0x04
+#define SMBV_invnid 0x05
+#define SMBV_invnetname 0x06
+#define SMBV_invdevice 0x07
+#define SMBV_qfull 0x31
+#define SMBV_qtoobig 0x32
+#define SMBV_qeof 0x33
+#define SMBV_invpfid 0x34
+#define SMBV_paused 0x51
+#define SMBV_msgoff 0x52
+#define SMBV_noroom 0x53
+#define SMBV_rmuns 0x57
+#define SMBV_nosupport 0xFFFF
+
+/* Hardware error codes ... */
+
+#define SMBH_nowrite 0x13
+#define SMBH_badunit 0x14
+#define SMBH_notready 0x15
+#define SMBH_badcmd 0x16
+#define SMBH_data 0x17
+#define SMBH_badreq 0x18
+#define SMBH_seek 0x19
+#define SMBH_badmedia 0x1A
+#define SMBH_badsector 0x1B
+#define SMBH_nopaper 0x1C
+#define SMBH_write 0x1D
+#define SMBH_read 0x1E
+#define SMBH_general 0x1F
+#define SMBH_badshare 0x20
+
+/* Access mode defines ... */
+
+#define SMB_AMODE_WTRU 0x4000
+#define SMB_AMODE_NOCACHE 0x1000
+#define SMB_AMODE_COMPAT 0x0000
+#define SMB_AMODE_DENYRWX 0x0010
+#define SMB_AMODE_DENYW 0x0020
+#define SMB_AMODE_DENYRX 0x0030
+#define SMB_AMODE_DENYNONE 0x0040
+#define SMB_AMODE_OPENR 0x0000
+#define SMB_AMODE_OPENW 0x0001
+#define SMB_AMODE_OPENRW 0x0002
+#define SMB_AMODE_OPENX 0x0003
+#define SMB_AMODE_FCBOPEN 0x00FF
+#define SMB_AMODE_LOCUNKN 0x0000
+#define SMB_AMODE_LOCMSEQ 0x0100
+#define SMB_AMODE_LOCMRAN 0x0200
+#define SMB_AMODE_LOCRAL 0x0300
+
+/* File attribute encoding ... */
+
+#define SMB_FA_ORD 0x00
+#define SMB_FA_ROF 0x01
+#define SMB_FA_HID 0x02
+#define SMB_FA_SYS 0x04
+#define SMB_FA_VOL 0x08
+#define SMB_FA_DIR 0x10
+#define SMB_FA_ARC 0x20
+
+/* Define the protocol types ... */
+
+#define SMB_P_Unknown -1 /* Hmmm, is this smart? */
+#define SMB_P_Core 0
+#define SMB_P_CorePlus 1
+#define SMB_P_DOSLanMan1 2
+#define SMB_P_LanMan1 3
+#define SMB_P_DOSLanMan2 4
+#define SMB_P_LanMan2 5
+#define SMB_P_DOSLanMan2_1 6
+#define SMB_P_LanMan2_1 7
+#define SMB_P_NT1 8
+
+/* SMBlib return codes */
+/* We want something that indicates whether or not the return code was a
+ * */
+/* remote error, a local error in SMBlib or returned from lower layer ...
+ * */
+/* Wonder if this will work ...
+ * */
+/* SMBlibE_Remote = 1 indicates remote error
+ * */
+/* SMBlibE_ values < 0 indicate local error with more info available
+ * */
+/* SMBlibE_ values >1 indicate local from SMBlib code errors?
+ * */
+
+#define SMBlibE_Success 0
+#define SMBlibE_Remote 1 /* Remote error, get more info from con
+ * */
+#define SMBlibE_BAD -1
+#define SMBlibE_LowerLayer 2 /* Lower layer error
+ * */
+#define SMBlibE_NotImpl 3 /* Function not yet implemented
+ * */
+#define SMBlibE_ProtLow 4 /* Protocol negotiated does not support
+ * req */
+#define SMBlibE_NoSpace 5 /* No space to allocate a structure
+ * */
+#define SMBlibE_BadParam 6 /* Bad parameters
+ * */
+#define SMBlibE_NegNoProt 7 /* None of our protocols was liked
+ * */
+#define SMBlibE_SendFailed 8 /* Sending an SMB failed
+ * */
+#define SMBlibE_RecvFailed 9 /* Receiving an SMB failed
+ * */
+#define SMBlibE_GuestOnly 10 /* Logged in as guest
+ * */
+#define SMBlibE_CallFailed 11 /* Call remote end failed
+ * */
+#define SMBlibE_ProtUnknown 12 /* Protocol unknown
+ * */
+#define SMBlibE_NoSuchMsg 13 /* Keep this up to date
+ * */
+
+typedef struct { /* A structure for a Dirent */
+
+ unsigned char resume_key[21]; /* Don't touch this */
+ unsigned char file_attributes; /* Attributes of file */
+ unsigned int date_time; /* date and time of last mod */
+ unsigned int size;
+ char filename[13]; /* The name of the file */
+
+} SMB_CP_dirent;
+
+#endif
diff --git a/daemon/smbval/smblib-priv.h b/daemon/smbval/smblib-priv.h
new file mode 100644
index 0000000..f5bc840
--- /dev/null
+++ b/daemon/smbval/smblib-priv.h
@@ -0,0 +1,672 @@
+/* mod_ntlm file: $Id: smblib-priv.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef SMBLIB_PRIV_H
+#define SMBLIB_PRIV_H
+
+/* UNIX SMBlib NetBIOS implementation
+ *
+ * Version 1.0 SMBlib private Defines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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 "std-defines.h"
+#include "smblib-common.h"
+#include <sys/types.h>
+#include <unistd.h>
+
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+
+#include "byteorder.h" /* Hmmm ... hot good */
+
+#define max(a,b) (a < b ? b : a)
+
+#define SMB_DEF_IDF 0x424D53FF /* "\377SMB" */
+
+/* Core protocol commands */
+
+#define SMBmkdir 0x00 /* create directory */
+#define SMBrmdir 0x01 /* delete directory */
+#define SMBopen 0x02 /* open file */
+#define SMBcreate 0x03 /* create file */
+#define SMBclose 0x04 /* close file */
+#define SMBflush 0x05 /* flush file */
+#define SMBunlink 0x06 /* delete file */
+#define SMBmv 0x07 /* rename file */
+#define SMBgetatr 0x08 /* get file attributes */
+#define SMBsetatr 0x09 /* set file attributes */
+#define SMBread 0x0A /* read from file */
+#define SMBwrite 0x0B /* write to file */
+#define SMBlock 0x0C /* lock byte range */
+#define SMBunlock 0x0D /* unlock byte range */
+#define SMBctemp 0x0E /* create temporary file */
+#define SMBmknew 0x0F /* make new file */
+#define SMBchkpth 0x10 /* check directory path */
+#define SMBexit 0x11 /* process exit */
+#define SMBlseek 0x12 /* seek */
+#define SMBtcon 0x70 /* tree connect */
+#define SMBtdis 0x71 /* tree disconnect */
+#define SMBnegprot 0x72 /* negotiate protocol */
+#define SMBdskattr 0x80 /* get disk attributes */
+#define SMBsearch 0x81 /* search directory */
+#define SMBsplopen 0xC0 /* open print spool file */
+#define SMBsplwr 0xC1 /* write to print spool file */
+#define SMBsplclose 0xC2 /* close print spool file */
+#define SMBsplretq 0xC3 /* return print queue */
+#define SMBsends 0xD0 /* send single block message */
+#define SMBsendb 0xD1 /* send broadcast message */
+#define SMBfwdname 0xD2 /* forward user name */
+#define SMBcancelf 0xD3 /* cancel forward */
+#define SMBgetmac 0xD4 /* get machine name */
+#define SMBsendstrt 0xD5 /* send start of multi-block message */
+#define SMBsendend 0xD6 /* send end of multi-block message */
+#define SMBsendtxt 0xD7 /* send text of multi-block message */
+
+/* CorePlus protocol */
+
+#define SMBlockread 0x13 /* Lock a range and read it */
+#define SMBwriteunlock 0x14 /* Unlock a range and then write */
+#define SMBreadbraw 0x1a /* read a block of data without smb header
+ * ohead */
+#define SMBwritebraw 0x1d /* write a block of data without smb
+ * header ohead */
+#define SMBwritec 0x20 /* secondary write request */
+#define SMBwriteclose 0x2c /* write a file and then close it */
+
+/* DOS Extended Protocol */
+
+#define SMBreadBraw 0x1A /* read block raw */
+#define SMBreadBmpx 0x1B /* read block multiplexed */
+#define SMBreadBs 0x1C /* read block (secondary response) */
+#define SMBwriteBraw 0x1D /* write block raw */
+#define SMBwriteBmpx 0x1E /* write block multiplexed */
+#define SMBwriteBs 0x1F /* write block (secondary request) */
+#define SMBwriteC 0x20 /* write complete response */
+#define SMBsetattrE 0x22 /* set file attributes expanded */
+#define SMBgetattrE 0x23 /* get file attributes expanded */
+#define SMBlockingX 0x24 /* lock/unlock byte ranges and X */
+#define SMBtrans 0x25 /* transaction - name, bytes in/out */
+#define SMBtranss 0x26 /* transaction (secondary
+ * request/response) */
+#define SMBioctl 0x27 /* IOCTL */
+#define SMBioctls 0x28 /* IOCTL (secondary request/response) */
+#define SMBcopy 0x29 /* copy */
+#define SMBmove 0x2A /* move */
+#define SMBecho 0x2B /* echo */
+#define SMBopenX 0x2D /* open and X */
+#define SMBreadX 0x2E /* read and X */
+#define SMBwriteX 0x2F /* write and X */
+#define SMBsesssetupX 0x73 /* Session Set Up & X (including User
+ * Logon) */
+#define SMBtconX 0x75 /* tree connect and X */
+#define SMBffirst 0x82 /* find first */
+#define SMBfunique 0x83 /* find unique */
+#define SMBfclose 0x84 /* find close */
+#define SMBinvalid 0xFE /* invalid command */
+
+/* Any more ? */
+
+#define SMBdatablockID 0x01 /* A data block identifier */
+#define SMBdialectID 0x02 /* A dialect id */
+#define SMBpathnameID 0x03 /* A pathname ID */
+#define SMBasciiID 0x04 /* An ascii string ID */
+#define SMBvariableblockID 0x05 /* A variable block ID */
+
+/* some other defines we need */
+
+/* Flags defines ... */
+
+#define SMB_FLG2_NON_DOS 0x01 /* We know non dos names
+ * */
+#define SMB_FLG2_EXT_ATR 0x02 /* We know about Extended
+ * Attributes */
+#define SMB_FLG2_LNG_NAM 0x04 /* Long names ?
+ * */
+
+typedef unsigned short WORD;
+typedef unsigned short UWORD;
+typedef unsigned int ULONG;
+typedef unsigned char BYTE;
+typedef unsigned char UCHAR;
+
+/* Some macros to allow access to actual packet data so that we */
+/* can change the underlying representation of packets. */
+/* */
+/* The current formats vying for attention are a fragment */
+/* approach where the SMB header is a fragment linked to the */
+/* data portion with the transport protocol (rfcnb or whatever) */
+/* being linked on the front. */
+/* */
+/* The other approach is where the whole packet is one array */
+/* of bytes with space allowed on the front for the packet */
+/* headers. */
+
+#define SMB_Hdr(p) (char *)(p -> data)
+
+/* SMB Hdr def for File Sharing Protocol? From MS and Intel, */
+/* Intel PN 138446 Doc Version 2.0, Nov 7, 1988. This def also */
+/* applies to LANMAN1.0 as well as the Core Protocol */
+/* The spec states that wct and bcc must be present, even if 0 */
+
+/* We define these as offsets into a char SMB[] array for the */
+/* sake of portability */
+
+/* NOTE!. Some of the lenght defines, SMB_<protreq>_len do not include */
+/* the data that follows in the SMB packet, so the code will have to */
+/* take that into account. */
+
+#define SMB_hdr_idf_offset 0 /* 0xFF,'SMB' 0-3 */
+#define SMB_hdr_com_offset 4 /* BYTE 4 */
+#define SMB_hdr_rcls_offset 5 /* BYTE 5 */
+#define SMB_hdr_reh_offset 6 /* BYTE 6 */
+#define SMB_hdr_err_offset 7 /* WORD 7 */
+#define SMB_hdr_reb_offset 9 /* BYTE 9 */
+#define SMB_hdr_flg_offset 9 /* same as reb ... */
+#define SMB_hdr_res_offset 10 /* 7 WORDs 10 */
+#define SMB_hdr_res0_offset 10 /* WORD 10 */
+#define SMB_hdr_flg2_offset 10 /* WORD */
+#define SMB_hdr_res1_offset 12 /* WORD 12 */
+#define SMB_hdr_res2_offset 14
+#define SMB_hdr_res3_offset 16
+#define SMB_hdr_res4_offset 18
+#define SMB_hdr_res5_offset 20
+#define SMB_hdr_res6_offset 22
+#define SMB_hdr_tid_offset 24
+#define SMB_hdr_pid_offset 26
+#define SMB_hdr_uid_offset 28
+#define SMB_hdr_mid_offset 30
+#define SMB_hdr_wct_offset 32
+
+#define SMB_hdr_len 33 /* 33 byte header? */
+
+#define SMB_hdr_axc_offset 33 /* AndX Command */
+#define SMB_hdr_axr_offset 34 /* AndX Reserved */
+#define SMB_hdr_axo_offset 35 /* Offset from start to WCT of
+ * AndX cmd */
+
+/* Format of the Negotiate Protocol SMB */
+
+#define SMB_negp_bcc_offset 33
+#define SMB_negp_buf_offset 35 /* Where the buffer starts */
+#define SMB_negp_len 35 /* plus the data */
+
+/* Format of the Negotiate Response SMB, for CoreProtocol, LM1.2 and */
+/* NT LM 0.12. wct will be 1 for CoreProtocol, 13 for LM 1.2, and 17 */
+/* for NT LM 0.12 */
+
+#define SMB_negrCP_idx_offset 33 /* Response to the neg req */
+#define SMB_negrCP_bcc_offset 35
+#define SMB_negrLM_idx_offset 33 /* dialect index */
+#define SMB_negrLM_sec_offset 35 /* Security mode */
+#define SMB_sec_user_mask 0x01 /* 0 = share, 1 = user */
+#define SMB_sec_encrypt_mask 0x02 /* pick out encrypt */
+#define SMB_negrLM_mbs_offset 37 /* max buffer size */
+#define SMB_negrLM_mmc_offset 39 /* max mpx count */
+#define SMB_negrLM_mnv_offset 41 /* max number of VCs */
+#define SMB_negrLM_rm_offset 43 /* raw mode support bit vec */
+#define SMB_read_raw_mask 0x01
+#define SMB_write_raw_mask 0x02
+#define SMB_negrLM_sk_offset 45 /* session key, 32 bits */
+#define SMB_negrLM_st_offset 49 /* Current server time */
+#define SMB_negrLM_sd_offset 51 /* Current server date */
+#define SMB_negrLM_stz_offset 53 /* Server Time Zone */
+#define SMB_negrLM_ekl_offset 55 /* encryption key length */
+#define SMB_negrLM_res_offset 57 /* reserved */
+#define SMB_negrLM_bcc_offset 59 /* bcc */
+#define SMB_negrLM_len 61 /* 61 bytes ? */
+#define SMB_negrLM_buf_offset 61 /* Where the fun begins */
+
+#define SMB_negrNTLM_idx_offset 33 /* Selected protocol */
+#define SMB_negrNTLM_sec_offset 35 /* Security more */
+#define SMB_negrNTLM_mmc_offset 36 /* Different format above */
+#define SMB_negrNTLM_mnv_offset 38 /* Max VCs */
+#define SMB_negrNTLM_mbs_offset 40 /* MBS now a long */
+#define SMB_negrNTLM_mrs_offset 44 /* Max raw size */
+#define SMB_negrNTLM_sk_offset 48 /* Session Key */
+#define SMB_negrNTLM_cap_offset 52 /* Capabilities */
+#define SMB_negrNTLM_stl_offset 56 /* Server time low */
+#define SMB_negrNTLM_sth_offset 60 /* Server time high */
+#define SMB_negrNTLM_stz_offset 64 /* Server time zone */
+#define SMB_negrNTLM_ekl_offset 66 /* Encrypt key len */
+#define SMB_negrNTLM_bcc_offset 67 /* Bcc */
+#define SMB_negrNTLM_len 69
+#define SMB_negrNTLM_buf_offset 69
+
+/* Offsets related to Tree Connect */
+
+#define SMB_tcon_bcc_offset 33
+#define SMB_tcon_buf_offset 35 /* where the data is for tcon */
+#define SMB_tcon_len 35 /* plus the data */
+
+#define SMB_tconr_mbs_offset 33 /* max buffer size */
+#define SMB_tconr_tid_offset 35 /* returned tree id */
+#define SMB_tconr_bcc_offset 37
+#define SMB_tconr_len 39
+
+#define SMB_tconx_axc_offset 33 /* And X Command */
+#define SMB_tconx_axr_offset 34 /* reserved */
+#define SMB_tconx_axo_offset 35 /* Next command offset */
+#define SMB_tconx_flg_offset 37 /* Flags, bit0=1 means disc TID */
+#define SMB_tconx_pwl_offset 39 /* Password length */
+#define SMB_tconx_bcc_offset 41 /* bcc */
+#define SMB_tconx_buf_offset 43 /* buffer */
+#define SMB_tconx_len 43 /* up to data ... */
+
+#define SMB_tconxr_axc_offset 33 /* Where the AndX Command is */
+#define SMB_tconxr_axr_offset 34 /* Reserved */
+#define SMB_tconxr_axo_offset 35 /* AndX offset location */
+
+/* Offsets related to tree_disconnect */
+
+#define SMB_tdis_bcc_offset 33 /* bcc */
+#define SMB_tdis_len 35 /* total len */
+
+#define SMB_tdisr_bcc_offset 33 /* bcc */
+#define SMB_tdisr_len 35
+
+/* Offsets related to Open Request */
+
+#define SMB_open_mod_offset 33 /* Mode to open with */
+#define SMB_open_atr_offset 35 /* Attributes of file */
+#define SMB_open_bcc_offset 37 /* bcc */
+#define SMB_open_buf_offset 39 /* File name */
+#define SMB_open_len 39 /* Plus the file name */
+
+#define SMB_openx_axc_offset 33 /* Next command */
+#define SMB_openx_axr_offset 34 /* Reserved */
+#define SMB_openx_axo_offset 35 /* offset of next wct */
+#define SMB_openx_flg_offset 37 /* Flags, bit0 = need more info */
+ /* bit1 = exclusive oplock */
+ /* bit2 = batch oplock */
+#define SMB_openx_mod_offset 39 /* mode to open with */
+#define SMB_openx_atr_offset 41 /* search attributes */
+#define SMB_openx_fat_offset 43 /* File attributes */
+#define SMB_openx_tim_offset 45 /* time and date of creat */
+#define SMB_openx_ofn_offset 49 /* Open function */
+#define SMB_openx_als_offset 51 /* Space to allocate on */
+#define SMB_openx_res_offset 55 /* reserved */
+#define SMB_openx_bcc_offset 63 /* bcc */
+#define SMB_openx_buf_offset 65 /* Where file name goes */
+#define SMB_openx_len 65
+
+#define SMB_openr_fid_offset 33 /* FID returned */
+#define SMB_openr_atr_offset 35 /* Attributes opened with */
+#define SMB_openr_tim_offset 37 /* Last mod time of file */
+#define SMB_openr_fsz_offset 41 /* File size 4 bytes */
+#define SMB_openr_acc_offset 45 /* Access allowed */
+#define SMB_openr_bcc_offset 47
+#define SMB_openr_len 49
+
+#define SMB_openxr_axc_offset 33 /* And X command */
+#define SMB_openxr_axr_offset 34 /* reserved */
+#define SMB_openxr_axo_offset 35 /* offset to next command */
+#define SMB_openxr_fid_offset 37 /* FID returned */
+#define SMB_openxr_fat_offset 39 /* File attributes returned */
+#define SMB_openxr_tim_offset 41 /* File creation date etc */
+#define SMB_openxr_fsz_offset 45 /* Size of file */
+#define SMB_openxr_acc_offset 49 /* Access granted */
+
+#define SMB_clos_fid_offset 33 /* FID to close */
+#define SMB_clos_tim_offset 35 /* Last mod time */
+#define SMB_clos_bcc_offset 39 /* bcc */
+#define SMB_clos_len 41
+
+/* Offsets related to Write requests */
+
+#define SMB_write_fid_offset 33 /* FID to write */
+#define SMB_write_cnt_offset 35 /* bytes to write */
+#define SMB_write_ofs_offset 37 /* location to write to */
+#define SMB_write_clf_offset 41 /* advisory count left */
+#define SMB_write_bcc_offset 43 /* bcc = data bytes + 3 */
+#define SMB_write_buf_offset 45 /* Data=0x01, len, data */
+#define SMB_write_len 45 /* plus the data ... */
+
+#define SMB_writr_cnt_offset 33 /* Count of bytes written */
+#define SMB_writr_bcc_offset 35 /* bcc */
+#define SMB_writr_len 37
+
+/* Offsets related to read requests */
+
+#define SMB_read_fid_offset 33 /* FID of file to read */
+#define SMB_read_cnt_offset 35 /* count of words to read */
+#define SMB_read_ofs_offset 37 /* Where to read from */
+#define SMB_read_clf_offset 41 /* Advisory count to go */
+#define SMB_read_bcc_offset 43
+#define SMB_read_len 45
+
+#define SMB_readr_cnt_offset 33 /* Count of bytes returned */
+#define SMB_readr_res_offset 35 /* 4 shorts reserved, 8 bytes */
+#define SMB_readr_bcc_offset 43 /* bcc */
+#define SMB_readr_bff_offset 45 /* buffer format char = 0x01 */
+#define SMB_readr_len_offset 46 /* buffer len */
+#define SMB_readr_len 45 /* length of the readr before data
+ */
+
+/* Offsets for Create file */
+
+#define SMB_creat_atr_offset 33 /* Attributes of new file ... */
+#define SMB_creat_tim_offset 35 /* Time of creation */
+#define SMB_creat_dat_offset 37 /* 4004BCE :-) */
+#define SMB_creat_bcc_offset 39 /* bcc */
+#define SMB_creat_buf_offset 41
+#define SMB_creat_len 41 /* Before the data */
+
+#define SMB_creatr_fid_offset 33 /* FID of created file */
+
+/* Offsets for Delete file */
+
+#define SMB_delet_sat_offset 33 /* search attribites */
+#define SMB_delet_bcc_offset 35 /* bcc */
+#define SMB_delet_buf_offset 37
+#define SMB_delet_len 37
+
+/* Offsets for SESSION_SETUP_ANDX for both LM and NT LM protocols */
+
+#define SMB_ssetpLM_mbs_offset 37 /* Max buffer Size, allow for AndX
+ */
+#define SMB_ssetpLM_mmc_offset 39 /* max multiplex count
+ * */
+#define SMB_ssetpLM_vcn_offset 41 /* VC number if new VC
+ * */
+#define SMB_ssetpLM_snk_offset 43 /* Session Key
+ * */
+#define SMB_ssetpLM_pwl_offset 47 /* password length
+ * */
+#define SMB_ssetpLM_res_offset 49 /* reserved
+ * */
+#define SMB_ssetpLM_bcc_offset 53 /* bcc
+ * */
+#define SMB_ssetpLM_len 55 /* before data ...
+ * */
+#define SMB_ssetpLM_buf_offset 55
+
+#define SMB_ssetpNTLM_mbs_offset 37 /* Max Buffer Size for NT LM 0.12
+ * */
+ /* and above
+ * */
+#define SMB_ssetpNTLM_mmc_offset 39 /* Max Multiplex count
+ * */
+#define SMB_ssetpNTLM_vcn_offset 41 /* VC Number
+ * */
+#define SMB_ssetpNTLM_snk_offset 43 /* Session key
+ * */
+#define SMB_ssetpNTLM_cipl_offset 47 /* Case Insensitive PW Len
+ * */
+#define SMB_ssetpNTLM_cspl_offset 49 /* Unicode pw len
+ * */
+#define SMB_ssetpNTLM_res_offset 51 /* reserved
+ * */
+#define SMB_ssetpNTLM_cap_offset 55 /* server capabilities
+ * */
+#define SMB_ssetpNTLM_bcc_offset 59 /* bcc
+ * */
+#define SMB_ssetpNTLM_len 61 /* before data
+ * */
+#define SMB_ssetpNTLM_buf_offset 61
+
+#define SMB_ssetpr_axo_offset 35 /* Offset of next response ... */
+#define SMB_ssetpr_act_offset 37 /* action, bit 0 = 1 => guest */
+#define SMB_ssetpr_bcc_offset 39 /* bcc */
+#define SMB_ssetpr_buf_offset 41 /* Native OS etc */
+
+/* Offsets for SMB create directory
+ * */
+
+#define SMB_creatdir_bcc_offset 33 /* only a bcc here */
+#define SMB_creatdir_buf_offset 35 /* Where things start */
+#define SMB_creatdir_len 35
+
+/* Offsets for SMB delete directory
+ * */
+
+#define SMB_deletdir_bcc_offset 33 /* only a bcc here */
+#define SMB_deletdir_buf_offset 35 /* where things start */
+#define SMB_deletdir_len 35
+
+/* Offsets for SMB check directory
+ * */
+
+#define SMB_checkdir_bcc_offset 33 /* Only a bcc here */
+#define SMB_checkdir_buf_offset 35 /* where things start */
+#define SMB_checkdir_len 35
+
+/* Offsets for SMB search
+ * */
+
+#define SMB_search_mdc_offset 33 /* Max Dir ents to return */
+#define SMB_search_atr_offset 35 /* Search attributes */
+#define SMB_search_bcc_offset 37 /* bcc */
+#define SMB_search_buf_offset 39 /* where the action is */
+#define SMB_search_len 39
+
+#define SMB_searchr_dec_offset 33 /* Dir ents returned */
+#define SMB_searchr_bcc_offset 35 /* bcc */
+#define SMB_searchr_buf_offset 37 /* Where the action starts */
+#define SMB_searchr_len 37 /* before the dir ents */
+
+#define SMB_searchr_dirent_len 43 /* 53 bytes */
+
+/* Defines for SMB transact and transact2 calls
+ * */
+
+#define SMB_trans_tpc_offset 33 /* Total param count */
+#define SMB_trans_tdc_offset 35 /* total Data count */
+#define SMB_trans_mpc_offset 37 /* Max params bytes to return */
+#define SMB_trans_mdc_offset 39 /* Max data bytes to return */
+#define SMB_trans_msc_offset 41 /* Max setup words to return */
+#define SMB_trans_rs1_offset 42 /* Reserved byte */
+#define SMB_trans_flg_offset 43 /* flags */
+#define SMB_trans_tmo_offset 45 /* Timeout, long */
+#define SMB_trans_rs2_offset 49 /* Next reserved */
+#define SMB_trans_pbc_offset 51 /* Param Byte count in buf */
+#define SMB_trans_pbo_offset 53 /* Offset to param bytes */
+#define SMB_trans_dbc_offset 55 /* Data byte count in buf */
+#define SMB_trans_dbo_offset 57 /* Data byte offset */
+#define SMB_trans_suc_offset 59 /* Setup count - byte */
+#define SMB_trans_rs3_offset 60 /* Reserved to pad ... */
+#define SMB_trans_len 61 /* Up to setup, still need bcc */
+
+#define SMB_transr_tpc_offset 33 /* Total param bytes returned */
+#define SMB_transr_tdc_offset 35
+#define SMB_transr_rs1_offset 37
+#define SMB_transr_pbc_offset 39
+#define SMB_transr_pbo_offset 41
+#define SMB_transr_pdi_offset 43 /* parameter displacement */
+#define SMB_transr_dbc_offset 45
+#define SMB_transr_dbo_offset 47
+#define SMB_transr_ddi_offset 49
+#define SMB_transr_suc_offset 51
+#define SMB_transr_rs2_offset 52
+#define SMB_transr_len 53
+
+/* Bit masks for SMB Capabilities ... */
+
+#define SMB_cap_raw_mode 0x0001
+#define SMB_cap_mpx_mode 0x0002
+#define SMB_cap_unicode 0x0004
+#define SMB_cap_large_files 0x0008
+#define SMB_cap_nt_smbs 0x0010
+#define SMB_rpc_remote_apis 0x0020
+#define SMB_cap_nt_status 0x0040
+#define SMB_cap_level_II_oplocks 0x0080
+#define SMB_cap_lock_and_read 0x0100
+#define SMB_cap_nt_find 0x0200
+
+/* SMB LANMAN api call defines */
+
+#define SMB_LMapi_SetUserInfo 0x0072
+#define SMB_LMapi_UserPasswordSet 0x0073
+
+/* Structures and defines we use in the client interface */
+
+/* The protocols we might support. Perhaps a bit ambitious, as only RFCNB */
+/* has any support so far 0(sometimes called NBT) */
+
+typedef enum {
+ SMB_RFCNB, SMB_IPXNB, SMB_NETBEUI, SMB_X25
+} SMB_Transport_Types;
+
+typedef enum {
+ SMB_Con_FShare, SMB_Con_PShare, SMB_Con_IPC
+} SMB_Con_Types;
+
+typedef enum {
+ SMB_State_NoState, SMB_State_Stopped, SMB_State_Started
+} SMB_State_Types;
+
+/* The following two arrays need to be in step! */
+/* We must make it possible for callers to specify these ... */
+
+static char *SMB_Prots[] =
+{"PC NETWORK PROGRAM 1.0",
+ "MICROSOFT NETWORKS 1.03",
+ "MICROSOFT NETWORKS 3.0",
+ "DOS LANMAN1.0",
+ "LANMAN1.0",
+ "DOS LM1.2X002",
+ "LM1.2X002",
+ "DOS LANMAN2.1",
+ "LANMAN2.1",
+ "Samba",
+ "NT LM 0.12",
+ "NT LANMAN 1.0",
+ NULL};
+
+static int SMB_Types[] =
+{SMB_P_Core,
+ SMB_P_CorePlus,
+ SMB_P_DOSLanMan1,
+ SMB_P_DOSLanMan1,
+ SMB_P_LanMan1,
+ SMB_P_DOSLanMan2,
+ SMB_P_LanMan2,
+ SMB_P_LanMan2_1,
+ SMB_P_LanMan2_1,
+ SMB_P_NT1,
+ SMB_P_NT1,
+ SMB_P_NT1,
+ -1};
+
+typedef struct SMB_Status {
+
+ union {
+ struct {
+ unsigned char ErrorClass;
+ unsigned char Reserved;
+ unsigned short Error;
+ } DosError;
+ unsigned int NtStatus;
+ } status;
+} SMB_Status;
+
+typedef struct SMB_Tree_Structure *SMB_Tree_Handle;
+
+typedef struct SMB_Connect_Def *SMB_Handle_Type;
+
+struct SMB_Connect_Def {
+
+ SMB_Handle_Type Next_Con, Prev_Con; /* Next and previous conn */
+ int protocol; /* What is the protocol */
+ int prot_IDX; /* And what is the index */
+ void *Trans_Connect; /* The connection */
+
+ /* All these strings should be malloc'd */
+
+ char service[80], username[80], password[80], desthost[80], sock_options[80];
+ char address[80], myname[80];
+
+ SMB_Tree_Handle first_tree, last_tree; /* List of trees on this
+ * server */
+
+ int gid; /* Group ID, do we need it?
+ * */
+ int mid; /* Multiplex ID? We might need one per con
+ */
+ int pid; /* Process ID
+ * */
+
+ int uid; /* Authenticated user id.
+ * */
+
+ /* It is pretty clear that we need to bust some of */
+ /* these out into a per TCon record, as there may */
+ /* be multiple TCon's per server, etc ... later */
+
+ int port; /* port to use in case not default, this
+ * is a TCPism! */
+
+ int max_xmit; /* Max xmit permitted by server
+ * */
+ int Security; /* 0 = share, 1 = user
+ * */
+ int Raw_Support; /* bit 0 = 1 = Read Raw supported, 1 = 1
+ * Write raw */
+ BOOL encrypt_passwords; /* FALSE = don't */
+ int MaxMPX, MaxVC, MaxRaw;
+ unsigned int SessionKey, Capabilities;
+ int SvrTZ; /* Server Time Zone */
+ int Encrypt_Key_Len;
+ char Encrypt_Key[80], Domain[80], PDomain[80], OSName[80], LMType[40];
+ char Svr_OS[80], Svr_LMType[80], Svr_PDom[80];
+
+};
+
+#define SMBLIB_DEFAULT_DOMAIN "STAFF"
+#define SMBLIB_DEFAULT_OSNAME "UNIX of some type"
+#define SMBLIB_DEFAULT_LMTYPE "SMBlib LM2.1 minus a bit"
+#define SMBLIB_MAX_XMIT 65535
+
+#define SMB_Sec_Mode_Share 0
+#define SMB_Sec_Mode_User 1
+
+/* A Tree_Structure */
+
+struct SMB_Tree_Structure {
+
+ SMB_Tree_Handle next, prev;
+ SMB_Handle_Type con;
+ char path[129];
+ char device_type[20];
+ int mbs; /* Local MBS */
+ int tid;
+
+};
+
+typedef struct SMB_File_Def SMB_File;
+
+struct SMB_File_Def {
+
+ SMB_Tree_Handle tree;
+ char filename[256]; /* We should malloc this ... */
+ UWORD fid;
+ unsigned int lastmod;
+ unsigned int size; /* Could blow up if 64bit files supported */
+ UWORD access;
+ off_t fileloc;
+
+};
+
+/* global Variables for the library */
+
+extern SMB_State_Types SMBlib_State;
+
+#ifndef SMBLIB_ERRNO
+extern int SMBlib_errno;
+extern int SMBlib_SMB_Error; /* last Error */
+#endif
+
+#endif
diff --git a/daemon/smbval/smblib-util.inc.c b/daemon/smbval/smblib-util.inc.c
new file mode 100644
index 0000000..f8c77bf
--- /dev/null
+++ b/daemon/smbval/smblib-util.inc.c
@@ -0,0 +1,248 @@
+/* mod_ntlm file: $Id: smblib-util.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
+
+/* UNIX SMBlib NetBIOS implementation
+ *
+ * Version 1.0 SMBlib Utility Routines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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 "smblib-priv.h"
+#include <malloc.h>
+
+#include "rfcnb.h"
+
+/* Figure out what protocol was accepted, given the list of dialect
+ * strings. We offered, and the index back from the server. We allow
+ * for a user supplied list, and assume that it is a subset of our
+ * list */
+static int
+SMB_Figure_Protocol(char *dialects[], int prot_index)
+{
+ int i;
+
+ if (dialects == SMB_Prots) { /* The jobs is easy, just index
+ * into table */
+ return SMB_Types[prot_index];
+ } else { /* Search through SMB_Prots looking
+ * for a match */
+ for (i = 0; SMB_Prots[i] != NULL; i++) {
+ if (strcmp(dialects[prot_index], SMB_Prots[i]) == 0) {
+ /* A match */
+ return SMB_Types[i];
+ }
+ }
+
+ /* If we got here, then we are in trouble, because the
+ * protocol was not one we understand ... */
+ return SMB_P_Unknown;
+ }
+}
+
+/* Negotiate the protocol we will use from the list passed in Prots we
+ * return the index of the accepted protocol in NegProt, -1 *indicates
+ * none acceptible, and our return value is 0 if ok, <0 if problems */
+static int
+SMB_Negotiate(SMB_Handle_Type Con_Handle, char *Prots[])
+{
+ struct RFCNB_Pkt *pkt;
+ int prots_len, i, pkt_len, prot, alloc_len;
+ char *p;
+
+ /* Figure out how long the prot list will be and allocate space
+ * for it */
+ prots_len = 0;
+
+ for (i = 0; Prots[i] != NULL; i++) {
+ prots_len = prots_len + strlen(Prots[i]) + 2; /* Account for
+ * null etc */
+ }
+
+ /* The -1 accounts for the one byte smb_buf we have because some
+ * systems don't like char msg_buf[] */
+ pkt_len = SMB_negp_len + prots_len;
+
+ /* Make sure that the pkt len is long enough for the max
+ * response... Which is a problem, because the encryption key len
+ * eec may be long */
+ if (pkt_len < (SMB_hdr_wct_offset + (19 * 2) + 40))
+ alloc_len = SMB_hdr_wct_offset + (19 * 2) + 40;
+ else
+ alloc_len = pkt_len;
+
+ pkt = (struct RFCNB_Pkt *) RFCNB_Alloc_Pkt(alloc_len);
+ if (pkt == NULL) {
+ SMBlib_errno = SMBlibE_NoSpace;
+ return (SMBlibE_BAD);
+ }
+ /* Now plug in the bits we need */
+ bzero(SMB_Hdr(pkt), SMB_negp_len);
+ SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk in IDF */
+ *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBnegprot;
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle->pid);
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle->mid);
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle->uid);
+ *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 0;
+
+ SSVAL(SMB_Hdr(pkt), SMB_negp_bcc_offset, prots_len);
+
+ /* Now copy the prot strings in with the right stuff */
+ p = (char *) (SMB_Hdr(pkt) + SMB_negp_buf_offset);
+
+ for (i = 0; Prots[i] != NULL; i++) {
+ *p = SMBdialectID;
+ strcpy(p + 1, Prots[i]);
+ p = p + strlen(Prots[i]) + 2; /* Adjust len of p for null
+ * plus dialectID */
+ }
+
+ /* Now send the packet and sit back ... */
+ if (RFCNB_Send(Con_Handle->Trans_Connect, pkt, pkt_len) < 0) {
+#ifdef SMB_DEBUG
+ fprintf(stderr, "Error sending negotiate protocol\n");
+#endif
+ RFCNB_Free_Pkt(pkt);
+ SMBlib_errno = -SMBlibE_SendFailed; /* Failed, check lower
+ * layer errno */
+ return (SMBlibE_BAD);
+ }
+ /* Now get the response ... */
+ if (RFCNB_Recv(Con_Handle->Trans_Connect, pkt, alloc_len) < 0) {
+#ifdef SMB_DEBUG
+ fprintf(stderr, "Error receiving response to negotiate\n");
+#endif
+ RFCNB_Free_Pkt(pkt);
+ SMBlib_errno = -SMBlibE_RecvFailed; /* Failed, check lower
+ * layer errno */
+ return (SMBlibE_BAD);
+ }
+ if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) {
+ /* Process error */
+#ifdef SMB_DEBUG
+ fprintf(stderr, "SMB_Negotiate failed with errorclass = %i, Error Code = %i\n",
+ CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
+ SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
+#endif
+ SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
+ RFCNB_Free_Pkt(pkt);
+ SMBlib_errno = SMBlibE_Remote;
+ return SMBlibE_BAD;
+ }
+ if (SVAL(SMB_Hdr(pkt), SMB_negrCP_idx_offset) == 0xFFFF) {
+#ifdef SMB_DEBUG
+ fprintf(stderr, "None of our protocols was accepted ... ");
+#endif
+ RFCNB_Free_Pkt(pkt);
+ SMBlib_errno = SMBlibE_NegNoProt;
+ return (SMBlibE_BAD);
+ }
+ /* Now, unpack the info from the response, if any and evaluate the
+ * proto selected. We must make sure it is one we like... */
+ Con_Handle->prot_IDX = prot = SVAL(SMB_Hdr(pkt), SMB_negrCP_idx_offset);
+ Con_Handle->protocol = SMB_Figure_Protocol(Prots, prot);
+
+ if (Con_Handle->protocol == SMB_P_Unknown) { /* No good ... */
+ RFCNB_Free_Pkt(pkt);
+ SMBlib_errno = SMBlibE_ProtUnknown;
+ return SMBlibE_BAD;
+ }
+ switch (CVAL(SMB_Hdr(pkt), SMB_hdr_wct_offset)) {
+ case 0x01: /* No more info ... */
+ break;
+
+ case 13: /* Up to and including LanMan 2.1 */
+ Con_Handle->Security = SVAL(SMB_Hdr(pkt), SMB_negrLM_sec_offset);
+ Con_Handle->encrypt_passwords
+ = ((Con_Handle->Security & SMB_sec_encrypt_mask) != 0x00);
+ Con_Handle->Security = Con_Handle->Security & SMB_sec_user_mask;
+
+ Con_Handle->max_xmit = SVAL(SMB_Hdr(pkt), SMB_negrLM_mbs_offset);
+ Con_Handle->MaxMPX = SVAL(SMB_Hdr(pkt), SMB_negrLM_mmc_offset);
+ Con_Handle->MaxVC = SVAL(SMB_Hdr(pkt), SMB_negrLM_mnv_offset);
+ Con_Handle->Raw_Support = SVAL(SMB_Hdr(pkt), SMB_negrLM_rm_offset);
+ Con_Handle->SessionKey = IVAL(SMB_Hdr(pkt), SMB_negrLM_sk_offset);
+ Con_Handle->SvrTZ = SVAL(SMB_Hdr(pkt), SMB_negrLM_stz_offset);
+ Con_Handle->Encrypt_Key_Len
+ = SVAL(SMB_Hdr(pkt), SMB_negrLM_ekl_offset);
+
+ p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset);
+#ifdef SMB_DEBUG
+ fprintf(stderr, "%s",
+ (char *) (SMB_Hdr(pkt) + SMB_negrLM_buf_offset));
+#endif
+ memcpy(Con_Handle->Encrypt_Key, p, 8);
+
+ p = (SMB_Hdr(pkt) + SMB_negrLM_buf_offset
+ + Con_Handle->Encrypt_Key_Len);
+
+ strncpy(p, Con_Handle->Svr_PDom, sizeof(Con_Handle->Svr_PDom) - 1);
+ break;
+
+ case 17: /* NT LM 0.12 and LN LM 1.0 */
+ Con_Handle->Security = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_sec_offset);
+ Con_Handle->encrypt_passwords
+ = ((Con_Handle->Security & SMB_sec_encrypt_mask) != 0x00);
+ Con_Handle->Security = Con_Handle->Security & SMB_sec_user_mask;
+
+ Con_Handle->max_xmit = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_mbs_offset);
+ Con_Handle->MaxMPX = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_mmc_offset);
+ Con_Handle->MaxVC = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_mnv_offset);
+ Con_Handle->MaxRaw = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_mrs_offset);
+ Con_Handle->SessionKey = IVAL(SMB_Hdr(pkt), SMB_negrNTLM_sk_offset);
+ Con_Handle->SvrTZ = SVAL(SMB_Hdr(pkt), SMB_negrNTLM_stz_offset);
+ Con_Handle->Encrypt_Key_Len = CVAL(SMB_Hdr(pkt),
+ SMB_negrNTLM_ekl_offset);
+
+ p = (SMB_Hdr(pkt) + SMB_negrNTLM_buf_offset);
+ memcpy(Con_Handle->Encrypt_Key, p, 8);
+ p = (SMB_Hdr(pkt) + SMB_negrNTLM_buf_offset
+ + Con_Handle->Encrypt_Key_Len);
+
+ strncpy(p, Con_Handle->Svr_PDom, sizeof(Con_Handle->Svr_PDom) - 1);
+ break;
+
+ default:
+#ifdef SMB_DEBUG
+ fprintf(stderr, "Unknown NegProt response format ... Ignored\n");
+ fprintf(stderr, " wct = %i\n", CVAL(SMB_Hdr(pkt), SMB_hdr_wct_offset));
+#endif
+ break;
+ }
+
+#ifdef SMB_DEBUG
+ fprintf(stderr, "Protocol selected is: %i:%s\n", prot, Prots[prot]);
+#endif
+
+ RFCNB_Free_Pkt(pkt);
+ return 0;
+}
+
+/* Get our hostname */
+static void
+SMB_Get_My_Name(char *name, int len)
+{
+ if (gethostname(name, len) < 0) { /* Error getting name */
+ strncpy(name, "unknown", len);
+
+ /* Should check the error */
+#ifdef SMB_DEBUG
+ fprintf(stderr, "gethostname in SMB_Get_My_Name returned error:");
+ perror("");
+#endif
+ }
+ /* only keep the portion up to the first "." */
+}
diff --git a/daemon/smbval/smblib.inc.c b/daemon/smbval/smblib.inc.c
new file mode 100644
index 0000000..c81dc02
--- /dev/null
+++ b/daemon/smbval/smblib.inc.c
@@ -0,0 +1,380 @@
+/* mod_ntlm file: $Id: smblib.inc.c,v 1.2 2003/02/21 01:55:14 casz Exp $ */
+
+/* UNIX SMBlib NetBIOS implementation
+ *
+ * Version 1.0 SMBlib Routines
+ *
+ * Copyright (C) Richard Sharpe 1996
+ *
+ */
+
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int SMBlib_errno;
+int SMBlib_SMB_Error;
+#define SMBLIB_ERRNO
+#define uchar unsigned char
+#include "smblib-priv.h"
+
+#include "rfcnb.h"
+
+#include <signal.h>
+
+SMB_State_Types SMBlib_State;
+
+/* Initialize the SMBlib package */
+static int
+SMB_Init()
+{
+ SMBlib_State = SMB_State_Started;
+ signal(SIGPIPE, SIG_IGN); /* Ignore these ... */
+
+/* If SMBLIB_Instrument is defines, turn on the instrumentation stuff */
+#ifdef SMBLIB_INSTRUMENT
+ SMBlib_Instrument_Init();
+#endif
+
+ return 0;
+}
+
+/* SMB_Connect_Server: Connect to a server, but don't negotiate protocol */
+/* or anything else ... */
+static SMB_Handle_Type
+SMB_Connect_Server(SMB_Handle_Type Con_Handle,
+ char *server, char *NTdomain)
+{
+ SMB_Handle_Type con;
+ char called[80], calling[80], *address;
+ int i;
+
+ /* Get a connection structure if one does not exist */
+ con = Con_Handle;
+ if (Con_Handle == NULL) {
+ if ((con = (struct SMB_Connect_Def *) malloc(
+ sizeof(struct SMB_Connect_Def))) == NULL) {
+ SMBlib_errno = SMBlibE_NoSpace;
+ return NULL;
+ }
+ }
+ /* Init some things ... */
+
+ strcpy(con->service, "");
+ strcpy(con->username, "");
+ strcpy(con->password, "");
+ strcpy(con->sock_options, "");
+ strcpy(con->address, "");
+ strcpy(con->desthost, server);
+ strcpy(con->PDomain, NTdomain);
+ strcpy(con->OSName, SMBLIB_DEFAULT_OSNAME);
+ strcpy(con->LMType, SMBLIB_DEFAULT_LMTYPE);
+ con->first_tree = con->last_tree = NULL;
+
+ SMB_Get_My_Name(con->myname, sizeof(con->myname));
+
+ con->port = 0; /* No port selected */
+
+ /* Get some things we need for the SMB Header */
+ con->pid = getpid();
+ con->mid = con->pid; /* This will do for now ... */
+ con->uid = 0; /* Until we have done a logon, no uid ... */
+ con->gid = getgid();
+
+ /* Now connect to the remote end, but first upper case the name of
+ * the service we are going to call, sine some servers want it in
+ * uppercase */
+ for (i = 0; i < strlen(server); i++)
+ called[i] = toupper(server[i]);
+
+ called[strlen(server)] = 0; /* Make it a string */
+
+ for (i = 0; i < strlen(con->myname); i++)
+ calling[i] = toupper(con->myname[i]);
+
+ calling[strlen(con->myname)] = 0; /* Make it a string */
+
+ if (strcmp(con->address, "") == 0)
+ address = con->desthost;
+ else
+ address = con->address;
+
+ con->Trans_Connect = RFCNB_Call(called,
+ calling,
+ address, /* Protocol specific */
+ con->port);
+
+ /* Did we get one? */
+ if (con->Trans_Connect == NULL) {
+ if (Con_Handle == NULL) {
+ Con_Handle = NULL;
+ free(con);
+ }
+ SMBlib_errno = -SMBlibE_CallFailed;
+ return NULL;
+ }
+ return (con);
+}
+
+/* Logon to the server. That is, do a session setup if we can. We do
+ * not do Unicode yet! */
+static int
+SMB_Logon_Server(SMB_Handle_Type Con_Handle, char *UserName,
+ char *PassWord, int precrypted)
+{
+ struct RFCNB_Pkt *pkt;
+ int param_len, pkt_len, pass_len;
+ char *p, pword[128];
+
+ /* First we need a packet etc ... but we need to know what
+ * protocol has been negotiated to figure out if we can do it and
+ * what SMB format to use ... */
+ if (Con_Handle->protocol < SMB_P_LanMan1) {
+#ifdef LOG
+ flog("SMB_Logon_Server: bad protocol");
+#endif
+ SMBlib_errno = SMBlibE_ProtLow;
+ return (SMBlibE_BAD);
+ }
+ if (precrypted) {
+ pass_len = 24;
+ memcpy(pword, PassWord, 24);
+ } else {
+ strcpy(pword, PassWord);
+ if (Con_Handle->encrypt_passwords) {
+ pass_len = 24;
+ SMBencrypt((uchar *) PassWord,
+ (uchar *) Con_Handle->Encrypt_Key, (uchar *) pword);
+ } else
+ pass_len = strlen(pword);
+ }
+
+ /* Now build the correct structure */
+ if (Con_Handle->protocol < SMB_P_NT1) {
+#ifdef LOG
+ flog("SMB_Logon_Server: type is LM (%d)", Con_Handle->protocol);
+#endif
+ param_len = strlen(UserName) + 1 + pass_len + 1 +
+ strlen(Con_Handle->PDomain) + 1 +
+ strlen(Con_Handle->OSName) + 1;
+
+ pkt_len = SMB_ssetpLM_len + param_len;
+
+ pkt = (struct RFCNB_Pkt *) RFCNB_Alloc_Pkt(pkt_len);
+
+ if (pkt == NULL) {
+#ifdef LOG
+ flog("SMB_Logon_Server: pkt == NULL");
+#endif
+ SMBlib_errno = SMBlibE_NoSpace;
+ return (SMBlibE_BAD); /* Should handle the error */
+ }
+ bzero(SMB_Hdr(pkt), SMB_ssetpLM_len);
+ SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk
+ * in IDF */
+ *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX;
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle->pid);
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle->mid);
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle->uid);
+ *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 10;
+ *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra
+ * command */
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0);
+
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mbs_offset, SMBLIB_MAX_XMIT);
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_mmc_offset, 2);
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_vcn_offset, Con_Handle->pid);
+ SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_snk_offset, 0);
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_pwl_offset, pass_len + 1);
+ SIVAL(SMB_Hdr(pkt), SMB_ssetpLM_res_offset, 0);
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpLM_bcc_offset, param_len);
+
+ /* Now copy the param strings in with the right stuff */
+ p = (char *) (SMB_Hdr(pkt) + SMB_ssetpLM_buf_offset);
+
+ /* Copy in password, then the rest. Password has a null at end */
+ memcpy(p, pword, pass_len);
+
+ p = p + pass_len + 1;
+
+ strcpy(p, UserName);
+ p = p + strlen(UserName);
+ *p = 0;
+
+ p = p + 1;
+
+ strcpy(p, Con_Handle->PDomain);
+ p = p + strlen(Con_Handle->PDomain);
+ *p = 0;
+ p = p + 1;
+
+ strcpy(p, Con_Handle->OSName);
+ p = p + strlen(Con_Handle->OSName);
+ *p = 0;
+ } else {
+#ifdef LOG
+ flog("SMB_Logon_Server: type is NTLM (%d)", Con_Handle->protocol);
+#endif
+ /* We don't admit to UNICODE support ... */
+ param_len = strlen(UserName) + 1 + pass_len +
+ strlen(Con_Handle->PDomain) + 1 +
+ strlen(Con_Handle->OSName) + 1 +
+ strlen(Con_Handle->LMType) + 1;
+
+ pkt_len = SMB_ssetpNTLM_len + param_len;
+
+ pkt = (struct RFCNB_Pkt *) RFCNB_Alloc_Pkt(pkt_len);
+
+ if (pkt == NULL) {
+#ifdef LOG
+ flog("SMB_Logon_Server: pkt == NULL, second check");
+#endif
+ SMBlib_errno = SMBlibE_NoSpace;
+ return (-1); /* Should handle the error */
+ }
+ bzero(SMB_Hdr(pkt), SMB_ssetpNTLM_len);
+ SIVAL(SMB_Hdr(pkt), SMB_hdr_idf_offset, SMB_DEF_IDF); /* Plunk
+ * in IDF */
+ *(SMB_Hdr(pkt) + SMB_hdr_com_offset) = SMBsesssetupX;
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_pid_offset, Con_Handle->pid);
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_tid_offset, 0);
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_mid_offset, Con_Handle->mid);
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset, Con_Handle->uid);
+ *(SMB_Hdr(pkt) + SMB_hdr_wct_offset) = 13;
+ *(SMB_Hdr(pkt) + SMB_hdr_axc_offset) = 0xFF; /* No extra
+ * command */
+ SSVAL(SMB_Hdr(pkt), SMB_hdr_axo_offset, 0);
+
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mbs_offset, SMBLIB_MAX_XMIT);
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_mmc_offset, 0);
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_vcn_offset, 0);
+ SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_snk_offset, 0);
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cipl_offset, pass_len);
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cspl_offset, 0);
+ SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_res_offset, 0);
+ SIVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_cap_offset, 0);
+ SSVAL(SMB_Hdr(pkt), SMB_ssetpNTLM_bcc_offset, param_len);
+
+ /* Now copy the param strings in with the right stuff */
+ p = (char *) (SMB_Hdr(pkt) + SMB_ssetpNTLM_buf_offset);
+
+ /* Copy in password, then the rest. Password has no null at end */
+ memcpy(p, pword, pass_len);
+
+ p = p + pass_len;
+
+ strcpy(p, UserName);
+ p = p + strlen(UserName);
+ *p = 0;
+
+ p = p + 1;
+
+ strcpy(p, Con_Handle->PDomain);
+ p = p + strlen(Con_Handle->PDomain);
+ *p = 0;
+ p = p + 1;
+
+ strcpy(p, Con_Handle->OSName);
+ p = p + strlen(Con_Handle->OSName);
+ *p = 0;
+ p = p + 1;
+
+ strcpy(p, Con_Handle->LMType);
+ p = p + strlen(Con_Handle->LMType);
+ *p = 0;
+ }
+
+ /* Now send it and get a response */
+ if (RFCNB_Send(Con_Handle->Trans_Connect, pkt, pkt_len) < 0) {
+#ifdef LOG
+ flog("SMB_Logon_Server: Error sending SessSetupX request");
+#endif
+#ifdef SMB_DEBUG
+ fprintf(stderr, "Error sending SessSetupX request\n");
+#endif
+ RFCNB_Free_Pkt(pkt);
+ SMBlib_errno = SMBlibE_SendFailed;
+ return (SMBlibE_BAD);
+ }
+
+ /* Now get the response ... */
+ if (RFCNB_Recv(Con_Handle->Trans_Connect, pkt, pkt_len) < 0) {
+#ifdef LOG
+ flog("SMB_Logon_Server: Error receiving response to SessSetupAndX");
+#endif
+#ifdef SMB_DEBUG
+ fprintf(stderr, "Error receiving response to SessSetupAndX\n");
+#endif
+ RFCNB_Free_Pkt(pkt);
+ SMBlib_errno = SMBlibE_RecvFailed;
+ return (SMBlibE_BAD);
+ }
+ /* Check out the response type ... */
+
+ if (CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset) != SMBC_SUCCESS) {
+ /* Process error */
+#ifdef LOG
+ flog("SMB_Logon_Server: SMB_SessSetupAndX failed; errorclass = %i, Error Code = %i\n",
+ CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
+ SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
+#endif
+#ifdef SMB_DEBUG
+ fprintf(stderr,
+ "SMB_SessSetupAndX failed; errorclass = %i, Error Code = %i\n",
+ CVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset),
+ SVAL(SMB_Hdr(pkt), SMB_hdr_err_offset));
+#endif
+ SMBlib_SMB_Error = IVAL(SMB_Hdr(pkt), SMB_hdr_rcls_offset);
+ RFCNB_Free_Pkt(pkt);
+ SMBlib_errno = SMBlibE_Remote;
+ return (SMBlibE_BAD);
+ }
+/** @@@ mdz: check for guest login { **/
+ if (SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset) & 0x1) {
+ /* do we allow guest login? NO! */
+#ifdef LOG
+ flog("SMB_Logon_Server: no guest login");
+#endif
+ return (SMBlibE_BAD);
+ }
+/** @@@ mdz: } **/
+
+#ifdef SMB_DEBUG
+ fprintf(stderr, "SessSetupAndX response. Action = %i\n",
+ SVAL(SMB_Hdr(pkt), SMB_ssetpr_act_offset));
+#endif
+
+ /* Now pick up the UID for future reference ... */
+ Con_Handle->uid = SVAL(SMB_Hdr(pkt), SMB_hdr_uid_offset);
+ RFCNB_Free_Pkt(pkt);
+
+#ifdef LOG
+ flog("SMB_Logon_Server: login OK");
+#endif
+ return 0;
+}
+
+/* Disconnect from the server, and disconnect all tree connects */
+static int
+SMB_Discon(SMB_Handle_Type Con_Handle, BOOL KeepHandle)
+{
+ /* We just disconnect the connection for now ... */
+ RFCNB_Hangup(Con_Handle->Trans_Connect);
+
+ if (!KeepHandle)
+ free(Con_Handle);
+
+ return 0;
+}
diff --git a/daemon/smbval/std-defines.h b/daemon/smbval/std-defines.h
new file mode 100644
index 0000000..2a25d57
--- /dev/null
+++ b/daemon/smbval/std-defines.h
@@ -0,0 +1,52 @@
+/* mod_ntlm file: $Id: std-defines.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef STD_DEFINES_H
+#define STD_DEFINES_H
+
+/* RFCNB Standard includes ... */
+/*
+ *
+ * SMBlib Standard Includes
+ *
+ * Copyright (C) 1996, Richard Sharpe
+ *
+ */
+/* One day we will conditionalize these on OS types ... */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details. You
+ * should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef BOOL
+#define BOOL int
+#endif
+typedef short int16;
+
+#include <netdb.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#if 0
+#include <strings.h>
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#endif
diff --git a/daemon/smbval/std-includes.h b/daemon/smbval/std-includes.h
new file mode 100644
index 0000000..3759d97
--- /dev/null
+++ b/daemon/smbval/std-includes.h
@@ -0,0 +1,54 @@
+/* mod_ntlm file: $Id: std-includes.h,v 1.3 2003/02/21 01:55:14 casz Exp $ */
+
+#ifndef STD_INCLUDES_H
+#define STD_INCLUDES_H
+
+/* RFCNB Standard includes ... */
+/*
+ *
+ * RFCNB Standard Includes
+ *
+ * Copyright (C) 1996, Richard Sharpe
+ *
+ */
+/* One day we will conditionalize these on OS types ... */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details. You
+ * should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef BOOL
+#define BOOL int
+#endif
+
+#include <netdb.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/* Pick up define for INADDR_NONE */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE -1
+#endif
+
+#endif
diff --git a/doc/httpauthd.conf.5 b/doc/httpauthd.conf.5
index e1a78db..959896a 100644
--- a/doc/httpauthd.conf.5
+++ b/doc/httpauthd.conf.5
@@ -69,6 +69,8 @@ implemented are:
.Bl -hang
.It LDAP
Authenticate against an LDAP server.
+.It NTLM
+Authenticate via NTLM against a Windows Server.
.It MYSQL
Authenticate against a MYSQL database
.It PGSQL
@@ -135,10 +137,10 @@ you're using a certain method twice (eg: LDAP) with different settings. This
option can only be used in a method section.
.It Cd AuthTypes
The allowed HTTP authentication types, separated by spaces. Any combination of:
-.Ar Basic Digest
+.Ar Basic Digest NTLM
.Pp
[ Default:
-.Ar Basic Digest
+.Ar Basic Digest NTLM
]
.It Cd CacheMax
The maximum amount of successful authentication requests a method can cache.
@@ -314,6 +316,44 @@ in the case where anonymous users can't perform LDAP searches, for example.
.Pp
[ Optional ]
.El
+.Sh NTLM METHOD OPTIONS
+Settings for the
+.Em NTLM
+authentication method. This method authenticates users against NT domain
+server.
+.Bl -hang
+.It Cd NTLMBackup
+The backup domain server to authenticate against. Used when
+.Em NTLMServer
+is not available.
+.Pp
+[ Optional ]
+.It Cd NTLMDomain
+The domain which contains the users that will be authenticated. This is
+the NT domain, not the DNS domain.
+.Pp
+[ Required ]
+.It Cd NTLMServer
+The domain server to authenticate against. You should specify a name here
+not an IP address.
+.Pp
+[ Required ]
+.It Cd PendingMax
+The maximum amount of halfway authenticated NTLM connections allowed.
+This corresponds directly to the amount of concurrent connections made to
+.Em NTLMServer
+.Pp
+[ Default:
+.Em 16
+]
+.It Cd PendingTimeout
+The maximum time a halfway authenticated NTLM connection is allowed to
+remain that way (in seconds).
+.Pp
+[ Default:
+.Em 20
+]
+.El
.Sh MYSQL AND PGSQL METHOD OPTIONS
Here are the options for the MYSQL and PGSQL handlers.
.Bl -hang
diff --git a/tools/mkha1.c b/tools/mkha1.c
index b42ec2f..4c09d51 100644
--- a/tools/mkha1.c
+++ b/tools/mkha1.c
@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include <string.h>
#include "compat.h"
#include "buffer.h"