From e593016a80ceee52b6e3244512ff4307f8c208fa Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Wed, 10 May 2006 17:31:32 +0000 Subject: Add NTLM support. --- apache1x/mod_httpauth.c | 15 +- apache2x/Makefile | 38 --- apache2x/Makefile.am | 31 ++ apache2x/mod_httpauth.c | 28 +- apache2x/modules.mk | 4 - common/buffer.c | 1 + common/hash.c | 1 + common/sock_any.c | 6 +- configure.in | 41 ++- daemon/Makefile.am | 18 +- daemon/httpauthd.c | 27 +- daemon/httpauthd.h | 2 + daemon/smbval/byteorder.h | 79 +++++ daemon/smbval/rfcnb-common.h | 37 +++ daemon/smbval/rfcnb-error.h | 50 +++ daemon/smbval/rfcnb-io.h | 30 ++ daemon/smbval/rfcnb-io.inc.c | 292 +++++++++++++++++ daemon/smbval/rfcnb-priv.h | 120 +++++++ daemon/smbval/rfcnb-util.h | 43 +++ daemon/smbval/rfcnb-util.inc.c | 257 +++++++++++++++ daemon/smbval/rfcnb.h | 49 +++ daemon/smbval/session.inc.c | 221 +++++++++++++ daemon/smbval/smbdes.inc.c | 329 ++++++++++++++++++++ daemon/smbval/smbencrypt.inc.c | 76 +++++ daemon/smbval/smblib-common.h | 205 ++++++++++++ daemon/smbval/smblib-priv.h | 672 ++++++++++++++++++++++++++++++++++++++++ daemon/smbval/smblib-util.inc.c | 248 +++++++++++++++ daemon/smbval/smblib.inc.c | 380 +++++++++++++++++++++++ daemon/smbval/std-defines.h | 52 ++++ daemon/smbval/std-includes.h | 54 ++++ doc/httpauthd.conf.5 | 44 ++- tools/mkha1.c | 1 + 32 files changed, 3379 insertions(+), 72 deletions(-) delete mode 100644 apache2x/Makefile create mode 100644 apache2x/Makefile.am delete mode 100644 apache2x/modules.mk create mode 100644 daemon/smbval/byteorder.h create mode 100644 daemon/smbval/rfcnb-common.h create mode 100644 daemon/smbval/rfcnb-error.h create mode 100644 daemon/smbval/rfcnb-io.h create mode 100644 daemon/smbval/rfcnb-io.inc.c create mode 100644 daemon/smbval/rfcnb-priv.h create mode 100644 daemon/smbval/rfcnb-util.h create mode 100644 daemon/smbval/rfcnb-util.inc.c create mode 100644 daemon/smbval/rfcnb.h create mode 100644 daemon/smbval/session.inc.c create mode 100644 daemon/smbval/smbdes.inc.c create mode 100644 daemon/smbval/smbencrypt.inc.c create mode 100644 daemon/smbval/smblib-common.h create mode 100644 daemon/smbval/smblib-priv.h create mode 100644 daemon/smbval/smblib-util.inc.c create mode 100644 daemon/smbval/smblib.inc.c create mode 100644 daemon/smbval/std-defines.h create mode 100644 daemon/smbval/std-includes.h 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 #include +#include + #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 #include #include +#include #include /* ----------------------------------------------------------------------- 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 #include +#include #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 -#include #include #include + +#include +#include #include #include +#include #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 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 +#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 +#include +#include + +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 +#include +#include + +#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 +#include + +static int RFCNB_errno = 0; +static int RFCNB_saved_errno = 0; +#define RFCNB_ERRNO + +#include "std-includes.h" +#include +#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 +#include +#include +#include +#include +#include + +#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 +#include + +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__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 + +#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 +#include +#include + +int SMBlib_errno; +int SMBlib_SMB_Error; +#define SMBLIB_ERRNO +#define uchar unsigned char +#include "smblib-priv.h" + +#include "rfcnb.h" + +#include + +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 +#include +#include +#include +#include +#include +#include +#include +#if 0 +#include +#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 +#include +#include +#include +#include +#include +#include +#include + +#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 #include #include +#include #include "compat.h" #include "buffer.h" -- cgit v1.2.3