Return-Path: Delivered-To: apmail-new-httpd-archive@apache.org Received: (qmail 80776 invoked by uid 500); 27 Apr 2000 10:13:08 -0000 Mailing-List: contact new-httpd-help@apache.org; run by ezmlm Precedence: bulk X-No-Archive: yes Reply-To: new-httpd@apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list new-httpd@apache.org Received: (qmail 80749 invoked from network); 27 Apr 2000 10:13:03 -0000 Message-ID: <7864CE46A3ACD311848B005004EB51A5013AC5CE@msxadv1.host.magwien.gv.at> From: Weber Sylvia To: "'new-httpd@apache.org'" Subject: AW: Announce: NTLM authentication module (source included) Date: Thu, 27 Apr 2000 12:04:19 +0200 MIME-Version: 1.0 X-Mailer: Internet Mail Service (5.5.2650.21) Content-Type: multipart/mixed; boundary="----_=_NextPart_000_01BFB02F.F44B99D0" X-Header-From: Weber Sylvia X-Header-From: Weber Sylvia Errors-To: ADVKOV@exchange.magwien.gv.at X-filter-Id: 5.09 117121233913 X-filter-From: kov@adv.magwien.gv.at X-filter-To: new-httpd@apache.org X-Spam-Rating: locus.apache.org 1.6.2 0/1000/N This message is in MIME format. Since your mail reader does not understand this format, some or all of this message may not be legible. ------_=_NextPart_000_01BFB02F.F44B99D0 Content-Type: multipart/alternative; boundary="----_=_NextPart_001_01BFB02F.F44B99D0" ------_=_NextPart_001_01BFB02F.F44B99D0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Here's the source of my ntlm_module. It would be great if you can test and discuss my solution. I would be = open to implement changes and enhancements.=20 At the moment the documentation should be qualified beta quality, = sorry. Attached are 3 files: mod_auth_ntlm.diff - diff file for apache 1.3.12 readme.txt - my doc :-] PwCheck_1.1.tar.gz - gnuzipped tar of the required PwCheck daemon Sylvia > From: Weber Sylvia [mailto:kov@adv.magwien.gv.at] > Sent: Wednesday, April 26, 2000 1:56 AM >=20 > I have written a module which is capable of doing ntlm=20 > (Windows NT Domain > Controller) style authentication. Here you can use challenge/response > protocol like the combination of IIS and Internet Explorer in=20 > Intranets. >=20 > You can choose two modes: > 1. You use challenge/response mode (truely like IIS).=20 > Now, with a NT > Domain controller, your not asked for username and password,=20 > your Domain > logon is used. > 2. You use normal .htaccess control (basic=20 > authentication), but no > htpasswd is used. Username and password are verified against=20 > the Windows > NT Domain controller. >=20 > This is a normal apache module, with small parts of the samba code. >=20 > Though it's my first time of code or patch contribution I=20 > would be glad to > get some help and testing from people out there. >=20 > I will send the code on request. >=20 > Sylvia=20 >=20 > --- > Sylvia Weber > Municipality of Vienna, Austria >=20 -----Urspr=FCngliche Nachricht----- Von: William A. Rowe, Jr. [mailto:wrowe@lnd.com] Gesendet: Mittwoch, 26. April 2000 16:29 An: new-httpd@apache.org Cc: kov@adv.magwien.gv.at Betreff: RE: Announce: NTLM authentication module A couple of NT folk were looking at this, including myself. We would be very happy to review your submission. One concern that I have is to offer a unix solution to challenge/response = authentication, based on a non-NT password store, as well as offer Win32 solutions as you have described. An ongoing debate has been to offer some Win32 password database = support. Since the NT password store is the obvious solution, this reduces the urgancy of that debate. The module sounds like an execelent contribution in this direction. Thank you for the offer. Any contributions you have to offer can be sent directly to new-httpd list for review and consideration. Bill ------_=_NextPart_001_01BFB02F.F44B99D0 Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable AW: Announce: NTLM authentication module (source = included)

Here's the source of my ntlm_module.
It would be great if you can test and discuss my = solution. I would be open to implement changes and enhancements. =
At the moment the documentation should be qualified = beta quality, sorry.

Attached are 3 files:

mod_auth_ntlm.diff - diff file for apache = 1.3.12
readme.txt - my doc :-]
PwCheck_1.1.tar.gz - gnuzipped tar of the required = PwCheck daemon

Sylvia


> From: Weber Sylvia [mailto:kov@adv.magwien.gv.at]<= /FONT>
> Sent: Wednesday, April 26, 2000 1:56 AM
>
> I have written a module which is capable of = doing ntlm
> (Windows NT Domain
> Controller) style authentication. Here you can = use challenge/response
> protocol like the combination of IIS and = Internet Explorer in
> Intranets.
>
> You can choose two modes:
>       1. You use = challenge/response mode (truely like IIS).
> Now, with a NT
> Domain controller, your not asked for username = and password,
> your Domain
> logon is used.
>       2. You use = normal .htaccess control (basic
> authentication), but no
> htpasswd is used. Username and password are = verified against
> the Windows
> NT Domain controller.
>
> This is a normal apache module, with small = parts of the samba code.
>
> Though it's my first time of code or patch = contribution I
> would be glad to
> get some help and testing from people out = there.
>
> I will send the code on request.
>
> Sylvia
>
> ---
> Sylvia Weber = <kov@adv.magwien.gv.at>
> Municipality of Vienna, Austria
>



-----Urspr=FCngliche Nachricht-----
Von: William A. Rowe, Jr. [mailto:wrowe@lnd.com]
Gesendet: Mittwoch, 26. April 2000 16:29
An: new-httpd@apache.org
Cc: kov@adv.magwien.gv.at
Betreff: RE: Announce: NTLM authentication = module


A couple of NT folk were looking at this, including = myself.

We would be very happy to review your = submission.  One concern that
I have is to offer a unix solution to = challenge/response authentication,
based on a non-NT password store, as well as offer = Win32 solutions as
you have described.

An ongoing debate has been to offer some Win32 = password database support.
Since the NT password store is the obvious solution, = this reduces the
urgancy of that debate.

The module sounds like an execelent contribution in = this direction.
Thank you for the offer.  Any contributions you = have to offer can be
sent directly to new-httpd list for review and = consideration.

Bill

  ------_=_NextPart_001_01BFB02F.F44B99D0-- ------_=_NextPart_000_01BFB02F.F44B99D0 Content-Type: application/octet-stream; name="mod_auth_ntlm.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="mod_auth_ntlm.diff" --- alloc.c.orig Tue Apr 25 11:09:40 2000=0A= +++ alloc.c Tue Apr 25 11:15:36 2000=0A= @@ -1528,6 +1528,64 @@=0A= #define AP_OVERLAP_TABLES_ON_STACK (512)=0A= #endif=0A= =0A= + /* KOV: no duplicates in table */=0A= + =0A= +#if defined(AIX)=0A= + char *strsep (char **, const char *);=0A= +#endif=0A= + =0A= + struct Liste {=0A= + char * wert;=0A= + int len;=0A= + struct Liste * n;=0A= + } ;=0A= +=0A= + struct Liste * trennen (struct Liste *start, char * in, int = *l, pool * p)=0A= + {=0A= + char * zk;=0A= + char * w;=0A= + struct Liste *ll, *neu, *ende, *first;=0A= + zk =3D ap_pstrdup(p, in);=0A= +=0A= + if (start=3D=3DNULL) {=0A= + w =3D strsep (&zk,",");=0A= + while (w[0] =3D=3D ' ') w++;=0A= + first =3D ap_pcalloc (p, sizeof(struct Liste));=0A= + first->n =3D NULL;=0A= + first->wert =3D w;=0A= + first->len =3D strlen(w);=0A= + *l =3D first->len;=0A= + ende =3D first;=0A= + }=0A= + else {=0A= + first =3D start;=0A= + for (ende=3Dfirst; ende->n !=3D NULL; ende =3D = ende->n);=0A= + }=0A= +=0A= + while (zk !=3D NULL) {=0A= + w =3D strsep (&zk,",");=0A= + if (w[0] !=3D '\0') {=0A= + /* kommt w in Liste schon vor ? */=0A= + while (w[0] =3D=3D ' ') w++; /* ,' ' ist = Trennung */=0A= + for (ll =3D first; ll !=3D NULL; ll =3D ll->n) = {=0A= + if (strcasecmp (ll->wert, w) =3D=3D 0) = break;=0A= + }=0A= + if (ll =3D=3D NULL) {=0A= + neu =3D ap_pcalloc (p, sizeof(struct = Liste));=0A= + neu->n=3DNULL;=0A= + neu->wert =3D w;=0A= + neu->len =3D strlen(w);=0A= + ende->n=3Dneu;=0A= + ende=3Dneu;=0A= + *l =3D *l + neu->len + 2;=0A= + }=0A= + }=0A= + }=0A= + return (first);=0A= + }=0A= + /* end Kov */=0A= +=0A= +=0A= API_EXPORT(void) ap_overlap_tables(table *a, const table *b, unsigned = flags)=0A= {=0A= overlap_key cat_keys_buf[AP_OVERLAP_TABLES_ON_STACK];=0A= @@ -1608,32 +1666,36 @@=0A= left =3D right;=0A= }=0A= else {=0A= - char *strp;=0A= - char *value;=0A= - size_t len;=0A= -=0A= - /* Have to merge some headers. Let's re-use the order field,=0A= - * since it's handy... we'll store the length of val there.=0A= - */=0A= - left->order =3D strlen(left->val);=0A= - len =3D left->order;=0A= - do {=0A= - right->order =3D strlen(right->val);=0A= - len +=3D 2 + right->order;=0A= - ++right;=0A= - } while (right < last=0A= - && !strcasecmp(left->key, right->key));=0A= - /* right points one past the last header to merge */=0A= - value =3D ap_palloc(a->a.pool, len + 1);=0A= - strp =3D value;=0A= - for (;;) {=0A= - memcpy(strp, left->val, left->order);=0A= - strp +=3D left->order;=0A= - ++left;=0A= - if (left =3D=3D right) break;=0A= - *strp++ =3D ',';=0A= - *strp++ =3D ' ';=0A= - }=0A= +=0A= + /* kov: no duplicates */=0A= +=0A= + char *strp;=0A= + char *value;=0A= + int len=3D0; =0A= + struct Liste *kette =3D NULL;=0A= +=0A= + /* Have to merge some headers. */ =0A= +=0A= + do {=0A= + ++right; =0A= + } while (right < last && !strcasecmp(left->key, = right->key));=0A= + /* right points one past the last header to merge */=0A= + for (;;) {=0A= + kette =3D trennen (kette, left->val,&len,a->a.pool);=0A= + ++left;=0A= + if (left =3D=3D right) break;=0A= + }=0A= + value =3D ap_palloc(a->a.pool, len + 1);=0A= + strp =3D value;=0A= + for (;kette !=3D NULL; kette =3D kette->n) {=0A= + memcpy(strp, kette->wert, kette->len);=0A= + strp +=3D kette->len;=0A= + if (kette->n !=3D NULL) {=0A= + *strp++ =3D ',';=0A= + *strp++ =3D ' ';=0A= + }=0A= + }=0A= +=0A= *strp =3D 0;=0A= ap_table_addn(a, (left-1)->key, value);=0A= }=0A= --- http_protocol.c.orig Tue Apr 25 11:27:56 2000=0A= +++ http_protocol.c Tue Apr 25 11:34:34 2000=0A= @@ -1373,11 +1373,17 @@=0A= * In other words, don't change this one without checking table_do in = alloc.c.=0A= * It returns true unless there was a write error of some kind.=0A= */=0A= +=0A= API_EXPORT_NONSTD(int) ap_send_header_field(request_rec *r,=0A= - const char *fieldname, const char *fieldval)=0A= -{=0A= - return (0 < ap_rvputs(r, fieldname, ": ", fieldval, CRLF, = NULL));=0A= -}=0A= + const char *fieldname, const char *fieldval)=0A= + {=0A= + char help_fieldname[132];=0A= + if (strcmp(fieldname,"Set-Cookie-NTLM")=3D=3D0) strcpy = (help_fieldname, "set-cookie");=0A= + else strcpy(help_fieldname, fieldname);=0A= + return (0 < ap_bvputs(r->connection->client,=0A= + help_fieldname, ": ", fieldval, "\015\012", NULL));=0A= + }=0A= +=0A= =0A= API_EXPORT(void) ap_basic_http_header(request_rec *r)=0A= {=0A= --- mod_autoindex.c.orig Tue Apr 25 11:37:19 2000=0A= +++ mod_autoindex.c Tue Apr 25 11:36:53 2000=0A= @@ -74,6 +74,8 @@=0A= #include "util_script.h"=0A= #include "fnmatch.h"=0A= =0A= +extern int check_smbaccess (request_rec *r);=0A= +=0A= module MODULE_VAR_EXPORT autoindex_module;=0A= =0A= /****************************************************************=0A= @@ -1715,6 +1717,8 @@=0A= autoindex_config_rec *d;=0A= int allow_opts =3D ap_allow_options(r);=0A= =0A= + int i;=0A= +=0A= d =3D (autoindex_config_rec *) = ap_get_module_config(r->per_dir_config,=0A= &autoindex_module);=0A= =0A= @@ -1734,7 +1738,14 @@=0A= if (r->filename[strlen(r->filename) - 1] !=3D '/') {=0A= r->filename =3D ap_pstrcat(r->pool, r->filename, "/", NULL);=0A= }=0A= - return index_directory(r, d);=0A= +/* KOV: .SMB-ACCESS */=0A= + if ( (r->connection->ap_auth_type) && ((strcmp = (r->connection->ap_auth_type, "NTLM") =3D=3D 0) ||=0A= + (strcmp (r->connection->ap_auth_type, "BasicSMB") = =3D=3D 0))) =0A= + i =3D check_smbaccess (r);=0A= + else i =3D OK;=0A= + if (i =3D=3D OK) return index_directory(r, d);=0A= + else return (i);=0A= + /* end .SMB-ACCESS */=0A= }=0A= else {=0A= ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r,=0A= --- /dev/null Thu Apr 27 11:47:59 2000=0A= +++ ../mod_auth_ntlm.c Wed Apr 26 09:03:16 2000=0A= @@ -0,0 +1,2422 @@=0A= +/*=0A= + * mod_auth_ntlm.c: Apache module for NTLM authentication=0A= + * /=0A= +=0A= +=0A= +=0A= +/*=0A= +This module uses pieces of SAMBA code. =0A= + */=0A= +=0A= +#include "httpd.h"=0A= +#include "http_config.h"=0A= +#include "http_core.h"=0A= +#include "http_log.h"=0A= +#include "http_protocol.h"=0A= +#include "http_conf_globals.h"=0A= +=0A= +#include "alloc.h"=0A= +=0A= +#define DEFAULT_CacheTimeout 3600 =0A= +#define DEFAULT_CacheMaxReq 100=0A= +#define DEFAULT_shm_size 81920=0A= +=0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +#include =0A= +/* #include */=0A= +=0A= +#include =0A= +extern int errno;=0A= +=0A= +#ifndef LINUX=0A= +extern const int sys_nerr;=0A= +#endif=0A= +=0A= +#ifdef LINUX=0A= +int getgrouplist(const char *name, int basegid, int *groups, int = *ngroups);=0A= +#endif=0A= +=0A= +#include "ntlm_constants.h"=0A= +=0A= +int check_smbaccess(request_rec *r);=0A= +void strupper(char *s);=0A= +BOOL username_gleich (char *DBuser, char *LANuser);=0A= +=0A= +#include "SMB_includes.h" =0A= +int smb_read_error =3D 0;=0A= +=0A= +typedef char pstring[1024];=0A= +pstring scope =3D "";=0A= +=0A= +static struct {=0A= + int prot;=0A= + char *name;=0A= + }=0A= +prots[] =3D =0A= + {=0A= + {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},=0A= + {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},=0A= + {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},=0A= + {PROTOCOL_LANMAN1,"LANMAN1.0"},=0A= + {PROTOCOL_LANMAN2,"LM1.2X002"},=0A= + {PROTOCOL_LANMAN2,"Samba"},=0A= + {PROTOCOL_NT1,"NT LM 0.12"},=0A= + {PROTOCOL_NT1,"NT LANMAN 1.0"},=0A= + {-1,NULL}=0A= + };=0A= +=0A= +=0A= +#define authenticated 0=0A= +#define not_authenticated 1=0A= +=0A= +static int my_pid;=0A= +char errstr[MAX_STRING_LEN];=0A= +=0A= +/*=0A= + * Data types for per-dir and server configuration=0A= + */=0A= +typedef struct=0A= +{=0A= + array_header *domains;=0A= + int CacheTimeout;=0A= + int shmkey;=0A= + int shm_size;=0A= + int CacheMaxReq;=0A= + char *default_domain;=0A= +} auth_ntlm_server_config_rec;=0A= +=0A= +typedef struct =0A= +{=0A= + char *auth_grpfile;=0A= + char *auth_usrfile;=0A= + array_header *rdomains;=0A= +} auth_ntlm_dir_config_rec;=0A= +=0A= +typedef struct=0A= +{=0A= + char *name;=0A= + char *pipe;=0A= + char *dc;=0A= + char *Bdc;=0A= +} domain_entry;=0A= +=0A= +typedef struct=0A= +{=0A= + char name[DOMAIN_LEN];=0A= + int domain_idx;=0A= +} rdomain_entry;=0A= +=0A= +static const char *add_default_domain(cmd_parms *cmd, void *dummy, = char *name);=0A= +static const char *add_CacheTimeout(cmd_parms *cmd, void *dummy, char = *timeout);=0A= +static const char *add_CacheMaxReq(cmd_parms *cmd, void *dummy, char = *maxreq);=0A= +static const char *add_domain(cmd_parms *cmd, void *dummy, char = *arg);=0A= +static const char *add_ShmSize(cmd_parms *cmd, void *dummy, char = *size);=0A= +static const char *add_required_domain(cmd_parms *cmd, char = *struct_ptr, char *arg);=0A= +=0A= +static void ntlm_initializer(server_rec *s, pool *p); =0A= +static void *ntlm_create_dir_config (pool *p, char *d);=0A= +static void *ntlm_create_server_config (pool *p, server_rec *s);=0A= +static int ntlm_auth_user (request_rec *r);=0A= +static int ntlm_check_auth(request_rec *r) ;=0A= +static void ntlm_child_init(server_rec *s, pool *p);=0A= +static void ntlm_child_exit(server_rec *s, pool *p);=0A= +=0A= +static const command_rec ntlmauth_cmds[] =3D {=0A= + { "NTLMCacheTimeout", add_CacheTimeout, NULL, RSRC_CONF, TAKE1, = =0A= + "timeout (seconds) for user in Shm" },=0A= + { "NTLMCacheMaxReq", add_CacheMaxReq, NULL, RSRC_CONF, TAKE1, =0A= + "max accesses per user without authentication on = controller" },=0A= + { "NTLMShmSize", add_ShmSize, NULL, RSRC_CONF, TAKE1, =0A= + "Shm size" },=0A= + {"NTLMDomainList", add_domain, NULL, RSRC_CONF, RAW_ARGS, =0A= + "filename (description of domains)" },=0A= + {"NTLMDefaultDomain", add_default_domain, NULL, RSRC_CONF, TAKE1, = =0A= + "default domain" },=0A= + {"NTLMAuthGroupFile", ap_set_file_slot,(void *) = XtOffsetOf(auth_ntlm_dir_config_rec, auth_grpfile), OR_AUTHCFG, = TAKE1,=0A= + "text file containing group names and member user = IDs"},=0A= + {"NTLMAuthUserFile", ap_set_file_slot,(void *) = XtOffsetOf(auth_ntlm_dir_config_rec, auth_usrfile), OR_AUTHCFG, = TAKE1,=0A= + "text file containing user IDs and passwords"},=0A= + {"NTLMrequireDomain", add_required_domain, (void *) = XtOffsetOf(auth_ntlm_dir_config_rec, rdomains), OR_AUTHCFG, RAW_ARGS, = =0A= + "list of domain-names"},=0A= + { NULL }=0A= +};=0A= +=0A= +module MODULE_VAR_EXPORT ntlm_module =3D {=0A= + STANDARD_MODULE_STUFF,=0A= + ntlm_initializer, /* initializer */=0A= + ntlm_create_dir_config, /* dir config creater */=0A= + NULL, /* dir merger --- default is to = override */=0A= + ntlm_create_server_config, /* server config */=0A= + NULL, /* merge server config */=0A= + ntlmauth_cmds, /* command table */=0A= + NULL, /* handlers */=0A= + NULL, /* filename translation */=0A= + ntlm_auth_user, /* check_user_id */=0A= + ntlm_check_auth, /* check auth */=0A= + NULL, /* check access */=0A= + NULL, /* type_checker */=0A= + NULL, /* fixups */=0A= + NULL, /* logger */=0A= + NULL, /* header parser */=0A= + ntlm_child_init, /* child_init */=0A= + ntlm_child_exit, /* child_exit */=0A= + NULL /* post read-request */=0A= +#ifdef EAPI=0A= + ,=0A= + NULL, /* EAPI: add_module */=0A= + NULL, /* EAPI: remove_module */=0A= + NULL, /* EAPI: rewrite_command */=0A= + NULL /* EAPI: new_connection */=0A= +#endif=0A= +};=0A= +=0A= +=0A= +#include "ntlm_shm.h"=0A= +=0A= +#define lock -1=0A= +#define unlock 1=0A= +=0A= +static ShmHeader *shmlist =3D NULL;=0A= +static int shmid =3D -1;=0A= +static int semid =3D -1;=0A= +static ShmKnoten *cur =3D NULL;=0A= +=0A= +BOOL process_exists(int pid) /* check if a process exists */=0A= +{=0A= + return(kill(pid,0) =3D=3D 0 || errno !=3D ESRCH);=0A= +}=0A= +=0A= +=0A= +static BOOL sem_change(int op)=0A= +{=0A= + struct sembuf sb;=0A= + int ret;=0A= +=0A= + sb.sem_num =3D 0;=0A= + sb.sem_op =3D op;=0A= + sb.sem_flg =3D 0;=0A= +=0A= + ret =3D semop(semid, &sb, 1);=0A= + if (ret !=3D 0) sprintf(errstr, "%d# sem_change (%d) failed. %s\n", = my_pid, op, strerror(errno)); =0A= + return (ret =3D=3D 0);=0A= +}=0A= +=0A= +static void *shm_index2addr(int i)=0A= +{ =0A= + return (void *)((char *)shmlist + ShmHeaderSize + = i*ShmKnotenSize);=0A= +}=0A= +=0A= +ShmKnoten * hashed_index (char *name) =0A= +{=0A= +char c;=0A= +int i;=0A= +if (name[0] =3D=3D '\0') return ((ShmKnoten *) shm_index2addr( 0));=0A= +=0A= +c=3D name[(strlen(name)-1)];=0A= +if (c < '0' || c > '9') c =3D '9' + 1; =0A= +i =3D (c - '0')*(shmlist->max_knoten_anz/11);=0A= +return ((ShmKnoten *) shm_index2addr( i));=0A= +}=0A= +=0A= +ShmKnoten * plus1(ShmKnoten * i)=0A= +{ =0A= +if (i->nr =3D=3D (shmlist->max_knoten_anz-1)) return ( (ShmKnoten *) = shm_index2addr(0) );=0A= +else return ( (ShmKnoten *) shm_index2addr(i->nr+1));=0A= +}=0A= +=0A= +ShmKnoten * minus1(ShmKnoten * i)=0A= +{ =0A= +if (i->nr =3D=3D 0) return ( (ShmKnoten *) = shm_index2addr(shmlist->max_knoten_anz-1) );=0A= +else return ( (ShmKnoten *) shm_index2addr( i->nr-1));=0A= +}=0A= +=0A= +void delete_knoten (ShmKnoten * d, request_rec *r);=0A= +=0A= +void ShmClean( int list_timeout, request_rec *r) {=0A= + time_t jetzt =3D time(NULL);=0A= + ShmKnoten *p;=0A= + int i;=0A= +=0A= + p =3D (ShmKnoten *)shm_index2addr(0);=0A= + for (i=3D0; i < shmlist->max_knoten_anz; i++) {=0A= + if ( (p->used =3D=3D True) && (difftime(jetzt, cur->zeit) > = list_timeout)) delete_knoten(p,r);=0A= + p =3D plus1(p);=0A= + }=0A= +}=0A= +=0A= +ShmKnoten * next_free (char * ip, int list_timeout, request_rec *r)=0A= +{=0A= +ShmKnoten * i;=0A= +if (shmlist->knoten_anz =3D=3D shmlist->max_knoten_anz) = ShmClean(list_timeout, r);=0A= +if (shmlist->knoten_anz =3D=3D shmlist->max_knoten_anz) i =3D NULL;=0A= +else {=0A= + i =3D hashed_index(ip);=0A= + while (i->used =3D=3D True) i =3D plus1(i);=0A= + }=0A= +return (i);=0A= +}=0A= +=0A= +void ShmDetach (server_rec *s)=0A= +{=0A= + if (shmlist !=3D NULL) {=0A= + if (shmdt(shmlist) =3D=3D 0) {=0A= + sprintf (errstr, "%d# ntlm_exit: shm detached\n", my_pid);=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s, = errstr);=0A= + shmlist =3D NULL;=0A= + }=0A= + else {=0A= + sprintf(errstr, "%d# ntlm_exit: Failed to shmdt. Error was = %s\n", my_pid, strerror(errno));=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, = errstr);=0A= + }=0A= + }=0A= +}=0A= +=0A= +int ShmRemove (server_rec *s)=0A= +{=0A= + struct shmid_ds *shmbuf;=0A= + int ret;=0A= +=0A= + ShmDetach(s);=0A= + ret =3D shmctl (shmid, IPC_RMID, shmbuf);=0A= + shmid =3D -1;=0A= + if (ret =3D=3D 0) return (OK);=0A= + else {=0A= + sprintf(errstr, "%d# ShmRemove: Can't remove Shm. Error was = %s\n", my_pid, strerror(errno));=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, s, = errstr);=0A= + return (SERVER_ERROR);=0A= + }=0A= +}=0A= +=0A= +=0A= +=0A= +void ShmInit(int size, server_rec *s)=0A= +{ =0A= + int i;=0A= + ShmKnoten *p;=0A= + =0A= + memset (shmlist,'\0', size);=0A= + strcpy((char *) shmlist->start, SHM_START_STRING);=0A= + shmlist->total_size =3D size;=0A= + shmlist->max_knoten_anz =3D (size - = ShmHeaderSize)/ShmKnotenSize;=0A= + shmlist->knoten_anz =3D 0;=0A= + =0A= + p =3D (ShmKnoten *)shm_index2addr(0);=0A= + for (i=3D0; i < shmlist->max_knoten_anz; i++) {=0A= + p->used =3D False;=0A= + p->nr =3D i;=0A= + p =3D plus1(p);=0A= + }=0A= + sprintf(errstr, "%d# Shm initilized for %d users\n", my_pid, = shmlist->max_knoten_anz);=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, s, errstr);=0A= +}=0A= +=0A= +=0A= +BOOL suche_knoten (char *ip, int list_timeout, request_rec *r) { =0A= + BOOL gefunden =3D False;=0A= + time_t jetzt =3D time(NULL);=0A= + ShmKnoten *ende;=0A= + =0A= + if ((cur->used =3D=3D True) && ( strcmp((char *) cur->client_ip, = ip) =3D=3D 0) ) gefunden =3D True;=0A= + else {=0A= + cur =3D hashed_index(ip);=0A= + ende =3D cur;=0A= + }=0A= + =0A= + while (!gefunden) { =0A= + if (cur->used =3D=3D True){ =0A= + if (strcmp((char *) cur->client_ip, ip)=3D=3D0) gefunden = =3D True;=0A= + else { =0A= + if (difftime(jetzt, cur->zeit) > list_timeout) = delete_knoten(cur,r);=0A= + }=0A= + }=0A= + if (!gefunden) {=0A= + cur =3D plus1(cur);=0A= + if (cur =3D=3D ende) break; =0A= + }=0A= + } =0A= + =0A= + if (gefunden && (difftime(jetzt, cur->zeit) > list_timeout)){=0A= + delete_knoten(cur,r);=0A= + gefunden=3DFalse;=0A= + } =0A= + return (gefunden);=0A= +}=0A= +=0A= +BOOL list_search (char *domain, char *user, char *pass, char = *cryptkey, int list_timeout, request_rec *r)=0A= +{ =0A= + BOOL gefunden;=0A= +=0A= + if (!sem_change (lock)) {=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, r, = errstr); =0A= + return (False); =0A= + } =0A= + if ( (gefunden =3D = suche_knoten(r->connection->remote_ip,list_timeout,r ))) {=0A= +=0A= + if ( (user[0] =3D=3D '\000') || (strcasecmp (user, cur->name) = =3D=3D 0 ) ){=0A= + sprintf(errstr, "%d# %s %s %s found in list, = index=3D%d\n",my_pid, cur->domain, user,cur->client_ip,cur->nr);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + memcpy (pass, cur->pw, 24);=0A= + memcpy (cryptkey, cur->cryptkey, 8);=0A= + strcpy ((char *) domain, (const char *) cur->domain);=0A= + if (user[0] =3D=3D '\000') strcpy ((char *) user, (const = char *) cur->name);=0A= + }=0A= + else {=0A= + sprintf(errstr, "%d# %s %s found in list - not %s, = index=3D%d\n",my_pid, cur->client_ip,cur->name,user,cur->nr);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + delete_knoten (cur, r);=0A= + gefunden =3D False;=0A= + }=0A= + }=0A= + if (!sem_change (unlock)) ap_log_rerror(APLOG_MARK, = APLOG_NOERRNO|APLOG_CRIT, r, errstr); =0A= +=0A= + return (gefunden);=0A= + } =0A= +=0A= + void list_delete (request_rec *r)=0A= +{=0A= + int t;=0A= + if (!sem_change (lock)) {=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, r, = errstr); =0A= + return;=0A= + } =0A= + if (suche_knoten(r->connection->remote_ip, t,r)) delete_knoten = (cur, r);=0A= + if (!sem_change (unlock)) ap_log_rerror(APLOG_MARK, = APLOG_NOERRNO|APLOG_CRIT, r, errstr); =0A= +}=0A= + =0A= +=0A= +void list_insert (char *user, char *pass, char *cryptkey, char *dom, = int list_timeout, int max_req, request_rec *r)=0A= +{ =0A= +ShmKnoten * neu;=0A= +=0A= + if (!sem_change (lock)) {=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, r, = errstr); =0A= + return;=0A= + }=0A= + if (suche_knoten(r->connection->remote_ip, list_timeout,r)) {=0A= + =0A= + if (cur->req =3D=3D (max_req -1)) {=0A= + sprintf(errstr, "%d# %s max requests, = index=3D%d\n",my_pid, user,cur->nr);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr);=0A= + delete_knoten(cur,r);=0A= + }=0A= + else if ( !((strcasecmp(cur->name, user) =3D=3D 0) && = (strcasecmp(cur->domain, dom) =3D=3D 0))) {=0A= + sprintf(errstr, "%d# %s user %s\\%s was stored, user = %s\\%s inserted; index=3D%d\n",=0A= + my_pid, cur->client_ip,cur->domain, = cur->name, dom, user, cur->nr);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr);=0A= + strcpy ((char *)cur->name,user);=0A= + memcpy (cur->pw,pass,24); =0A= + memcpy (cur->cryptkey, cryptkey,8); =0A= + strcpy ((char *) cur->domain, dom); =0A= + cur->zeit =3D time(NULL);=0A= + cur->used =3D True;=0A= + cur->req =3D 1;=0A= + } =0A= + else { =0A= + sprintf(errstr, "%d# %s %s access-timestamp modified, = index=3D%d\n",my_pid, user, cur->client_ip, cur->nr);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + cur->zeit =3D time(NULL);=0A= + memcpy (cur->pw,pass,24); =0A= + memcpy (cur->cryptkey, cryptkey,8); =0A= + strcpy ((char *) cur->domain, dom); =0A= + cur->req =3D cur->req + 1;=0A= + }=0A= + }=0A= + else {=0A= + neu =3D next_free(r->connection->remote_ip,list_timeout,r);=0A= + if (neu =3D=3D NULL) {=0A= + sprintf(errstr, "%d# shm full. user %s not = stored\n",my_pid, user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, = errstr);=0A= + }=0A= + else {=0A= + cur =3D neu;=0A= + strcpy ((char *) cur->client_ip, = r->connection->remote_ip);=0A= + strcpy ((char *) cur->name,user);=0A= + memcpy (cur->pw,pass,24); =0A= + memcpy (cur->cryptkey, cryptkey,8); =0A= + strcpy ((char *) cur->domain, dom); =0A= + cur->zeit =3D time(NULL);=0A= + cur->used =3D True;=0A= + cur->req =3D 1;=0A= + sprintf(errstr,"%d# %s %s stored in list, = index=3D%d\n",my_pid, user, cur->client_ip,cur->nr);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr);=0A= + shmlist->knoten_anz ++;=0A= + };=0A= + };=0A= + if (!sem_change (unlock)) ap_log_rerror(APLOG_MARK, = APLOG_NOERRNO|APLOG_CRIT, r, errstr); =0A= + }=0A= +=0A= +void delete_knoten (ShmKnoten * d, request_rec *r)=0A= +{=0A= + sprintf (errstr,"%d# %s %s removed,index=3D%d\n",my_pid, d->name, = d->client_ip,d->nr); =0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, errstr);=0A= + =0A= + bzero (d->name, USERNAME_LEN);=0A= + bzero (d->pw, sizeof (d->pw));=0A= + bzero (d->cryptkey, sizeof(d->cryptkey));=0A= + bzero (d->domain, sizeof(d->domain));=0A= + bzero (d->client_ip, sizeof (d->client_ip));=0A= + d->zeit =3D 0; =0A= + d->req =3D 0;=0A= + d->used =3D False;=0A= + shmlist->knoten_anz --;=0A= +} =0A= +=0A= +=0A= +int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)=0A= +{ /* find the difference in milliseconds between two struct timeval = values */=0A= + return((tvalnew->tv_sec - tvalold->tv_sec)*1000 + =0A= + ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000); =0A= + }=0A= +=0A= +=0A= +static const char basis_64[] =3D =0A= +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; = =0A= +=0A= +char *my_uuencode(pool *a, char *string, int len) =0A= +{ =0A= + int i; =0A= + char *p; =0A= + char *encoded =3D (char *) ap_pcalloc(a, (len+2) / 3 * 4); =0A= + =0A= + p =3D encoded; =0A= + for (i =3D 0; i < len; i +=3D 3) { =0A= + *p++ =3D basis_64[string[i] >> 2]; =0A= + *p++ =3D basis_64[((string[i] & 0x3) << 4) | ((int) (string[i = + 1] & 0xF0) >> 4)]; =0A= + *p++ =3D basis_64[((string[i + 1] & 0xF) << 2) | ((int) = (string[i + 2] & 0xC0) >> 6)]; =0A= + *p++ =3D basis_64[string[i + 2] & 0x3F]; =0A= + } =0A= + *p-- =3D '\0'; =0A= + *p-- =3D '=3D'; =0A= + *p-- =3D '=3D'; =0A= + return encoded; =0A= +}=0A= +=0A= +void strlower(char *s)=0A= +{=0A= + while (*s) {=0A= + if (isupper(*s))=0A= + *s =3D tolower(*s);=0A= + s++;=0A= + }=0A= +}=0A= +=0A= +char *skip_string(char *buf,int n)=0A= +{ /* skip past some strings in a buffer */=0A= + while (n--)=0A= + buf +=3D strlen(buf) + 1;=0A= + return(buf);=0A= +}=0A= +=0A= +ssize_t write_data(int fd,char *buffer,size_t N,request_rec *r)=0A= +{ /* write data to a fd */=0A= + size_t total=3D0;=0A= + ssize_t ret;=0A= + while (total < N) {=0A= + ret =3D write(fd,(const void *)(buffer + total),N - total);=0A= + if (ret =3D=3D -1) {=0A= + =0A= + sprintf(errstr, "%d# write_data: %d%s\n",my_pid, = errno,strerror(errno));=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + =0A= + return -1;=0A= + }=0A= + if (ret =3D=3D 0) return total;=0A= + total +=3D ret;=0A= + }=0A= + return (ssize_t)total;=0A= +}=0A= +=0A= +=0A= +static int pollfd(int fd)=0A= +{=0A= + int r=3D0;=0A= + (void)ioctl(fd, FIONREAD, &r);=0A= + return(r);=0A= +}=0A= +=0A= +int sys_select(int maxfd, fd_set *fds,struct timeval *tval)=0A= +{=0A= + fd_set fds2;=0A= + int counter=3D0;=0A= + int found=3D0;=0A= +=0A= + FD_ZERO(&fds2);=0A= +=0A= + while (1) =0A= + {=0A= + int i;=0A= + for (i=3D0;i0) {=0A= + found++;=0A= + FD_SET(i,&fds2);=0A= + }=0A= + }=0A= +=0A= + if (found) {=0A= + memcpy((void *)fds,(void *)&fds2,sizeof(fds2));=0A= + return(found);=0A= + }=0A= + =0A= + if (tval && tval->tv_sec < counter) return(0);=0A= + sleep(1);=0A= + counter++;=0A= + }=0A= +}=0A= +=0A= +static void msleep(int t)=0A= +{ /* sleep for a specified number of milliseconds */=0A= + int tdiff=3D0;=0A= + struct timeval tval,t1,t2; =0A= + struct timezone tz;=0A= + fd_set fds;=0A= +=0A= + gettimeofday(&t1, &tz);=0A= + gettimeofday(&t2, &tz);=0A= + =0A= + while (tdiff < t) {=0A= + tval.tv_sec =3D (t-tdiff)/1000;=0A= + tval.tv_usec =3D 1000*((t-tdiff)%1000);=0A= + =0A= + FD_ZERO(&fds);=0A= + errno =3D 0;=0A= + sys_select(0,&fds,&tval);=0A= +=0A= + gettimeofday(&t2, &tz);=0A= + tdiff =3D TvalDiff(&t1,&t2);=0A= + }=0A= +}=0A= +=0A= +int smb_len(char *buf)=0A= +{ /* return the length of an smb packet */=0A= + return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );=0A= +}=0A= +=0A= +=0A= +void show_msg(char *buf)=0A= +{ /* show a smb message structure */=0A= + int i;=0A= + int bcc=3D0;=0A= +=0A= + fprintf (stderr, = "size=3D%d\nsmb_com=3D0x%x\nsmb_rcls=3D%d\nsmb_reh=3D%d\nsmb_err=3D%d\ns= mb_flg=3D%d\nsmb_flg2=3D%d\n",=0A= + smb_len(buf),=0A= + (int)CVAL(buf,smb_com),=0A= + (int)CVAL(buf,smb_rcls),=0A= + (int)CVAL(buf,smb_reh),=0A= + (int)SVAL(buf,smb_err),=0A= + (int)CVAL(buf,smb_flg),=0A= + (int)SVAL(buf,smb_flg2));=0A= + = fprintf(stderr,"smb_tid=3D%d\nsmb_pid=3D%d\nsmb_uid=3D%d\nsmb_mid=3D%d\n= smt_wct=3D%d\n",=0A= + (int)SVAL(buf,smb_tid),=0A= + (int)SVAL(buf,smb_pid),=0A= + (int)SVAL(buf,smb_uid),=0A= + (int)SVAL(buf,smb_mid),=0A= + (int)CVAL(buf,smb_wct));=0A= +=0A= + for (i=3D0;i<(int)CVAL(buf,smb_wct);i++) {=0A= + fprintf(stderr,"smb_vwv[%d]=3D%d = (0x%X)\n",i,SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i));=0A= + }=0A= +=0A= + bcc =3D (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));=0A= + fprintf(stderr, "smb_bcc=3D%d\n",bcc); =0A= + }=0A= +=0A= +=0A= +ssize_t write_socket(int fd,char *buf,size_t len,request_rec *r)=0A= +{ /* write to a socket */=0A= + ssize_t ret=3D0;=0A= + ret =3D write_data(fd,buf,len,r);=0A= + return(ret);=0A= +}=0A= +=0A= +void _smb_setlen(char *buf,int len)=0A= +{=0A= + buf[0] =3D 0;=0A= + buf[1] =3D (len&0x10000)>>16;=0A= + buf[2] =3D (len&0xFF00)>>8;=0A= + buf[3] =3D len&0xFF;=0A= +}=0A= +=0A= +void smb_setlen(char *buf,int len)=0A= +{ /* set the length and marker of an smb packet */=0A= + _smb_setlen(buf,len);=0A= + CVAL(buf,4) =3D 0xFF;=0A= + CVAL(buf,5) =3D 'S';=0A= + CVAL(buf,6) =3D 'M';=0A= + CVAL(buf,7) =3D 'B';=0A= +}=0A= +=0A= +int set_message(char *buf,int num_words,int num_bytes,BOOL zero)=0A= +{ /* setup the word count and byte count for a smb message */=0A= + if (zero)=0A= + bzero(buf + smb_size,num_words*2 + num_bytes);=0A= + CVAL(buf,smb_wct) =3D num_words;=0A= + SSVAL(buf,smb_vwv + num_words*2,num_bytes); =0A= + smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);=0A= + return (smb_size + num_words*2 + num_bytes);=0A= +}=0A= +=0A= +=0A= +static void cli_setup_packet(struct cli_state *cli)=0A= +{=0A= + SSVAL(cli->outbuf,smb_pid,cli->pid);=0A= + SSVAL(cli->outbuf,smb_uid,cli->uid);=0A= + SSVAL(cli->outbuf,smb_mid,cli->mid);=0A= + if (cli->protocol > PROTOCOL_CORE) {=0A= + SCVAL(cli->outbuf,smb_flg,0x8);=0A= + SSVAL(cli->outbuf,smb_flg2,0x1);=0A= + }=0A= +}=0A= +=0A= +=0A= +BOOL send_smb(int fd,char *buffer,request_rec *r)=0A= +{ /* send an smb to a fd */=0A= + size_t len;=0A= + size_t nwritten=3D0;=0A= + ssize_t ret;=0A= + len =3D smb_len(buffer) + 4;=0A= +=0A= + while (nwritten < len) {=0A= + ret =3D write_socket(fd,buffer+nwritten,len - nwritten,r);=0A= + if (ret <=3D 0) {=0A= + close(fd); fd=3D-1;=0A= + return (False);=0A= + }=0A= + nwritten +=3D ret;=0A= + }=0A= + return (True);=0A= +}=0A= +=0A= +ssize_t read_data(int fd,char *buffer,size_t N)=0A= +{ /* read data from the client, reading exactly N bytes. */=0A= + ssize_t ret;=0A= + size_t total=3D0; =0A= + =0A= + smb_read_error =3D 0;=0A= + while (total < N) {=0A= + ret =3D read(fd,buffer + total,N - total);=0A= + if (ret =3D=3D 0){=0A= + smb_read_error =3D READ_EOF;=0A= + return 0;=0A= + }=0A= + if (ret =3D=3D -1) {=0A= + smb_read_error =3D READ_ERROR;=0A= + return -1;=0A= + }=0A= + total +=3D ret;=0A= + }=0A= + return (ssize_t)total;=0A= +}=0A= +=0A= +=0A= +=0A= +ssize_t read_with_timeout(int fd,char *buf,size_t mincnt,size_t = maxcnt,unsigned int time_out)=0A= +{=0A= +/*=0A= +read data from a device with a timout in msec.=0A= +mincount =3D if timeout, minimum to read before returning=0A= +maxcount =3D number to be read.=0A= +time_out =3D timeout in milliseconds=0A= +*/=0A= +=0A= + fd_set fds;=0A= + int selrtn;=0A= + ssize_t readret;=0A= + size_t nread =3D 0;=0A= + struct timeval timeout;=0A= +=0A= + /* just checking .... */=0A= + if (maxcnt <=3D 0) return(0);=0A= +=0A= + smb_read_error =3D 0;=0A= +=0A= + /* Blocking read */=0A= + if (time_out <=3D 0) {=0A= + if (mincnt =3D=3D 0) mincnt =3D maxcnt;=0A= + while (nread < mincnt) {=0A= + readret =3D read(fd, buf + nread, maxcnt - nread);=0A= + if (readret =3D=3D 0) {=0A= + smb_read_error =3D READ_EOF;=0A= + return -1;=0A= + }=0A= + if (readret =3D=3D -1) {=0A= + smb_read_error =3D READ_ERROR;=0A= + return -1;=0A= + }=0A= + nread +=3D readret;=0A= + }=0A= + return((ssize_t)nread);=0A= + }=0A= + =0A= + /* Most difficult - timeout read */=0A= + /* If this is ever called on a disk file and =0A= + mincnt is greater then the filesize then=0A= + system performance will suffer severely as =0A= + select always returns true on disk files */=0A= +=0A= + /* Set initial timeout */=0A= + timeout.tv_sec =3D (time_t)(time_out / 1000);=0A= + timeout.tv_usec =3D (long)(1000 * (time_out % 1000));=0A= +=0A= + for (nread=3D0; nread < mincnt; ) =0A= + { =0A= + FD_ZERO(&fds);=0A= + FD_SET(fd,&fds);=0A= + =0A= + selrtn =3D sys_select(fd+1,&fds,&timeout);=0A= +=0A= + /* Check if error */=0A= + if(selrtn =3D=3D -1) {=0A= + /* something is wrong. Maybe the socket is dead? */=0A= + smb_read_error =3D READ_ERROR;=0A= + return -1;=0A= + }=0A= + =0A= + /* Did we timeout ? */=0A= + if (selrtn =3D=3D 0) {=0A= + smb_read_error =3D READ_TIMEOUT;=0A= + return -1;=0A= + }=0A= + =0A= + readret =3D read(fd, buf+nread, maxcnt-nread);=0A= +=0A= + if (readret =3D=3D 0) {=0A= + /* we got EOF on the file descriptor */=0A= + smb_read_error =3D READ_EOF;=0A= + return -1;=0A= + }=0A= +=0A= + if (readret =3D=3D -1) {=0A= + /* the descriptor is probably dead */=0A= + smb_read_error =3D READ_ERROR;=0A= + return -1;=0A= + }=0A= + =0A= + nread +=3D readret;=0A= + }=0A= +=0A= + /* Return the number we got */=0A= + return((ssize_t)nread);=0A= +}=0A= +=0A= +static int smb_buf_ofs(char *buf)=0A= +{ /* return a pointer to the smb_buf data area */=0A= + return (smb_size + CVAL(buf,smb_wct)*2);=0A= +}=0A= +=0A= +char *smb_buf(char *buf)=0A= +{ /* return a pointer to the smb_buf data area */=0A= + return (buf + smb_buf_ofs(buf));=0A= +}=0A= +=0A= +static ssize_t read_smb_length_return_keepalive(int fd,char = *inbuf,unsigned int timeout)=0A= +{=0A= +/*=0A= +read 4 bytes of a smb packet and return the smb length of the = packet=0A= +store the result in the buffer=0A= +the function will return a length of zero on receiving a keepalive = packet.=0A= +timeout is in milliseconds.=0A= +*/=0A= + ssize_t len=3D0;=0A= + int msg_type;=0A= + BOOL ok =3D False;=0A= +=0A= + while (!ok) {=0A= + if (timeout > 0) ok =3D (read_with_timeout(fd,inbuf,4,4,timeout) = =3D=3D 4);=0A= + else ok =3D (read_data(fd,inbuf,4) =3D=3D 4);=0A= + if (!ok) return(-1);=0A= +=0A= + len =3D smb_len(inbuf);=0A= + msg_type =3D CVAL(inbuf,0);=0A= + /* (msg_type =3D=3D 0x85) Got keepalive packet */=0A= + }=0A= + return(len);=0A= +}=0A= +=0A= +BOOL receive_smb(int fd,char *buffer, unsigned int timeout, int = buffer_size)=0A= +{=0A= +/*=0A= + read an smb from a fd. Note that the buffer *MUST* be of size=0A= + cli.bufsize +SAFETY_MARGIN.=0A= + The timeout is in milliseconds. =0A= + This function will return on a=0A= + receipt of a session keepalive packet.=0A= +*/=0A= + ssize_t len,ret;=0A= +=0A= + smb_read_error =3D 0;=0A= +=0A= + bzero(buffer,smb_size + 100);=0A= +=0A= + len =3D read_smb_length_return_keepalive(fd,buffer,timeout);=0A= + if (len < 0)=0A= + return(False);=0A= +=0A= + if (len > buffer_size ) {=0A= + /* Invalid packet length! */=0A= + if (len > buffer_size + (SAFETY_MARGIN/2)) return (False);=0A= + }=0A= +=0A= + if(len > 0) {=0A= + ret =3D read_data(fd,buffer+4,len);=0A= + if (ret !=3D len) {=0A= + smb_read_error =3D READ_ERROR;=0A= + return (False);=0A= + }=0A= + }=0A= + return(True);=0A= +}=0A= +=0A= +=0A= +BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout, int = buffer_size)=0A= +{=0A= +/*=0A= + read an smb from a fd ignoring all keepalive packets. Note that the = buffer =0A= + *MUST* be of size cli.bufsize+SAFETY_MARGIN.=0A= + The timeout is in milliseconds=0A= +=0A= + This is exactly the same as receive_smb except that it never = returns=0A= + a session keepalive packet (just as receive_smb used to do).=0A= + receive_smb was changed to return keepalives as the oplock = processing means this call=0A= + should never go into a blocking read.=0A= +*/=0A= +=0A= + BOOL ret;=0A= + for(;;)=0A= + {=0A= + ret =3D receive_smb(fd, buffer, timeout,buffer_size);=0A= + if(ret =3D=3D False) return ret;=0A= + /* Ignore session keepalive packets. */=0A= + if(CVAL(buffer,0) !=3D 0x85) break;=0A= + }=0A= + return ret;=0A= +}=0A= +=0A= +=0A= +struct hostent *Get_Hostbyname(char *name)=0A= +{=0A= + char *name2 =3D strdup(name);=0A= + struct hostent *ret;=0A= +=0A= + ret =3D gethostbyname(name2);=0A= + if (ret !=3D NULL) {=0A= + free(name2);=0A= + return(ret);=0A= + }=0A= +=0A= + /* try with all lowercase */=0A= + strlower(name2);=0A= + ret =3D gethostbyname(name2);=0A= + if (ret !=3D NULL){=0A= + free(name2);=0A= + return(ret);=0A= + }=0A= +=0A= + /* try with all uppercase */=0A= + strupper(name2);=0A= + ret =3D gethostbyname(name2);=0A= + if (ret !=3D NULL) {=0A= + free(name2);=0A= + return(ret);=0A= + }=0A= + =0A= + /* nothing works :-( */=0A= + free(name2);=0A= + return(NULL);=0A= + }=0A= +=0A= +=0A= +BOOL cli_negprot(struct cli_state *cli, request_rec *r)=0A= +{=0A= + char *p;=0A= + int numprots;=0A= + int plength;=0A= +=0A= + bzero(cli->outbuf,smb_size);=0A= +=0A= + /* setup the protocol strings */=0A= + for (plength=3D0,numprots=3D0;=0A= + prots[numprots].name && = prots[numprots].prot<=3Dcli->protocol;=0A= + numprots++)=0A= + plength +=3D strlen(prots[numprots].name)+2;=0A= + =0A= + set_message(cli->outbuf,0,plength,True);=0A= +=0A= + p =3D smb_buf(cli->outbuf);=0A= + for (numprots=3D0;=0A= + prots[numprots].name && = prots[numprots].prot<=3Dcli->protocol;=0A= + numprots++) {=0A= + *p++ =3D 2;=0A= + strcpy(p,prots[numprots].name);=0A= + p +=3D strlen(p) + 1;=0A= + }=0A= +=0A= + CVAL(cli->outbuf,smb_com) =3D SMBnegprot;=0A= + cli_setup_packet(cli);=0A= +=0A= + CVAL(smb_buf(cli->outbuf),0) =3D 2;=0A= +=0A= + send_smb(cli->fd,cli->outbuf,r);=0A= + if = (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout,cli->bufsize))=0A= + return (False);=0A= +=0A= + if (r->server->loglevel =3D=3D APLOG_DEBUG) {=0A= + fprintf(stderr,"%d cli_negprot:inbuf:\n",my_pid);=0A= + show_msg(cli->inbuf);=0A= + }=0A= +=0A= +=0A= + if (CVAL(cli->inbuf,smb_rcls) !=3D 0 || =0A= + ((int)SVAL(cli->inbuf,smb_vwv0) >=3D numprots)) {=0A= + return(False);=0A= + }=0A= +=0A= + cli->protocol =3D prots[SVAL(cli->inbuf,smb_vwv0)].prot;=0A= +=0A= +=0A= + if (cli->protocol >=3D PROTOCOL_NT1) { =0A= + /* NT protocol */=0A= + cli->sec_mode =3D CVAL(cli->inbuf,smb_vwv1);=0A= + cli->max_xmit =3D IVAL(cli->inbuf,smb_vwv3+1);=0A= + cli->sesskey =3D IVAL(cli->inbuf,smb_vwv7+1);=0A= +/* cli->serverzone =3D SVALS(cli->inbuf,smb_vwv15+1)*60; */=0A= +/* this time arrives in real GMT */=0A= +/* cli->servertime =3D interpret_long_date(cli->inbuf+smb_vwv11+1); = */=0A= + memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);=0A= + if (IVAL(cli->inbuf,smb_vwv9+1) & 1)=0A= + cli->readbraw_supported =3D =0A= + cli->writebraw_supported =3D True; =0A= + } else if (cli->protocol >=3D PROTOCOL_LANMAN1) {=0A= + cli->sec_mode =3D SVAL(cli->inbuf,smb_vwv1);=0A= + cli->max_xmit =3D SVAL(cli->inbuf,smb_vwv2);=0A= + cli->sesskey =3D IVAL(cli->inbuf,smb_vwv6);=0A= + /* cli->serverzone =3D SVALS(cli->inbuf,smb_vwv10)*60; */=0A= + /* this time is converted to GMT by make_unix_date */=0A= + /* cli->servertime =3D make_unix_date(cli->inbuf+smb_vwv8); */=0A= + cli->readbraw_supported =3D ((SVAL(cli->inbuf,smb_vwv5) & 0x1) !=3D = 0);=0A= + cli->writebraw_supported =3D ((SVAL(cli->inbuf,smb_vwv5) & 0x2) !=3D = 0);=0A= + memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);=0A= + } else {=0A= + /* the old core protocol */=0A= + cli->sec_mode =3D 0;=0A= +/* cli->serverzone =3D TimeDiff(time(NULL)); */=0A= + }=0A= +=0A= + return (True);=0A= +}=0A= +=0A= +=0A= +=0A= +=0A= +int name_len( char *s )=0A= +{ /* return the total storage length of a mangled name */=0A= + int len;=0A= +=0A= + /* If the two high bits of the byte are set, return 2. */=0A= + if( 0xC0 =3D=3D (*(unsigned char *)s & 0xC0) )=0A= + return(2);=0A= +=0A= + /* Add up the length bytes. */=0A= + for( len =3D 1; (*s); s +=3D (*s) + 1 )=0A= + {=0A= + len +=3D *s + 1;=0A= + }=0A= +=0A= + return( len );=0A= +} /* name_len */=0A= +=0A= +int vslprintf(char *str, int n, char *format, va_list ap)=0A= +{=0A= + int ret =3D vsnprintf(str, n, format, ap);=0A= + if (ret > n || ret < 0) {=0A= + str[n] =3D 0;=0A= + return -1;=0A= + }=0A= + str[ret] =3D 0;=0A= + return ret;=0A= +}=0A= +=0A= +=0A= + int slprintf(char *str, int n, char *format, ...)=0A= +{=0A= + va_list ap; =0A= + int ret;=0A= + va_start(ap, format);=0A= + ret =3D vslprintf(str,n,format,ap);=0A= + va_end(ap);=0A= + return ret;=0A= +}=0A= +=0A= +=0A= +int name_mangle( char *In, char *Out, char name_typ )=0A= + { /* mangle a name into netbios format=0A= + Note: must be (33 + strlen(scope) + 2) bytes long, at = minimum=0A= + */ =0A= + int i;=0A= + int c;=0A= + int len;=0A= + char buf[20];=0A= + char *p =3D Out;=0A= +=0A= + /* Safely copy the input string, In, into buf[]. */=0A= + (void)memset( buf, 0, 20 );=0A= + if( '*' =3D=3D In[0] )=0A= + buf[0] =3D '*';=0A= + else (void)slprintf( buf, sizeof(buf) - 1, "%-15.15s%c", In, = name_typ);=0A= + =0A= + /* Place the length of the first field into the output buffer. */=0A= + p[0] =3D 32;=0A= + p++;=0A= +=0A= + /* Now convert the name to the rfc1001/1002 format. */=0A= + for( i =3D 0; i < 16; i++ )=0A= + {=0A= + c =3D toupper( buf[i] );=0A= + p[i*2] =3D ( (c >> 4) & 0x000F ) + 'A';=0A= + p[(i*2)+1] =3D (c & 0x000F) + 'A';=0A= + }=0A= + p +=3D 32;=0A= + p[0] =3D '\0';=0A= +=0A= + /* Add the scope string. */=0A= + for( i =3D 0, len =3D 0; NULL !=3D scope; i++, len++ )=0A= + {=0A= + switch( scope[i] )=0A= + {=0A= + case '\0':=0A= + p[0] =3D len;=0A= + if( len > 0 )=0A= + p[len+1] =3D 0;=0A= + return( name_len(Out) );=0A= + case '.':=0A= + p[0] =3D len;=0A= + p +=3D (len + 1);=0A= + len =3D 0;=0A= + break;=0A= + default:=0A= + p[len+1] =3D scope[i];=0A= + break;=0A= + }=0A= + }=0A= +=0A= + return( name_len(Out) );=0A= + } /* name_mangle */=0A= +=0A= +#define COOKIE_NAME "NTLM=3D"=0A= +void set_cookie(request_rec *r, char *wert)=0A= +{=0A= + char *new_cookie;=0A= +=0A= + new_cookie =3D ap_psprintf(r->pool, "%s%s; path=3D/", = COOKIE_NAME,wert);=0A= + ap_table_setn(r->headers_out, "Set-Cookie-NTLM", new_cookie);=0A= + return;=0A= +}=0A= +=0A= +const char *get_cookie(request_rec *r)=0A= +{=0A= + const char *cookie;=0A= + char *wert =3D NULL;=0A= + char *ende;=0A= + char *value;=0A= +=0A= + cookie =3D ap_table_get(r->headers_in, "Cookie");=0A= + if (cookie) {=0A= + value =3D strstr(cookie, COOKIE_NAME);=0A= + if (value) {=0A= + value +=3D strlen(COOKIE_NAME);=0A= + wert =3D ap_pstrdup(r->pool, value);=0A= + ende =3D strchr(wert, ';');=0A= + if (ende) *ende =3D '\0'; /* Ignore anything after a ; = */=0A= + }=0A= + }=0A= + return (wert);=0A= +}=0A= +=0A= +=0A= +=0A= +BOOL cli_session_request(struct cli_state *cli, char *host, int = name_type, char *myname,request_rec *r)=0A= +{ /* send a session request */=0A= + fstring dest;=0A= + char *p;=0A= + int len =3D 4;=0A= + /* send a session request (RFC 1002) */=0A= + =0A= + strcpy(dest,host);=0A= + p =3D strchr(dest,'.');=0A= + if (p) *p =3D 0;=0A= + strcpy(cli->desthost, dest);=0A= + =0A= + /* put in the destination name */=0A= + p =3D cli->outbuf+len;=0A= + name_mangle(dest,p,name_type);=0A= + len +=3D name_len(p);=0A= +=0A= + /* and my name */=0A= + p =3D cli->outbuf+len;=0A= + name_mangle(myname,p,0);=0A= + len +=3D name_len(p);=0A= +=0A= + /* setup the packet length */=0A= + _smb_setlen(cli->outbuf,len);=0A= + CVAL(cli->outbuf,0) =3D 0x81;=0A= +=0A= + send_smb(cli->fd,cli->outbuf,r); /* Sent session request */=0A= +=0A= + if = (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout,cli->bufsize))=0A= + return (False);=0A= +=0A= + if (CVAL(cli->inbuf,0) !=3D 0x82) return (False);=0A= + =0A= + return(True);=0A= +}=0A= +=0A= +=0A= +=0A= +BOOL cli_connect (struct cli_state *cli, int port, char = *local_machine, char *host_name , request_rec *r)=0A= +{ /* open the client sockets */=0A= +=0A= + struct sockaddr_in sock_out;=0A= + int ret;=0A= + int connect_loop =3D 250; /* 250 milliseconds */=0A= + int loops =3D ( LONG_CONNECT_TIMEOUT * 1000) / connect_loop;=0A= + struct hostent *hp;=0A= +=0A= + char * text;=0A= +=0A= + /* create a socket to write to */=0A= + cli->fd =3D socket(PF_INET, SOCK_STREAM, 0);=0A= + if (cli->fd =3D=3D -1) return (False); =0A= + =0A= + bzero((char *)&sock_out,sizeof(sock_out));=0A= + hp =3D Get_Hostbyname(host_name);=0A= + if ((hp !=3D NULL) && (hp->h_addr !=3D NULL)) {=0A= + memcpy((char *)&sock_out.sin_addr,(char *)hp->h_addr,4);=0A= + }=0A= + else {=0A= + close (cli->fd); cli->fd =3D -1;=0A= + return (False);=0A= + }=0A= +=0A= + sock_out.sin_port =3D htons( port );=0A= + sock_out.sin_family =3D PF_INET;=0A= +=0A= +connect_again: =0A= + ret =3D connect(cli->fd,(struct sockaddr = *)&sock_out,sizeof(sock_out));=0A= + if (ret < 0 && (errno =3D=3D EINPROGRESS || errno =3D=3D EALREADY = ||errno =3D=3D EAGAIN) && loops--) {=0A= + msleep(connect_loop);=0A= + goto connect_again;=0A= + }=0A= +=0A= + if (ret < 0 ) {=0A= + if (r->server->loglevel =3D=3D APLOG_DEBUG){=0A= + text =3D inet_ntoa(sock_out.sin_addr);=0A= + sprintf (errstr,"%d# cli_connect: connecting to %s = port:%d %s\n",my_pid, text , port, strerror(errno));=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + }=0A= + close(cli->fd); cli->fd =3D -1; =0A= + return (False);=0A= + }=0A= + /* connected */ =0A= + =0A= + if (!cli_session_request(cli, host_name, 0x20, local_machine,r)) = {=0A= + =0A= + sprintf(errstr,"%d# %s rejected the session\n",my_pid, = cli->desthost);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, errstr); = =0A= +=0A= + if (cli->fd !=3D -1) close(cli->fd); cli->fd =3D -1;=0A= + return (False);=0A= + }=0A= + /* got session */=0A= +=0A= + if (!cli_negprot(cli,r)) {=0A= + =0A= + sprintf(errstr,"%d# %s rejected the negprot\n",my_pid, (char = *)cli->desthost);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, errstr); = =0A= +=0A= + if (cli->fd !=3D -1) close(cli->fd); cli->fd =3D -1;=0A= + return (False);=0A= + }=0A= +=0A= + if (cli->protocol < PROTOCOL_LANMAN2 || !(cli->sec_mode & 1)) {=0A= + =0A= + sprintf (errstr,"%d# %s isn't in user level security = mode\n",my_pid, cli->desthost);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, errstr); = =0A= + =0A= + if (cli->fd !=3D -1) close(cli->fd); cli->fd =3D -1;=0A= + return (False);=0A= + }=0A= +=0A= + =0A= + sprintf(errstr,"%d# cli_connect:password server %s OK\n", my_pid, = host_name);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, errstr); = =0A= +=0A= + return (True);=0A= + }=0A= +=0A= +=0A= +int cli_session_setup( struct cli_state *cli,request_rec *r)=0A= +{ /* send a session setup */=0A= + char *p;=0A= + bzero(cli->outbuf,smb_size);=0A= + set_message(cli->outbuf,13,0,True);=0A= + CVAL(cli->outbuf,smb_com) =3D SMBsesssetupX;=0A= + cli_setup_packet(cli);=0A= + =0A= + CVAL(cli->outbuf,smb_vwv0) =3D 0xFF;=0A= + SSVAL(cli->outbuf,smb_vwv2,cli->bufsize );=0A= + SSVAL(cli->outbuf,smb_vwv3,2);=0A= + SSVAL(cli->outbuf,smb_vwv4,cli->pid);=0A= + SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);=0A= + SSVAL(cli->outbuf,smb_vwv7,24); /* password len */=0A= + /* SSVAL(cli->outbuf,smb_vwv8,ntpasslen); */=0A= + p =3D smb_buf(cli->outbuf);=0A= + memcpy(p,cli->pwd,24); =0A= + p +=3D SVAL(cli->outbuf,smb_vwv7);=0A= + strcpy(p, (const char *) cli->user); strupper(p); p =3D = skip_string(p,1);=0A= + strcpy(p, (const char *) cli->domain); strupper(p); p =3D = skip_string(p,1);=0A= + strcpy(p,"Unix");p =3D skip_string(p,1);=0A= + strcpy(p,"Samba");p =3D skip_string(p,1);=0A= + = set_message(cli->outbuf,13,PTR_DIFF(p,smb_buf(cli->outbuf)),False);=0A= +=0A= +=0A= + if (r->server->loglevel =3D=3D APLOG_DEBUG) {=0A= + fprintf(stderr, "\n %d cli_session_setup - outbuf:\n", = my_pid);=0A= + show_msg(cli->outbuf);=0A= + }=0A= +=0A= + if (!send_smb(cli->fd,cli->outbuf,r)) return -1;=0A= + if = (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout,cli->bufsize)) = return -1;=0A= +=0A= + if (r->server->loglevel =3D=3D APLOG_DEBUG) {=0A= + fprintf(stderr, "\ncli_session_setup - inbuf:\n");=0A= + show_msg(cli->inbuf);=0A= + }=0A= +=0A= + if (CVAL(cli->inbuf,smb_rcls) !=3D 0) return = (CVAL(cli->inbuf,smb_err));=0A= +=0A= + /* use the returned uid from now on */=0A= + cli->uid =3D SVAL(cli->inbuf,smb_uid);=0A= +=0A= + return SMB_SUCCESS;=0A= +}=0A= +=0A= +=0A= +BOOL cli_ulogoff(struct cli_state *cli,request_rec *r)=0A= +{=0A= + bzero(cli->outbuf,smb_size);=0A= + set_message(cli->outbuf,2,0,True);=0A= + CVAL(cli->outbuf,smb_com) =3D SMBulogoffX;=0A= + cli_setup_packet(cli);=0A= + SSVAL(cli->outbuf,smb_vwv0,0xFF);=0A= + SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */=0A= +=0A= + if (!send_smb(cli->fd,cli->outbuf,r)) return (False);=0A= + if = (!client_receive_smb(cli->fd,cli->inbuf,cli->timeout,cli->bufsize)) = return (False);=0A= + return CVAL(cli->inbuf,smb_rcls) =3D=3D 0;=0A= +}=0A= +=0A= +void cli_clear (struct cli_state *c)=0A= +{=0A= + bzero(c->pwd_check,24); =0A= + bzero(c->cryptkey,8); =0A= + bzero(c->pwd,24); =0A= + bzero(c->user,USERNAME_LEN);=0A= + bzero(c->outbuf,smb_size);=0A= + bzero(c->inbuf,smb_size);=0A= + bzero(c->domain, DOMAIN_LEN);=0A= + c->crypt_mode =3D 0;=0A= +}=0A= +=0A= +int domain_check (char *this_domain, array_header *rdomains)=0A= + {=0A= + rdomain_entry *entries, *d;=0A= + int i;=0A= + int domain_idx =3D -1;=0A= +=0A= + entries =3D (rdomain_entry *) rdomains->elts;=0A= + for (i =3D 0; (i < rdomains->nelts); i++) {=0A= + d =3D &entries[i];=0A= + if (strcasecmp (this_domain, d->name) =3D=3D 0) {=0A= + domain_idx =3D d->domain_idx;=0A= + break;=0A= + }=0A= + }=0A= + =0A= + return (domain_idx);=0A= + }=0A= +=0A= +int check_Basic_auth_line (const char *auth_line, request_rec *r, char = *pw, char *default_domain, array_header *rdomains, int *idx)=0A= +{=0A= + char *t, *d;=0A= +=0A= + t =3D ap_uudecode(r->pool, auth_line);=0A= + d =3D ap_getword_nc (r->pool, &t, '\\');=0A= + if (t[0] =3D=3D '\0') {=0A= + t=3Dd;=0A= + d=3Ddefault_domain;=0A= + }=0A= +=0A= + r->connection->user =3D ap_getword_nulls_nc (r->connection->pool, = &t, ':');=0A= + /* Note that this allocation has to be made from = r->connection->pool=0A= + * because it has the lifetime of the connection. The other = allocations=0A= + * are temporary and can be tossed away any time.=0A= + */=0A= +=0A= + /* existence of default_domain checked in child_init */=0A= + =0A= + if ( (*idx =3D domain_check (d, rdomains)) < 0 ){=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "wrong = domain %s, user=3D%s; uri=3D%s", d, r->connection->user,r->uri);=0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + ap_pstrcat(r->pool, "BASIC realm=3D\"", = ap_auth_name(r), "\"", NULL)); =0A= + return AUTH_REQUIRED;=0A= + }=0A= +=0A= + r->connection->ap_auth_type =3D ap_pcalloc(r->pool,9);=0A= + strcpy(r->connection->ap_auth_type,"BasicSMB");=0A= + strcpy (pw, t);=0A= + ap_table_setn(r->subprocess_env, "REMOTE_DOMAIN", d);=0A= + return OK;=0A= +}=0A= +=0A= +#define ntlmDpos_pw 16=0A= +#define ntlmDpos_end 24=0A= +#define ntlmDpos_domain 32=0A= +#define ntlmDpos_pc 48=0A= +#define ntlmDlen_domain 28 /* oder 30 */ =0A= +#define ntlmDlen_user 36 /* oder 38 */=0A= +#define ntlmDlen_pc 44 /* oder 46 */=0A= +=0A= +int get_ntlm_auth_pw(request_rec *r, struct cli_state *c, char *pw, = int list_timeout, array_header *rdomains, =0A= + array_header *domains, char *default_domain, int = *domains_idx) =0A= +{=0A= + const char *auth_line =3D ap_table_get(r->headers_in,=0A= + r->proxyreq ? = "Proxy-Authorization"=0A= + : = "Authorization");=0A= + const char *a, *t, *l, *cookie;=0A= + char *d, *u;=0A= + const char *Agent;=0A= + char *msie;=0A= + char buffer[70];=0A= + char antwort [48];=0A= + char shm_domain[DOMAIN_LEN];=0A= + char client_domain[DOMAIN_LEN];=0A= + int idx;=0A= +=0A= + domain_entry *domain_entries;=0A= + domain_entry *this_domain;=0A= + rdomain_entry *rdomain_entries;=0A= +=0A= + domain_entries =3D (domain_entry *)domains->elts;=0A= + rdomain_entries =3D (rdomain_entry *)rdomains->elts;=0A= + idx =3D rdomain_entries[0].domain_idx;=0A= + this_domain =3D &domain_entries[idx];=0A= + =0A= + if (! ((a =3D ap_auth_type(r)) && ( (strcasecmp(a, "NTLM")=3D=3D0) = || (strcasecmp(a,"BasicSMB")=3D=3D0) || = (strcasecmp(a,"OPTIONAL_NTLM")=3D=3D0)) ) )=0A= + return DECLINED;=0A= +=0A= + Agent =3D ap_table_get(r->headers_in, "User-Agent");=0A= + msie =3D strstr (Agent, "MSIE");=0A= + if (msie =3D=3D NULL) msie =3D strstr (Agent, "Microsoft URL = Control");=0A= + if (msie =3D=3D NULL) msie =3D strstr (Agent, "ADVWSInf");=0A= +=0A= + if ( !ap_auth_name(r) && (strcasecmp(a,"OPTIONAL_NTLM")!=3D0)) = {=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "need = AuthName: %s", r->uri);=0A= + return SERVER_ERROR;=0A= + }=0A= +=0A= + cookie =3D get_cookie(r);=0A= + u =3D (char *)cookie;=0A= + d =3D (char *) strsep (&u, "\\");=0A= + if ( (u !=3D NULL) && (u[0] !=3D '\000') ) {=0A= + strcpy((char *) c->user,u);=0A= + sprintf (errstr, "%d# get_ntlm_auth_pw: cookie-domain=3D%s = cookie-user=3D%s\n", my_pid, c->domain, c->user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + }=0A= + idx =3D -2;=0A= + if ( (d !=3D NULL) && (d[0] !=3D '\000') ) {=0A= + if ((idx=3Ddomain_check(d, rdomains)) > -1) strcpy((char *) = c->domain, d);=0A= + }=0A= +=0A= + if (!auth_line) { =0A= + if ((r->proto_num < HTTP_VERSION(1,1)) || = (r->server->keep_alive =3D=3D0) || (r->proxyreq=3D=3D1) || (idx =3D=3D = -1) ){ =0A= + =0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + = ap_pstrcat(r->pool, "BASIC realm=3D\"", ap_auth_name(r), "\"", = NULL));=0A= + if (r->proto_num < HTTP_VERSION(1,1)) = ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, "HTTP < 1.1 -> = BasicSMB"); =0A= + if (r->server->keep_alive =3D=3D0) = ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "KeepAlive = off -> BasicSMB");=0A= + if (r->proxyreq =3D=3D1) = ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, "kein NTLM am = proxy -> BasicSMB");=0A= + if (idx < 0) ap_log_rerror(APLOG_MARK, = APLOG_NOERRNO|APLOG_DEBUG, r, "cookie-domain not required -> = BasicSMB");=0A= + } =0A= + else if (msie =3D=3D NULL) = ap_table_setn(r->err_headers_out,r->proxyreq ? "Proxy-Authenticate" : = "WWW-Authenticate",=0A= + = ap_pstrcat(r->pool, "BASIC realm=3D\"", ap_auth_name(r), "\"", NULL)); = =0A= + else ap_table_setn(r->err_headers_out, r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate", ap_pstrcat(r->pool, "NTLM", = NULL));=0A= + return AUTH_REQUIRED;=0A= + }=0A= + =0A= + t =3D ap_getword(r->pool, &auth_line, ' ');=0A= + if (strcasecmp(t, "NTLM")) {=0A= + cli_clear (c);=0A= + if (strcasecmp (t, "Basic")) {=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, = "client used wrong authentication scheme: %s", r->uri);=0A= + return AUTH_REQUIRED;=0A= + }=0A= + /* auth_line: Basic */=0A= + if ( (strcasecmp (t, "NTLM") =3D=3D 0) && msie && = (r->connection->keepalives =3D=3D 0)) {=0A= + ap_table_setn(r->err_headers_out, r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + ap_pstrcat (r->pool, "NTLM", NULL));=0A= + return AUTH_REQUIRED;=0A= + }=0A= + /* not NTLM --> fallback BASIC */=0A= + l =3D ap_getword(r->pool, &auth_line,' ');=0A= + return check_Basic_auth_line (l, r, pw, default_domain, = rdomains,domains_idx);=0A= + }=0A= + =0A= + l =3D ap_getword(r->pool, &auth_line,' ');=0A= + =0A= +/*=0A= + if (r->server->loglevel =3D=3D APLOG_DEBUG) {=0A= + t =3D ap_uudecode(r->pool,l);=0A= + sprintf (errstr, "%d# get_ntlm_auth_pw: = auth_line=3D%s\n",my_pid, (char *)t);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + }=0A= +*/=0A= + =0A= + /* l[11] =3D=3D 'B' replies to authorization NTLM =0A= + 'D' browser replies to challenge */ =0A= + if (l[11]=3D=3D'B') {=0A= + /* generate challenge, 401, www-Authenticate=3DNTLM */=0A= +=0A= + c->crypt_mode =3D undefined_crypt; =0A= + =0A= + if (list_search (shm_domain, (char *) c->user , (char *) = c->pwd_check, (char *) c->cryptkey, list_timeout,r)) {=0A= + if ((idx=3Ddomain_check(shm_domain, rdomains)) > -1) {=0A= + sprintf (errstr, "%d# get_ntlm_auth_pw:NTLM Phase B: = list_crypt", my_pid);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, = r, errstr);=0A= + c->crypt_mode =3D list_crypt;=0A= + this_domain =3D &domain_entries[idx];=0A= + strcpy ((char *) c->domain, this_domain->name);=0A= + }=0A= + else {=0A= + list_delete (r);=0A= + } =0A= + }=0A= +=0A= + if ( c->crypt_mode =3D=3D undefined_crypt ){=0A= + sprintf (errstr, "%d# get_ntlm_auth_pw:NTLM Phase B: = dc_crypt", my_pid);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + /* connect zu DC */=0A= + if (!cli_connect(c,SMB_port,r->server->server_hostname, = this_domain->dc,r)) {=0A= + if (this_domain->Bdc !=3D NULL) {=0A= + if = (!cli_connect(c,SMB_port,r->server->server_hostname, = this_domain->Bdc,r)) {=0A= + sprintf (errstr, "%d# get_ntlm_auth_pw: error = connecting password server. dc=3D%s, backup=3D%s\n", =0A= + my_pid, this_domain->dc, = this_domain->Bdc);=0A= + ap_log_rerror(APLOG_MARK, = APLOG_NOERRNO|APLOG_ERR, r, errstr);=0A= + return (SERVER_ERROR);=0A= + }=0A= + }=0A= + else {=0A= + sprintf (errstr, "%d# get_ntlm_auth_pw: error = connecting password server. dc=3D%s\n", my_pid, this_domain->dc);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, = r, errstr);=0A= + return (SERVER_ERROR);=0A= + }=0A= + }=0A= + c->crypt_mode =3D dc_crypt;=0A= + }=0A= + =0A= + bzero(buffer, sizeof(buffer)); =0A= + strcpy (buffer, "NTLMSSP");=0A= + buffer[8]=3D'\002'; =0A= + buffer[12]=3Dstrlen((const char *) c->domain); =0A= + buffer[14]=3Dbuffer[12]; =0A= + buffer[16]=3D'('; /* =3D ascii 40: Position domain - = name */=0A= + buffer[20]=3D'\006'; /* ? */=0A= + buffer[21]=3D'\202'; /* =3D ascii 130 ? */=0A= + buffer[22]=3D'\001'; /* ? */=0A= + memcpy (buffer+24, c->cryptkey,8);=0A= + memcpy (buffer+40, c->domain,8);=0A= + t =3D my_uuencode(r->pool,buffer,47);=0A= + =0A= + bzero(antwort, 70);=0A= + strcpy (antwort, "NTLM ");=0A= + memcpy (antwort+5, t, 64);=0A= + antwort[69] =3D '\0';=0A= +=0A= + ap_table_setn(r->err_headers_out, r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate", ap_pstrcat(r->pool, antwort, = NULL));=0A= + =0A= + return AUTH_REQUIRED;=0A= + }=0A= + =0A= +=0A= + if (l[11]=3D=3D'D'){=0A= +=0A= + t =3D ap_uudecode(r->pool,l);=0A= + r->connection->user =3D ap_pcalloc (r->pool, = t[ntlmDlen_user]);=0A= + memcpy (r->connection->user, t + = (t[ntlmDpos_domain]+t[ntlmDlen_domain]),t[ntlmDlen_user] ) ;=0A= + r->connection->user[ (int) t[ntlmDlen_user]]=3D'\0';=0A= +=0A= + memcpy (client_domain, t + t[ntlmDpos_domain], = t[ntlmDlen_domain]);=0A= + client_domain[(int) t[ntlmDlen_domain]]=3D'\0';=0A= + if ( (c->crypt_mode =3D=3D list_crypt) && (strcasecmp = (client_domain, c->domain) !=3D 0)) {=0A= + list_delete (r);=0A= + sprintf (errstr, "%d# get_ntlm_auth_pw:NTLM Phase D: = wrong domain, client-domain=3D%s, list-domain=3D%s, user=3D%s\n" ,=0A= + my_pid, client_domain, = c->domain,r->connection->user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr);=0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + ap_pstrcat(r->pool, "BASIC = realm=3D\"", ap_auth_name(r), "\"", NULL)); =0A= + return AUTH_REQUIRED;=0A= + }=0A= + if ( (idx =3D domain_check (client_domain, rdomains)) < 0) = {=0A= + sprintf (errstr, "%d# get_ntlm_auth_pw:NTLM Phase D: = wrong domain, client-domain=3D%s, user=3D%s\n" ,=0A= + my_pid, = client_domain,r->connection->user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr);=0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + ap_pstrcat(r->pool, "BASIC = realm=3D\"", ap_auth_name(r), "\"", NULL)); =0A= + return AUTH_REQUIRED;=0A= + }=0A= +=0A= + if (c->crypt_mode =3D=3D dc_crypt) strcpy ((char *)c->user, = r->connection->user); /* check_ntlmsmb needs c->user */=0A= + memcpy (c->pwd, (t + t[ntlmDpos_pw]), 24);=0A= +=0A= + r->connection->ap_auth_type =3D = ap_pcalloc(r->pool,strlen(a));=0A= + strcpy(r->connection->ap_auth_type,a);=0A= + strcpy ((char *) c->domain, client_domain);=0A= +=0A= + sprintf (errstr, "%d# get_ntlm_auth_pw:NTLM phase D = user:%s\n", my_pid, =0A= + r->connection->user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + }=0A= +=0A= + return OK;=0A= + }=0A= +=0A= +=0A= +int get_BasicSMB_auth_pw(request_rec *r, char *pw, char = *default_domain, array_header *rdomains, int * idx)=0A= +{=0A= + const char *auth_line =3D ap_table_get(r->headers_in,=0A= + r->proxyreq ? = "Proxy-Authorization"=0A= + : = "Authorization");=0A= +=0A= + if (!ap_auth_name(r)) {=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "need = AuthName: %s", r->uri);=0A= + return SERVER_ERROR;=0A= + }=0A= +=0A= + if (!auth_line) {=0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + ap_pstrcat(r->pool, "BASIC realm=3D\"", = ap_auth_name(r), "\"", NULL)); =0A= + return AUTH_REQUIRED;=0A= + }=0A= +=0A= + if (strcasecmp(ap_getword(r->pool, &auth_line, ' '), "Basic")) = {=0A= + /* Client tried to authenticate using wrong auth scheme */=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, "client = used wrong authentication scheme: %s", r->uri);=0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + ap_pstrcat(r->pool, "BASIC realm=3D\"", = ap_auth_name(r), "\"", NULL)); =0A= + return AUTH_REQUIRED;=0A= + }=0A= + return (check_Basic_auth_line (auth_line, r, pw, default_domain, = rdomains, idx));=0A= +}=0A= +=0A= +=0A= +int check_ntlmsmb (request_rec *r, struct cli_state *c)=0A= +{=0A= + int ret;=0A= + =0A= + if ( (ret =3D cli_session_setup(c,r)) !=3D SMB_SUCCESS) {=0A= + if (ret !=3D ERRbadpw) {=0A= + sprintf(errstr, "%d# NTLM Auth: Failed for user %s - = password server error: (%d)\n",my_pid, c->user, ret);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, = errstr);=0A= + return (SERVER_ERROR);=0A= + } =0A= +=0A= +=0A= + else {=0A= + sprintf (errstr, "%d# User =3D %s - password = invalid",my_pid, c->user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + }=0A= +=0A= + close (c->fd); c->fd =3D -1;=0A= + return not_authenticated;=0A= + }=0A= +=0A= + /* if logged in as guest then reject */=0A= + if ((SVAL(c->inbuf,smb_vwv2) & 1) !=3D 0) {=0A= + =0A= + sprintf(errstr,"%d# password server %s gave us guest = only\n",my_pid, c->desthost);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, = errstr); =0A= + =0A= + cli_ulogoff(c,r);=0A= + close (c->fd); c->fd =3D -1;=0A= + return(not_authenticated);=0A= + }=0A= +=0A= + cli_ulogoff(c,r);=0A= + close (c->fd); c->fd =3D -1;=0A= + return authenticated;=0A= +}=0A= +=0A= +int retry_writev(int fd, struct iovec *iov, int iovcnt)=0A= +{ =0A= +int n; =0A= +int i; =0A= +int written =3D 0;=0A= +static int iov_max =3D 8192; =0A= +=0A= +for (;;) {=0A= + while (iovcnt && iov[0].iov_len =3D=3D 0) {=0A= + iov++;=0A= + iovcnt--; } =0A= + if (!iovcnt) return written;=0A= + n =3D writev(fd, iov, iovcnt > iov_max ? iov_max : iovcnt);=0A= + if (n =3D=3D -1) { =0A= + if (errno =3D=3D EINVAL && iov_max > 10) {=0A= + iov_max /=3D 2; =0A= + continue; =0A= + }=0A= + if (errno =3D=3D EINTR) continue; =0A= + return -1; =0A= + }=0A= + written +=3D n; =0A= + for (i =3D 0; i < iovcnt; i++) {=0A= + if (iov[i].iov_len > n) {=0A= + iov[i].iov_base =3D (char *)iov[i].iov_base + n;=0A= + iov[i].iov_len -=3D n; =0A= + break; =0A= + }=0A= + n -=3D iov[i].iov_len; =0A= + iov[i].iov_len =3D 0; =0A= + }=0A= + if (i =3D=3D iovcnt) return written; =0A= + }=0A= +}=0A= +=0A= +=0A= +#define TXTLEN 80=0A= +char Text[TXTLEN];=0A= +=0A= +char *Zeit( char tstr[TXTLEN])=0A= + {=0A= + time_t tc;=0A= + struct tm *t;=0A= + tc =3D time(NULL);=0A= + t =3D localtime(&tc);=0A= + strftime(tstr, TXTLEN, "[%d/%b/%Y:%H:%M:%S ", t);=0A= + return (tstr);=0A= + }=0A= +=0A= +=0A= +int smbcheck (char *user_name,const char *user_passwd, request_rec *r, = char *pipe)=0A= +=0A= +{=0A= +=0A= +int s;=0A= +struct sockaddr_un srvaddr;=0A= +int ret;=0A= +struct iovec iov[10];=0A= +static char response[1024]; =0A= +int start, n;=0A= +=0A= +s =3D socket(AF_UNIX, SOCK_STREAM, 0);=0A= +if (s =3D=3D -1) {=0A= +=0A= + sprintf(errstr,"%d# %s%s%s(%d)%s\n",my_pid, Zeit(Text),user_name, = "socket", errno,strerror(errno));=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, errstr);=0A= + return (not_authenticated);=0A= + }=0A= +=0A= +memset((char *)&srvaddr, 0, sizeof(srvaddr)); =0A= +srvaddr.sun_family =3D AF_UNIX;=0A= +=0A= +strcpy(srvaddr.sun_path, pipe);=0A= +=0A= +ret =3D connect(s, (struct sockaddr *)&srvaddr, sizeof(srvaddr));=0A= +if (ret =3D=3D -1) { =0A= + sprintf(errstr,"%d# %s%s\n cannot connect to pwcheck server\n = connect: %s pipe=3D%s\n",my_pid, = Zeit(Text),user_name,strerror(errno),srvaddr.sun_path);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, errstr);=0A= + return (not_authenticated);=0A= + } =0A= +=0A= +iov[0].iov_base =3D user_name;=0A= +iov[0].iov_len =3D strlen(user_name)+1;=0A= +iov[1].iov_base =3D (char *)user_passwd;=0A= +iov[1].iov_len =3D strlen(user_passwd)+1; =0A= +retry_writev(s, iov, 2);=0A= +=0A= +start =3D 0; =0A= +while (start < sizeof(response) - 1) {=0A= + n =3D read(s, response+start, sizeof(response) - 1 - start);=0A= + if (n < 1) break; =0A= + start +=3D n;=0A= + } =0A= +close(s);=0A= + if (start > 1 && !strncmp(response, "OK", 2)) {=0A= +=0A= + =0A= + sprintf(errstr, "%d# %s%s%s", my_pid, Zeit(Text), user_name, " = Password logon succeeded\n");=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, errstr); = =0A= + =0A= + r->connection->ap_auth_type =3D ap_pcalloc(r->pool,9);=0A= + strcpy(r->connection->ap_auth_type,"BasicSMB");=0A= + r->connection->user =3D ap_pcalloc(r->pool, strlen = (user_name));=0A= + strcpy ( r->connection->user, user_name); = strupper(r->connection->user);=0A= + return (authenticated);=0A= + }=0A= +else {=0A= + sprintf(errstr, "%d# %s%s%s",my_pid, Zeit(Text), user_name, " = Password logon NOT succeeded\n");=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, errstr); = =0A= + return (not_authenticated);=0A= + }=0A= +}=0A= +=0A= +static char *fget_pw(request_rec *r, char *user, char *auth_pwfile)=0A= +{=0A= + configfile_t *f;=0A= + char l[MAX_STRING_LEN];=0A= + const char *rpw, *w;=0A= +=0A= + if (!(f =3D ap_pcfg_openfile(r->pool, auth_pwfile))) {=0A= + sprintf(errstr, "%d# Could not open password file: %s\n", = my_pid, auth_pwfile);=0A= + ap_log_rerror(APLOG_MARK, APLOG_ERR, r, errstr);=0A= + return NULL;=0A= + }=0A= + while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {=0A= + if ((l[0] =3D=3D '#') || (!l[0])) continue;=0A= + rpw =3D l;=0A= + w =3D ap_getword(r->pool, &rpw, ':');=0A= + if (!strcmp(user, w)) {=0A= + ap_cfg_closefile(f);=0A= + return ap_getword(r->pool, &rpw, ':');=0A= + }=0A= + }=0A= + ap_cfg_closefile(f);=0A= + return NULL;=0A= +}=0A= +=0A= +BOOL vergleich(uchar *s1, uchar *s2, int len)=0A= +{=0A= + int i =3D 0;=0A= + while ((s1[i] =3D=3D s2[i]) && (i < len)) i++;=0A= + return (i =3D=3D len);=0A= +}=0A= +=0A= +void init_cli(struct cli_state *cli, request_rec *r,char *domain)=0A= +{=0A= + if (cli->initialisiert =3D=3D 0) {=0A= + /* initialise a client structure */=0A= + memset(cli, 0, sizeof(cli));=0A= + cli->fd =3D -1;=0A= + cli->cnum =3D -1;=0A= + cli->pid =3D my_pid;=0A= + cli->mid =3D 1;=0A= + cli->crypt_mode =3D 0;=0A= + cli->uid =3D getuid();=0A= + cli->protocol =3D PROTOCOL_NT1;=0A= + cli->timeout =3D 20000;=0A= + cli->bufsize =3D (0xFFFF);=0A= + cli->max_xmit =3D cli->bufsize - 4;=0A= + strcpy((char *) cli->domain, domain);=0A= + }=0A= + cli->inbuf =3D (char = *)ap_pcalloc(r->connection->pool,cli->bufsize + SAFETY_MARGIN);=0A= + cli->outbuf =3D (char *)ap_pcalloc(r->connection->pool,cli->bufsize = + SAFETY_MARGIN); =0A= + cli->initialisiert =3D 1;=0A= + }=0A= +=0A= +static table *groups_for_user(request_rec *r, char *user, char = *grpfile)=0A= +{=0A= + configfile_t *f;=0A= + table *grps =3D ap_make_table(r->pool, 15);=0A= + pool *sp;=0A= + char l[MAX_STRING_LEN];=0A= + const char *group_name, *ll, *w;=0A= +=0A= + if (!(f =3D ap_pcfg_openfile(r->pool, grpfile))) {=0A= + sprintf(errstr, "%d# Could not open group file: %s, %s\n", = my_pid, grpfile, strerror(errno));=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, = errstr);=0A= + return NULL;=0A= + }=0A= + sp =3D ap_make_sub_pool(r->pool);=0A= + while (!(ap_cfg_getline(l, MAX_STRING_LEN, f))) {=0A= + if ((l[0] =3D=3D '#') || (!l[0])) continue;=0A= + ll =3D l;=0A= + ap_clear_pool(sp);=0A= + group_name =3D ap_getword(sp, &ll, ':');=0A= + while (ll[0]) {=0A= + w =3D ap_getword_conf(sp, &ll);=0A= + if (!strcasecmp(w, user)) {=0A= + ap_table_setn(grps, ap_pstrdup(r->pool, group_name), = "in");=0A= + break;=0A= + }=0A= + }=0A= + }=0A= + ap_cfg_closefile(f);=0A= + ap_destroy_pool(sp);=0A= + return grps;=0A= + }=0A= +=0A= +/**********************************************************************= ****/=0A= +=0A= +static void ntlm_initializer(server_rec *s, pool *p)=0A= +{=0A= +ap_add_version_component("NTLM/2.2");=0A= +}=0A= +=0A= +/**********************************************************************= ****/=0A= +=0A= +static void ntlm_child_init(server_rec *s, pool *p)=0A= +{=0A= +=0A= + key_t semkey;=0A= + BOOL neu =3D False;=0A= + int pid;=0A= + union semun su;=0A= + struct semid_ds sem_ds;=0A= + int i;=0A= + array_header *domains;=0A= + domain_entry *entries;=0A= + domain_entry *d;=0A= +=0A= + auth_ntlm_server_config_rec *sc_rec =3D (auth_ntlm_server_config_rec = *) ap_get_module_config(s->module_config, &ntlm_module);=0A= + =0A= + my_pid =3D getpid();=0A= + =0A= + if (s->loglevel =3D=3D APLOG_DEBUG) {=0A= + /* sleep (120); */=0A= + fprintf (stderr,"%d# ntlm_child_init: = server_config-addr=3D%ld\n",my_pid, (long)sc_rec);=0A= + =0A= + fprintf (stderr," CacheTimeout=3D%d\n", = sc_rec->CacheTimeout);=0A= + fprintf (stderr," shmkey=3D%d\n", sc_rec->shmkey);=0A= + fprintf (stderr," shm_size=3D%d\n", sc_rec->shm_size);=0A= + fprintf (stderr," CacheMaxReq=3D%d\n", = sc_rec->CacheMaxReq);=0A= + fprintf (stderr," default domain=3D%s\n", = sc_rec->default_domain);=0A= + =0A= + domains =3D sc_rec->domains; =0A= + entries =3D (domain_entry *) domains->elts;=0A= + for (i =3D 0; i < domains->nelts; i++) {=0A= + d =3D &entries[i];=0A= + fprintf (stderr," domain:%s\n", d->name); =0A= + fprintf (stderr," pipe=3D%s\n", d->pipe);=0A= + fprintf (stderr," dc=3D%s\n", d->dc);=0A= + fprintf (stderr," Bdc=3D%s\n", d->Bdc); =0A= + }=0A= + };=0A= +=0A= + if (sc_rec->default_domain =3D=3D NULL) {=0A= + sprintf (errstr, "%d# ntlm_child_init: NTLMDefaultDomain not = defined\n", my_pid);=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, = errstr);=0A= + exit (1);=0A= + }=0A= +=0A= + if (sc_rec->shmkey =3D=3D -1) sc_rec->shmkey =3D ftok = (ap_server_confname, 13) ;=0A= + semkey =3D sc_rec->shmkey + 2 ;=0A= +=0A= + /* first the semaphore */=0A= + semid =3D semget(semkey,0,0); =0A= + if (semid =3D=3D -1) { =0A= + semid =3D semget(semkey, 1, IPC_CREAT| 0600);=0A= + if (semid !=3D -1) neu =3D True;=0A= + }=0A= + if (semid =3D=3D -1) {=0A= + sprintf (errstr, "%d# ntlm_child_init: Can't create or use = semaphore. Error was %s\n", my_pid, strerror(errno));=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, = errstr);=0A= + exit (1);=0A= + }=0A= +=0A= + if (neu =3D=3D True) { =0A= + su.val =3D 1;=0A= + if (semctl(semid,0, SETVAL, su) !=3D 0) {=0A= + sprintf(errstr, "%d# ntlm_child_init: Failed to init = semaphore. Error was %s\n", my_pid, strerror(errno));=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, = errstr);=0A= + exit (1);=0A= + }=0A= + =0A= + sprintf (errstr,"%d# ntlm_child_init: new semaphore %d\n", = my_pid, semid);=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s, = errstr);=0A= + }=0A= + else {=0A= + if (semctl(semid, 0, GETVAL, su) =3D=3D 0 && = !process_exists((pid=3Dsemctl(semid, 0, GETPID, su)))) {=0A= + sprintf(errstr, "%d# ntlm_child_init: clearing IPC lock set = by dead process %d\n", my_pid, pid);=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, s, = errstr);=0A= + su.val =3D 1;=0A= + if (semctl(semid, 0, SETVAL, su) !=3D 0) {=0A= + sprintf(errstr, "%d# ntlm_child_init: ERROR: Failed to = clear lock. Error was %s\n",my_pid, strerror(errno));=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, = errstr);=0A= + exit (1);=0A= + }=0A= + }=0A= + }=0A= +=0A= + su.buf =3D &sem_ds;=0A= + if (semctl(semid, 0, IPC_STAT, su) !=3D 0) {=0A= + sprintf(errstr,"%d# ntlm_child_init semctl: can't IPC_STAT. Error = was %s\n", my_pid, strerror(errno));=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, errstr); = =0A= + exit(1);=0A= + }=0A= + if (sem_ds.sem_perm.uid !=3D ap_user_id) {=0A= + if (neu =3D=3D False) {=0A= + sprintf(errstr,"%d# ntlm_child_init:semaphore uid=3D%d = changed to uid=3D%d\n",my_pid, sem_ds.sem_perm.uid, ap_user_id) ;=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, s, = errstr);=0A= + }=0A= + sem_ds.sem_perm.uid =3D ap_user_id;=0A= + if (semctl(semid,0, IPC_SET, su) !=3D 0) {=0A= + sprintf(errstr, "%d# ntlm_child_init - semctl IPC_SET Error = was: %s\n", my_pid, strerror(errno));=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, = errstr);=0A= + exit (1);=0A= + }=0A= + } =0A= + =0A= + /* Shm */=0A= + neu =3D True;=0A= + if (!sem_change (lock)) {=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, = errstr);=0A= + exit(1);=0A= + } =0A= + =0A= + /* Try to use an existing key. Note that in order to use an existing = key successfully size must be zero else shmget returns EINVAL. */ =0A= + shmid =3D shmget(sc_rec->shmkey, 0, 0);=0A= + if (shmid !=3D -1) {=0A= + shmlist =3D (ShmHeader *)shmat(shmid, 0, 0);=0A= + if ((long)shmlist =3D=3D -1) {=0A= + sprintf(errstr, "%d# ntlm_child_init: Can't attach to IPC = area. Error was %s\n", my_pid, strerror(errno));=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, = errstr);=0A= + if (!sem_change(unlock)) ap_log_error(APLOG_MARK, = APLOG_NOERRNO|APLOG_CRIT, s, errstr);=0A= + exit(1);=0A= + }=0A= + /* size changed ? */=0A= + if (shmlist->total_size !=3D sc_rec->shm_size) {=0A= + sprintf(errstr, "%d# ntlm_child_init: new shm-size =3D %d, = shm removed and then created again\n",my_pid, sc_rec->shm_size);=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, s, = errstr);=0A= + if (ShmRemove(s) !=3D OK) {=0A= + if (!sem_change(unlock)) ap_log_error(APLOG_MARK, = APLOG_NOERRNO|APLOG_CRIT, s, errstr);=0A= + exit (1);=0A= + }=0A= + }=0A= + else {=0A= + neu =3D False;=0A= + if (!sem_change (unlock)) ap_log_error(APLOG_MARK, = APLOG_NOERRNO|APLOG_CRIT, s, errstr);=0A= + }=0A= + }=0A= +=0A= + /* if that failed then create one */=0A= +=0A= + if (shmid =3D=3D -1) shmid =3D shmget(sc_rec->shmkey, = sc_rec->shm_size, IPC_CREAT | SHM_R | SHM_W);=0A= + if (shmid =3D=3D -1) {=0A= + sprintf(errstr, "%d# ntlm_child_init: Can't create or use IPC = area. Error was %s\n", my_pid, strerror(errno));=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, = errstr);=0A= + sprintf (errstr,"%d# ntlm_child_init: shm_size=3D%d\n",my_pid, = sc_rec->shm_size);=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, s, = errstr);=0A= + if (!sem_change (unlock)) ap_log_error(APLOG_MARK, = APLOG_NOERRNO|APLOG_CRIT, s, errstr);=0A= + exit(1);=0A= + }=0A= + =0A= + if (neu) {=0A= + shmlist =3D (ShmHeader *)shmat(shmid, 0, 0);=0A= + if ((long)shmlist =3D=3D -1) {=0A= + sprintf(errstr, "%d# ntlm_child_init: Can't attach to IPC = area. Error was %s\n",my_pid, strerror(errno));=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_CRIT, s, = errstr);=0A= + if (!sem_change (unlock)) ap_log_error(APLOG_MARK, = APLOG_NOERRNO|APLOG_CRIT, s, errstr);=0A= + exit (1);=0A= + }=0A= + ShmInit( sc_rec->shm_size, s);=0A= + if (!sem_change (unlock)) ap_log_error(APLOG_MARK, = APLOG_NOERRNO|APLOG_CRIT, s, errstr);=0A= + }=0A= +=0A= + cur =3D (ShmKnoten *) shm_index2addr(0); =0A= + =0A= +}=0A= +=0A= +int get_domain_idx (array_header *domains, char *arg)=0A= +{=0A= + domain_entry *entries, *domain;=0A= + int i ;=0A= + int ret =3D -1;=0A= + =0A= + entries =3D (domain_entry *) domains->elts;=0A= + for (i =3D 0; i < (domains->nelts) && (ret =3D=3D -1); i++) {=0A= + domain =3D &entries[i];=0A= + if (strcasecmp (domain->name, arg) =3D=3D 0) ret =3D i;=0A= + }=0A= + return (ret);=0A= +}=0A= +=0A= +/*=0A= + * Creators for per-dir and server configurations=0A= + */=0A= +=0A= +static const char *add_ShmSize(cmd_parms *cmd, void *dummy, char = *shm_size)=0A= +{=0A= + auth_ntlm_server_config_rec *sc_rec;=0A= +=0A= + sc_rec =3D ap_get_module_config( cmd->server->module_config, = &ntlm_module);=0A= + sc_rec->shm_size =3D atoi(shm_size);=0A= +=0A= + printf(errstr,"%d# add_ShmSize:%d\n",my_pid, = sc_rec->shm_size);=0A= + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, = cmd->server, errstr);=0A= + =0A= + return NULL;=0A= +}=0A= +=0A= +static const char *add_default_domain(cmd_parms *cmd, void *dummy, = char *name)=0A= +{=0A= + auth_ntlm_server_config_rec *sc_rec;=0A= +=0A= + sc_rec =3D ap_get_module_config( cmd->server->module_config, = &ntlm_module);=0A= + sc_rec->default_domain =3D name;=0A= + return NULL;=0A= +}=0A= +static const char *add_domain(cmd_parms *cmd, void *dummy, char = *filename)=0A= +{=0A= + auth_ntlm_server_config_rec *sc_rec;=0A= + FILE *fp =3D NULL;=0A= + char line[LINELEN+1];=0A= + domain_entry *new;=0A= + char *domain_name, *l;=0A= +=0A= + sc_rec =3D ap_get_module_config( cmd->server->module_config, = &ntlm_module);=0A= + =0A= + if (!ap_os_is_path_absolute (filename)) filename =3D = ap_make_full_path(cmd->pool, ap_server_root, filename);=0A= + if ((fp=3Dfopen(filename,"r"))=3D=3DNULL) { =0A= + sprintf(errstr, "NTLMDomainList: fopen failed (%s), file = =3D %s", strerror(errno), filename);=0A= + return errstr; =0A= + }=0A= +=0A= + rewind(fp);=0A= + while (fgets(line,LINELEN,fp)!=3DNULL) {=0A= + l=3Dline;=0A= + domain_name =3D ap_getword_conf_nc(cmd->pool, &l);=0A= + if ( (domain_name[0] =3D=3D '\0') || (domain_name[0] = =3D=3D '#')) continue;=0A= + new =3D ap_push_array (sc_rec->domains);=0A= + new -> name =3D domain_name;=0A= + new -> pipe =3D ap_getword_conf_nc(cmd->pool, &l);=0A= + if ( new->pipe[0] =3D=3D '\0') return = ap_pstrcat(cmd->pool, "NTMLDomain ", domain_name, ": pipename missing! = (filename:", =0A= + = filename, ")", NULL); =0A= + new -> dc =3D ap_getword_conf_nc(cmd->pool, &l);=0A= + if ( new->dc[0] =3D=3D '\0') return = ap_pstrcat(cmd->pool, "NTMLDomain ", domain_name, ": NTLMDomain dc-name = missing! (filename:",=0A= + = filename, ")", NULL); =0A= + new -> Bdc =3D ap_getword_conf_nc(cmd->pool, &l);=0A= + if (new->Bdc[0] =3D=3D '\0') new->Bdc =3D NULL;=0A= + }=0A= + =0A= + fclose (fp);=0A= + return NULL;=0A= +}=0A= +=0A= +static const char * add_required_domain(cmd_parms *cmd, char = *struct_ptr, char *arg)=0A= +{=0A= + auth_ntlm_server_config_rec *sc_rec =3D ap_get_module_config( = cmd->server->module_config, &ntlm_module);=0A= + int offset =3D (int) (long) cmd->info;=0A= + rdomain_entry *new;=0A= + char *d; =0A= +=0A= + while ( *arg && (d=3Dap_getword_conf_nc (cmd->pool, &arg )) ){=0A= + new =3D ap_push_array(*(array_header **) (struct_ptr + = offset));=0A= + strcpy (new->name, d);=0A= + new->domain_idx =3D get_domain_idx (sc_rec->domains, d);=0A= + if (new->domain_idx =3D=3D -1) {=0A= + sprintf(errstr,"%d# add_required_domain: no parameters for = required domain %s\n", my_pid, arg); =0A= + return errstr;=0A= + }=0A= + }=0A= + =0A= + return NULL;=0A= +}=0A= +=0A= +=0A= +static const char *add_CacheTimeout(cmd_parms *cmd, void *dummy, char = *timeout)=0A= +{=0A= + auth_ntlm_server_config_rec *sc_rec;=0A= +=0A= +=0A= + sc_rec =3D ap_get_module_config( cmd->server->module_config, = &ntlm_module);=0A= + sc_rec->CacheTimeout =3D atoi(timeout);=0A= + return NULL;=0A= +}=0A= +=0A= +static const char *add_CacheMaxReq(cmd_parms *cmd, void *dummy, char = *maxreq)=0A= +{=0A= + auth_ntlm_server_config_rec *sc_rec;=0A= +=0A= + sc_rec =3D ap_get_module_config( cmd->server->module_config, = &ntlm_module);=0A= + sc_rec->CacheMaxReq =3D atoi(maxreq);=0A= + return NULL;=0A= +}=0A= +=0A= +static void *ntlm_create_dir_config (pool *p, char *d)=0A= +{=0A= + auth_ntlm_dir_config_rec *c;=0A= + c =3D ap_pcalloc (p, sizeof(auth_ntlm_dir_config_rec));=0A= + c->auth_usrfile =3D NULL;=0A= + c->auth_grpfile =3D NULL;=0A= + c->rdomains =3D ap_make_array(p, 1, sizeof(rdomain_entry));=0A= + return c;=0A= +}=0A= +=0A= +=0A= +static void *ntlm_create_server_config (pool *p, server_rec *s)=0A= +{=0A= +=0A= + auth_ntlm_server_config_rec *c;=0A= + =0A= + c =3D ap_pcalloc (p, sizeof(auth_ntlm_server_config_rec));=0A= + c->domains =3D ap_make_array(p, 2, sizeof(domain_entry));=0A= + c->CacheTimeout =3D DEFAULT_CacheTimeout;=0A= + c->CacheMaxReq =3D DEFAULT_CacheMaxReq;=0A= + c->shm_size =3D DEFAULT_shm_size;=0A= + c->shmkey =3D -1;=0A= + c->default_domain =3D NULL;=0A= + return (void *)c;=0A= + }=0A= +=0A= +static int ntlm_auth_user (request_rec *r)=0A= +{=0A= + auth_ntlm_server_config_rec *server_config_rec = =3D(auth_ntlm_server_config_rec *)ap_get_module_config = (r->server->module_config, &ntlm_module);=0A= + auth_ntlm_dir_config_rec *dir_config_rec =3D(auth_ntlm_dir_config_re= c *)ap_get_module_config (r->per_dir_config,&ntlm_module);=0A= +=0A= + int res, code;=0A= + conn_rec *c =3D r->connection;=0A= + fstring pw;=0A= + const char *t;=0A= + static struct cli_state cli;=0A= + char *real_pw, *invalid_pw;=0A= + rdomain_entry *new;=0A= + int idx;=0A= + domain_entry *entries;=0A= + rdomain_entry *rentries;=0A= + =0A= + /* user allready authenticated */=0A= + if (strcmp(r->protocol, "INCLUDED") =3D=3D 0) {return OK; }=0A= + else if (r->connection->user) {return OK;}=0A= +=0A= + if (dir_config_rec->rdomains->nelts =3D=3D 0) {=0A= + new =3D ap_push_array (dir_config_rec->rdomains);=0A= + strcpy (new -> name, server_config_rec->default_domain);=0A= + new->domain_idx =3D get_domain_idx (server_config_rec->domains, = new -> name);=0A= + if (new->domain_idx =3D=3D -1) {=0A= + sprintf(errstr,"%d# ntlm_auth_user: no parameters for default = domain %s\n", my_pid, new->name); =0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, = errstr); =0A= + return (SERVER_ERROR);=0A= + }=0A= + }=0A= + =0A= + entries =3D (domain_entry *) server_config_rec->domains->elts;=0A= + rentries =3D (rdomain_entry *) dir_config_rec->rdomains->elts; = =0A= +=0A= + if ( (t =3D ap_auth_type(r)) ) {=0A= +=0A= + if ( (strcasecmp(t,"OPTIONAL_NTLM")=3D=3D0) && =0A= + ( (r->proto_num < HTTP_VERSION(1,1)) || = (r->server->keep_alive =3D=3D0) || (r->proxyreq=3D=3D1) || =0A= + ( strstr(ap_table_get(r->headers_in, "User-Agent"), = "MSIE") =3D=3D NULL) )) {=0A= + ap_table_setn(r->subprocess_env, "AUTH_STAT", = "NOT_NTLM");=0A= + ap_table_setn(r->subprocess_env, "AUTH_TYPE", = "OPTIONAL_NTLM");=0A= + return OK;=0A= + }=0A= +=0A= + if ((strcasecmp(t, "NTLM")=3D=3D0) || (strcasecmp(t, = "OPTIONAL_NTLM")=3D=3D0)){=0A= +=0A= + = init_cli(&cli,r,rentries[dir_config_rec->rdomains->nelts-1].name);=0A= + =0A= + /* Get the password, exit if can't get */=0A= + if ((res =3D get_ntlm_auth_pw (r,&cli, pw, = server_config_rec->CacheTimeout, dir_config_rec->rdomains, = server_config_rec->domains,=0A= + = server_config_rec->default_domain, &idx))) return res;=0A= + }=0A= + else if (strcasecmp(t,"BasicSMB")=3D=3D0) {=0A= + if ((res =3D get_BasicSMB_auth_pw (r, pw, = server_config_rec->default_domain, dir_config_rec->rdomains, &idx))) = return res;=0A= + }=0A= + else return DECLINED;=0A= + }=0A= + else return DECLINED;=0A= +=0A= + if (!strcasecmp(c->ap_auth_type,"BasicSMB")){=0A= + if (c->user[0] =3D=3D '\0') {=0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + = ap_pstrcat(r->pool, "BASIC realm=3D\"", ap_auth_name(r), "\"", NULL)); = =0A= + return AUTH_REQUIRED;=0A= + }=0A= + code =3D smbcheck(c->user,pw,r, entries[idx].pipe);=0A= + if (code =3D=3D authenticated) return (OK);=0A= + else {=0A= + if (dir_config_rec->auth_usrfile) {=0A= + sprintf(errstr,"%d# ntlm_auth_user:%s in %s = ?\n",my_pid, c->user, dir_config_rec->auth_usrfile);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, = r, errstr); =0A= + if (!(real_pw =3D fget_pw(r, c->user, = dir_config_rec->auth_usrfile))) {=0A= + ap_log_rerror(APLOG_MARK, = APLOG_NOERRNO|APLOG_ERR, r, "%d# user %s not found: %s\n", my_pid, = c->user, r->uri);=0A= + return AUTH_REQUIRED;=0A= + }=0A= + invalid_pw =3D ap_validate_password(pw, real_pw);=0A= + if (invalid_pw !=3D NULL) {=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, = r,"%d# user %s: authentication failure for \"%s\": %s",=0A= + my_pid, c->user, r->uri, invalid_pw);=0A= + return AUTH_REQUIRED;=0A= + }=0A= + else return (OK);=0A= + } =0A= + else return AUTH_REQUIRED;=0A= + }=0A= + }=0A= + =0A= +=0A= + /* NTLM security */=0A= + =0A= + if (cli.crypt_mode =3D=3D dc_crypt) {=0A= + code =3D check_ntlmsmb(r,&cli);=0A= + sprintf(errstr,"%d# ntlm_auth_user:%s dc asked\n",my_pid, = c->user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + if (code =3D=3D authenticated) {=0A= + ap_table_setn (r->subprocess_env, "REMOTE_DOMAIN", = ap_pstrcat(r->pool,cli.domain, NULL));=0A= + list_insert ((char *) cli.user, (char *) cli.pwd, (char *) = cli.cryptkey, (char *) cli.domain, server_config_rec->CacheTimeout, = server_config_rec->CacheMaxReq, r);=0A= + set_cookie (r, ap_pstrcat(r->pool, cli.domain, "\\", = cli.user, NULL)); =0A= + cli_clear (&cli);=0A= + if (strcasecmp(t, "OPTIONAL_NTLM")=3D=3D0) = ap_table_setn(r->subprocess_env, "AUTH_STAT", "OK");=0A= + return OK;=0A= + }=0A= + else {=0A= + cli_clear (&cli);=0A= + if (strcasecmp(t, "OPTIONAL_NTLM")=3D=3D0) {=0A= + ap_table_setn(r->subprocess_env, "AUTH_STAT", = "INVALID");=0A= + return OK;=0A= + }=0A= + else {=0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + ap_pstrcat(r->pool, "BASIC realm=3D\"", = ap_auth_name(r), "\"", NULL)); =0A= + return AUTH_REQUIRED;=0A= + }=0A= + } =0A= + }=0A= + else { /* list_crypt */=0A= + sprintf(errstr,"%d# ntlm_auth_user:%s %s: check in = list\n",my_pid, r->connection->remote_ip, r->connection->user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr); =0A= + if (strcasecmp (r->connection->user, cli.user) =3D=3D 0) {=0A= + if (vergleich(cli.pwd_check, cli.pwd, 24)) {=0A= + /* authenticated */=0A= + list_insert ((char *) cli.user, (char *) cli.pwd, (char = *) cli.cryptkey, (char *) cli.domain, server_config_rec->CacheTimeout, = server_config_rec->CacheMaxReq, r);=0A= + set_cookie (r, ap_pstrcat (r->pool, cli.domain, "\\", = cli.user, NULL ));=0A= + ap_table_setn(r->subprocess_env, "REMOTE_DOMAIN", = ap_pstrcat (r->pool,cli.domain, NULL));=0A= + cli_clear (&cli);=0A= + if (strcasecmp(t, "OPTIONAL_NTLM")=3D=3D0) = ap_table_setn(r->subprocess_env, "AUTH_STAT", "OK");=0A= + return OK;=0A= + }=0A= + else { =0A= + cli_clear (&cli);=0A= + if (strcasecmp(t, "OPTIONAL_NTLM")=3D=3D0) {=0A= + ap_table_setn(r->subprocess_env, "AUTH_STAT", = "INVALID");=0A= + return OK;=0A= + }=0A= + else {=0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + ap_pstrcat(r->pool, "BASIC realm=3D\"", = ap_auth_name(r), "\"", NULL)); =0A= + return AUTH_REQUIRED;=0A= + }=0A= + }=0A= + }=0A= + else {=0A= + /* there is another user on the client_host */=0A= + sprintf(errstr,"%d# ntlm_auth_user:%s %s in list, %s = requests\n",my_pid, r->connection->remote_ip,cli.user, = r->connection->user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, r, = errstr);=0A= + list_search ((char *) cli.domain, r->connection->user , (char = *) cli.pwd_check, (char *) cli.cryptkey, = server_config_rec->CacheTimeout,r); /* deletes this record in Shm */ = =0A= + cli_clear (&cli);=0A= + r->connection->user =3D NULL; =0A= + if (strcasecmp(t, "OPTIONAL_NTLM")=3D=3D0) {=0A= + ap_table_setn(r->subprocess_env, "AUTH_STAT", = "CLIENT_CHANGED");=0A= + return OK;=0A= + }=0A= + else {=0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + ap_pstrcat(r->pool, "BASIC = realm=3D\"", ap_auth_name(r), "\"", NULL));=0A= + return AUTH_REQUIRED;=0A= + } =0A= + }=0A= + }=0A= +}=0A= + =0A= +static int ntlm_check_auth(request_rec *r) =0A= +{=0A= +=0A= + auth_ntlm_dir_config_rec *dir_config_rec = =3D(auth_ntlm_dir_config_rec *)ap_get_module_config = (r->per_dir_config,&ntlm_module);=0A= +=0A= + conn_rec *c =3D r->connection;=0A= + int m =3D r->method_number; =0A= + const array_header *reqs_arr =3D ap_requires (r);=0A= + require_line *reqs =3D reqs_arr ? (require_line *)reqs_arr->elts : = NULL;=0A= + table *grpstatus;=0A= + int x;=0A= + char *w;=0A= + const char * t;=0A= +#define UNDEFINED -13=0A= + int ret =3D UNDEFINED;=0A= +=0A= + if (!r->connection->user) return OK;=0A= + if (!r->connection->ap_auth_type) return OK;=0A= + if (!((strcmp (r->connection->ap_auth_type, "NTLM") =3D=3D 0) || = (strcmp (r->connection->ap_auth_type, "BasicSMB") =3D=3D 0) ||=0A= + (strcmp (r->connection->ap_auth_type, "OPTIONAL_NTLM") = =3D=3D 0))) return DECLINED;=0A= + =0A= + if (!reqs_arr) ret =3D DECLINED;=0A= + else { /* 1: .htaccess */=0A= + if (dir_config_rec->auth_grpfile) grpstatus =3D = groups_for_user(r, c->user, dir_config_rec->auth_grpfile);=0A= + else grpstatus =3D NULL;=0A= + =0A= + for(x=3D0; ((x < reqs_arr->nelts) && (ret =3D=3D UNDEFINED)); = x++) {=0A= + if (! (reqs[x].method_mask & (1 << m))) continue;=0A= + t =3D reqs[x].requirement;=0A= + w =3D ap_getword_white(r->pool, &t);=0A= + if(!strcmp(w,"valid-user")) ret =3D OK;=0A= + if(!strcmp(w,"user")) {=0A= + while(t[0]) {=0A= + w =3D ap_getword_conf (r->pool, &t);=0A= + if(!strcasecmp(c->user,w)) { ret =3D OK; break;}=0A= + }=0A= + }=0A= + else if (!strcmp(w, "group")) {=0A= + if (!grpstatus) {=0A= + sprintf(errstr,"%d# ntlm_check_auth: no group file = ?\n", my_pid);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, = r, errstr); =0A= + return (SERVER_ERROR);=0A= + }=0A= + else while (t[0]) {=0A= + w =3D ap_getword_conf(r->pool, &t);=0A= + if (ap_table_get(grpstatus, w)) {ret =3D OK; break; = }=0A= + }=0A= + } /* if group */=0A= + } /* for */=0A= + }=0A= + =0A= + if ((ret =3D=3D UNDEFINED) || (ret =3D=3D AUTH_REQUIRED)) {=0A= + if (strcmp (r->connection->ap_auth_type, "OPTIONAL_NTLM") =3D=3D = 0) {=0A= + ap_table_setn(r->subprocess_env, "AUTH_STAT", = "NOT_ACCEPTED"); =0A= + }=0A= + else {=0A= + /* another chance */=0A= + ap_table_setn(r->err_headers_out,r->proxyreq ? = "Proxy-Authenticate" : "WWW-Authenticate",=0A= + ap_pstrcat(r->pool, "BASIC realm=3D\"", = ap_auth_name(r), "\"", NULL)); =0A= + return AUTH_REQUIRED;=0A= + }=0A= + }=0A= +=0A= + /* .htaccess ---> DECLINED or OK */=0A= + /* 2: .SMBACCESS */=0A= + return (check_smbaccess (r));=0A= +}=0A= +=0A= +=0A= +static void ntlm_child_exit(server_rec *s, pool *p)=0A= +{=0A= + ShmDetach(s);=0A= +}=0A= +=0A= --- /dev/null Thu Apr 27 11:47:59 2000=0A= +++ ../smbaccess.c Wed Apr 26 09:03:20 2000=0A= @@ -0,0 +1,240 @@=0A= +=0A= +/*=0A= + * smbaccess.c: checks file access according to the rules in = .SMBACCESS=0A= + * =0A= + */=0A= +=0A= +#include "httpd.h"=0A= +#include "http_config.h"=0A= +#include "http_core.h"=0A= +#include "http_log.h"=0A= +#include "http_protocol.h"=0A= +#include "http_conf_globals.h"=0A= +=0A= +#include =0A= +#include =0A= +=0A= +#include "ntlm_constants.h"=0A= +#include "SMB_includes.h" =0A= +=0A= +#ifndef LINUX=0A= +extern const int sys_nerr;=0A= +#else=0A= + int getgrouplist(const char * uname, int agroup, register int * = groups, int * grpcnt);=0A= +#endif=0A= +=0A= +BOOL username_gleich (char *DBuser, char *LANuser)=0A= +{=0A= +#define MIN_NAME_LEN 8=0A= + int LANl =3D strlen(LANuser);=0A= +=0A= + if (strcasecmp(DBuser, LANuser) =3D=3D 0) return (True);=0A= + if ((strncasecmp (LANuser, "LAN",3)=3D=3D0) && (strcasecmp = (LANuser+3, DBuser) =3D=3D 0)) return (True);=0A= + if ( (LANl > MIN_NAME_LEN) && (strcasecmp (LANuser + (LANl - = MIN_NAME_LEN),DBuser) =3D=3D 0)) return (True);=0A= + return (False);=0A= +}=0A= +=0A= +void strupper(char *s)=0A= +{=0A= + while (*s) {=0A= + if (islower(*s)) *s =3D toupper(*s);=0A= + s++;=0A= + }=0A= +}=0A= +=0A= +struct USER_Info * get_passwd_info(char *user )=0A= +{=0A= + struct passwd * pwdp;=0A= + BOOL gefunden =3D False;=0A= + static struct USER_Info user_info ;=0A= +=0A= + if (user_info.uid !=3D 0 && (strcasecmp(user_info.lanuser, = user)=3D=3D0)) return (&user_info); =0A= + =0A= + errno =3D 0;=0A= + setpwent();=0A= + while ( (pwdp =3D getpwent()) !=3D NULL && errno !=3D ENOATTR && = (gefunden =3D=3D False)) {=0A= + gefunden =3D username_gleich (pwdp->pw_name, user);=0A= + if (gefunden =3D=3D True) {=0A= + strcpy ((char *) user_info.dbuser, pwdp->pw_name); =0A= + strcpy ((char *) user_info.lanuser, user); =0A= + user_info.uid =3D pwdp->pw_uid;=0A= + user_info.gid =3D pwdp->pw_gid; =0A= + }=0A= + }=0A= + endpwent();=0A= + =0A= + if (gefunden =3D=3D True) return (&user_info);=0A= + else return (NULL);=0A= +}=0A= +=0A= +void epsdirname(char *dest, const char *string)=0A= +{=0A= + register char *p;=0A= + register const char *t;=0A= + register int len;=0A= +=0A= + for (p =3D dest, t =3D string, len =3D 0; (*p++ =3D *t++); len++) = ;=0A= + for (p =3D dest + len; ('/' !=3D *p) && (p > dest) ; p--);=0A= + if (p =3D=3D dest) {=0A= + *p++ =3D '.';=0A= + *p =3D '\0';=0A= + }=0A= + else {=0A= + *p =3D '\0';=0A= + }=0A= + }=0A= +=0A= +=0A= +int aclfindkey(request_rec *r,char *keyname,FILE *fp,char *user, int = ngroups, int *groups)=0A= +{=0A= + char line[LINELEN+1],buffer[LINELEN+1];=0A= + char *ptr; =0A= + char item[80];=0A= + int len,i;=0A= + char * star;=0A= + struct group *grp;=0A= + char errstr[MAX_STRING_LEN];=0A= +=0A= + rewind(fp);=0A= + while (fgets(line,LINELEN,fp)!=3DNULL) {=0A= + if ( (sscanf(line,"%s:%*s",buffer)=3D=3D1) &&=0A= + ( (strcmp (buffer,keyname) =3D=3D 0) || (strcmp (buffer, = S_ACLPERMITALL) =3D=3D 0) ) ) {=0A= + /* row found */=0A= + strupper (line);=0A= + /* search for the user */ =0A= + strcpy(item,user); =0A= + strupper (item); =0A= + len =3D strlen(item);=0A= + star =3D strchr( line, '*' );=0A= + do {=0A= + ptr =3D strchr( line, ':' );=0A= + while ( (ptr =3D strstr(ptr+1,item)) !=3D NULL ) {=0A= + /* substring found: Test if single word */=0A= + if ( ( isspace(ptr[len]) || (strchr(",;\r\n*", = ptr[len]) !=3D NULL) || ptr[len] =3D=3D '\0' ) /* Ende */ &&=0A= + ( isspace(ptr[-1]) || (strchr(":,;", ptr[-1] = ) !=3D NULL) ) ) return (OK);=0A= + } /* while ptr !=3D NULL */=0A= + if ( star ) {=0A= + if ( len > 0 ) { strcpy( item+len-1, "*" ); --len; = }=0A= + else star=3D0;=0A= + }=0A= + } while ( star );=0A= + =0A= + /* search for the group */=0A= + for (i=3D0; ifilename, r);=0A= + continue;=0A= + }=0A= + strcpy(item,"@");=0A= + strcat(item,grp->gr_name); =0A= + strupper (item);=0A= + len =3D strlen(item);=0A= + ptr =3D strchr( line, ':' );=0A= + while ( (ptr =3D strstr(ptr+1,item)) !=3D NULL ){=0A= + /* substring found: Test if end; start =3D = '@', '*' not implemented*/=0A= + if ( isspace(ptr[len]) || strchr(",;\r\n*", = ptr[len]) || ptr[len] =3D=3D '\0' ) return (OK);=0A= + }=0A= + } /* for groups */ =0A= + } /* if keyname found */=0A= + } /* while */=0A= + return (AUTH_REQUIRED);=0A= +}=0A= +=0A= +=0A= +=0A= +int check_smbaccess(request_rec *r)=0A= +{=0A= +=0A= +char *accessfilename,dir[PATH_MAX];=0A= +FILE *fp;=0A= +=0A= +struct USER_Info * user_info;=0A= +struct group * w_prim_grp;=0A= +=0A= +char w_user[USERNAME_LEN];=0A= +int w_gid;=0A= +int w_ngroups =3D NGROUPS;=0A= +int w_groups[NGROUPS];=0A= +=0A= +struct stat st;=0A= +=0A= +int ret =3D AUTH_REQUIRED;=0A= +int i;=0A= +char errstr[MAX_STRING_LEN];=0A= +=0A= + /* open .SMB-ACCESS */=0A= + fp =3D NULL;=0A= + dir[0]=3D'\0';=0A= + accessfilename =3D ap_pcalloc(r->pool,PATH_MAX+1);=0A= + strcpy(accessfilename, r->filename);=0A= + strcpy(dir,accessfilename);=0A= + epsdirname(accessfilename,dir);=0A= + strcat(accessfilename,"/");=0A= + strcat(accessfilename,ACLFILE);=0A= + if ((fp=3Dfopen(accessfilename,"r"))=3D=3DNULL) { =0A= + if ( (errno <=3D sys_nerr) || (strcmp = (r->connection->ap_auth_type, "OPTIONAL_NTLM") =3D=3D 0)) return (OK); = =0A= + /* no .SMB-ACCESS or OPTIONAL_NTLM */=0A= + else { =0A= + sprintf(errstr, "# check SMB-ACCESS: fopen failed (%s) file = %s", strerror(errno), accessfilename);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, = errstr); =0A= + return (FORBIDDEN);=0A= + }=0A= + }=0A= +=0A= + /* determine uid, primary gid */=0A= + user_info =3D get_passwd_info (r->connection->user);=0A= + if (user_info=3D=3DNULL) { =0A= + =0A= + sprintf(errstr, "# check SMB-ACCESS: user not identified, = user:%s\n", r->connection->user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, = errstr); =0A= + =0A= + strcpy (w_user, r->connection->user);=0A= + w_prim_grp =3D NULL;=0A= + }=0A= + else {=0A= + strcpy (w_user, (const char *) user_info->dbuser);=0A= + w_prim_grp=3Dgetgrgid(user_info->gid);=0A= + }=0A= + if (w_prim_grp=3D=3DNULL) {=0A= + =0A= + sprintf(errstr, "# check SMB-ACCESS: primary group not = identified, user:%s -> %s\n", r->connection->user, w_user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, r, errstr); = =0A= + =0A= + w_gid =3D -2;=0A= + }=0A= + else w_gid =3D w_prim_grp->gr_gid;=0A= + =0A= + /* calculate group access list */=0A= + if (getgrouplist(w_user, w_gid, w_groups, &w_ngroups) =3D=3D -1) = {=0A= + sprintf(errstr, "# check SMB-ACCESS: group list too small, = user:%s --> %s\n", r->connection->user, w_user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r, = errstr); =0A= + }=0A= + =0A= + i =3D stat(r->filename,&st);=0A= + if (i =3D=3D 0){ /* ok */=0A= + if (st.st_mode & S_IFDIR) ret =3D = aclfindkey(r,S_ACLREADDIR,fp, w_user, w_ngroups, w_groups); /* ---> = mod_autoindex */=0A= + else ret =3D aclfindkey(r,S_ACLREAD,fp, w_user, w_ngroups, = w_groups);=0A= + }=0A= + else ret =3D DECLINED;=0A= + =0A= + =0A= + /* S_ACLPERMITALL in aclfindkey checked */=0A= + =0A= + fclose (fp);=0A= +=0A= + if (ret !=3D OK) {=0A= + if (strcmp (r->connection->ap_auth_type, "OPTIONAL_NTLM") = =3D=3D 0) {=0A= + ret =3D OK;=0A= + ap_table_setn(r->subprocess_env, "AUTH_STAT", = "NO_SMBACCESS");=0A= + }=0A= + else {=0A= + sprintf(errstr, "# check SMB-ACCESS: user %s not accepted", = r->connection->user);=0A= + ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, r, = errstr); =0A= + }=0A= + }=0A= +=0A= + return (ret);=0A= +} =0A= + =0A= --- /dev/null Thu Apr 27 11:47:59 2000=0A= +++ ../SMB_includes.h Wed Apr 26 09:03:32 2000=0A= @@ -0,0 +1,498 @@=0A= +=0A= +=0A= +/*=0A= + Samba needs type definitions for int16, int32, uint16 and = uint32.=0A= + Normally these are signed and unsigned 16 and 32 bit integers, = but=0A= + they actually only need to be at least 16 and 32 bits=0A= + respectively. Thus if your word size is 8 bytes just defining = them=0A= + as signed and unsigned int will work.=0A= +*/=0A= +#define uint8 unsigned char=0A= +#define int16 short=0A= +#define uint16 unsigned =0A= +#define int32 int=0A= +#define uint32 unsigned int32=0A= +#define uchar unsigned char=0A= +=0A= +#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])=0A= +#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))=0A= +#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)=0A= +#define SCVAL(buf,pos,val) (CVAL(buf,pos) =3D (val))=0A= +#define SSVALX(buf,pos,val) = (CVAL(buf,pos)=3D(val)&0xFF,CVAL(buf,pos+1)=3D(val)>>8)=0A= +#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))=0A= +#define SIVAL(buf,pos,val) IVAL(buf,pos)=3D((uint32)(val))=0A= +#define SVALS(buf,pos) ((int16)SVAL(buf,pos))=0A= +#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val)))=0A= +=0A= +#define PTR_DIFF(p1,p2) ((int)(((char *)(p1)) - (char *)(p2)))=0A= +=0A= +/* the basic packet size, assuming no words or bytes */=0A= +#define smb_size 39=0A= +#define SMB_port 139=0A= +=0A= +typedef char fstring[128];=0A= +=0A= +/* offsets into message for common items */=0A= +#define smb_com 8=0A= +#define smb_rcls 9 /* error-class */=0A= +#define smb_reh 10=0A= +#define smb_err 11=0A= +#define smb_flg 13=0A= +#define smb_flg2 14=0A= +#define smb_reb 13=0A= +#define smb_tid 28=0A= +#define smb_pid 30=0A= +#define smb_uid 32=0A= +#define smb_mid 34=0A= +#define smb_wct 36=0A= +#define smb_vwv 37=0A= +#define smb_vwv0 37=0A= +#define smb_vwv1 39=0A= +#define smb_vwv2 41=0A= +#define smb_vwv3 43=0A= +#define smb_vwv4 45=0A= +#define smb_vwv5 47=0A= +#define smb_vwv6 49=0A= +#define smb_vwv7 51=0A= +#define smb_vwv8 53=0A= +#define smb_vwv9 55=0A= +#define smb_vwv10 57=0A= +#define smb_vwv11 59=0A= +#define smb_vwv12 61=0A= +#define smb_vwv13 63=0A= +#define smb_vwv14 65=0A= +#define smb_vwv15 67=0A= +#define smb_vwv16 69=0A= +#define smb_vwv17 71=0A= +=0A= +#define list_crypt 1=0A= +#define dc_crypt 2=0A= +#define undefined_crypt 0=0A= +=0A= +struct cli_state {=0A= + int initialisiert;=0A= + int fd;=0A= + int cnum;=0A= + int pid;=0A= + int mid;=0A= + int uid;=0A= + int protocol;=0A= + int sec_mode;=0A= + fstring desthost;=0A= + uchar user[USERNAME_LEN];=0A= + uchar domain[DOMAIN_LEN];=0A= + uchar pwd[24];=0A= + uchar cryptkey[8];=0A= + int crypt_mode;=0A= + uchar pwd_check[24];=0A= + uint32 sesskey;=0A= + int readbraw_supported;=0A= + int writebraw_supported;=0A= + int timeout;=0A= + int max_xmit;=0A= + char *outbuf;=0A= + char *inbuf;=0A= + int bufsize;=0A= +} ;=0A= +=0A= +#define SAFETY_MARGIN 1024=0A= +=0A= +#define READ_TIMEOUT 1=0A= +#define READ_EOF 2=0A= +#define READ_ERROR 3=0A= +=0A= +#define LONG_CONNECT_TIMEOUT 30=0A= +=0A= +/* protocol types. It assumes that higher protocols include lower = protocols=0A= + as subsets */=0A= +enum protocol_types = {PROTOCOL_NONE,PROTOCOL_CORE,PROTOCOL_COREPLUS,PROTOCOL_LANMAN1,PROTOCOL= _LANMAN2,PROTOCOL_NT1};=0A= +=0A= +=0A= +#define SMBmkdir 0x00 /* create directory */=0A= +#define SMBrmdir 0x01 /* delete directory */=0A= +#define SMBopen 0x02 /* open file */=0A= +#define SMBcreate 0x03 /* create file */=0A= +#define SMBclose 0x04 /* close file */=0A= +#define SMBflush 0x05 /* flush file */=0A= +#define SMBunlink 0x06 /* delete file */=0A= +#define SMBmv 0x07 /* rename file */=0A= +#define SMBgetatr 0x08 /* get file attributes */=0A= +#define SMBsetatr 0x09 /* set file attributes */=0A= +#define SMBread 0x0A /* read from file */=0A= +#define SMBwrite 0x0B /* write to file */=0A= +#define SMBlock 0x0C /* lock byte range */=0A= +#define SMBunlock 0x0D /* unlock byte range */=0A= +#define SMBctemp 0x0E /* create temporary file */=0A= +#define SMBmknew 0x0F /* make new file */=0A= +#define SMBchkpth 0x10 /* check directory path */=0A= +#define SMBexit 0x11 /* process exit */=0A= +#define SMBlseek 0x12 /* seek */=0A= +#define SMBtcon 0x70 /* tree connect */=0A= +#define SMBtconX 0x75 /* tree connect and X*/=0A= +#define SMBtdis 0x71 /* tree disconnect */=0A= +#define SMBnegprot 0x72 /* negotiate protocol */=0A= +#define SMBdskattr 0x80 /* get disk attributes */=0A= +#define SMBsearch 0x81 /* search directory */=0A= +#define SMBsplopen 0xC0 /* open print spool file */=0A= +#define SMBsplwr 0xC1 /* write to print spool file */=0A= +#define SMBsplclose 0xC2 /* close print spool file */=0A= +#define SMBsplretq 0xC3 /* return print queue */=0A= +#define SMBsends 0xD0 /* send single block message */=0A= +#define SMBsendb 0xD1 /* send broadcast message */=0A= +#define SMBfwdname 0xD2 /* forward user name */=0A= +#define SMBcancelf 0xD3 /* cancel forward */=0A= +#define SMBgetmac 0xD4 /* get machine name */=0A= +#define SMBsendstrt 0xD5 /* send start of multi-block message = */=0A= +#define SMBsendend 0xD6 /* send end of multi-block message */=0A= +#define SMBsendtxt 0xD7 /* send text of multi-block message */=0A= +=0A= +/* Core+ protocol */=0A= +#define SMBlockread 0x13 /* Lock a range and read */=0A= +#define SMBwriteunlock 0x14 /* Unlock a range then write */=0A= +#define SMBreadbraw 0x1a /* read a block of data with no smb header = */=0A= +#define SMBwritebraw 0x1d /* write a block of data with no smb = header */=0A= +#define SMBwritec 0x20 /* secondary write request */=0A= +#define SMBwriteclose 0x2c /* write a file then close it */=0A= +=0A= +/* dos extended protocol */=0A= +#define SMBreadBraw 0x1A /* read block raw */=0A= +#define SMBreadBmpx 0x1B /* read block multiplexed */=0A= +#define SMBreadBs 0x1C /* read block (secondary response) = */=0A= +#define SMBwriteBraw 0x1D /* write block raw */=0A= +#define SMBwriteBmpx 0x1E /* write block multiplexed */=0A= +#define SMBwriteBs 0x1F /* write block (secondary request) = */=0A= +#define SMBwriteC 0x20 /* write complete response */=0A= +#define SMBsetattrE 0x22 /* set file attributes expanded */=0A= +#define SMBgetattrE 0x23 /* get file attributes expanded */=0A= +#define SMBlockingX 0x24 /* lock/unlock byte ranges and X */=0A= +#define SMBtrans 0x25 /* transaction - name, bytes in/out = */=0A= +#define SMBtranss 0x26 /* transaction (secondary = request/response) */=0A= +#define SMBioctl 0x27 /* IOCTL */=0A= +#define SMBioctls 0x28 /* IOCTL (secondary request/response) = */=0A= +#define SMBcopy 0x29 /* copy */=0A= +#define SMBmove 0x2A /* move */=0A= +#define SMBecho 0x2B /* echo */=0A= +#define SMBopenX 0x2D /* open and X */=0A= +#define SMBreadX 0x2E /* read and X */=0A= +#define SMBwriteX 0x2F /* write and X */=0A= +#define SMBsesssetupX 0x73 /* Session Set Up & X (including User = Logon) */=0A= +#define SMBffirst 0x82 /* find first */=0A= +#define SMBfunique 0x83 /* find unique */=0A= +#define SMBfclose 0x84 /* find close */=0A= +#define SMBinvalid 0xFE /* invalid command */=0A= +=0A= +/* Extended 2.0 protocol */=0A= +#define SMBtrans2 0x32 /* TRANS2 protocol set */=0A= +#define SMBtranss2 0x33 /* TRANS2 protocol set, secondary = command */=0A= +#define SMBfindclose 0x34 /* Terminate a TRANSACT2_FINDFIRST = */=0A= +#define SMBfindnclose 0x35 /* Terminate a = TRANSACT2_FINDNOTIFYFIRST */=0A= +#define SMBulogoffX 0x74 /* user logoff */=0A= +=0A= +/* NT SMB extensions. */=0A= +#define SMBnttrans 0xA0 /* NT transact */=0A= +#define SMBnttranss 0xA1 /* NT transact secondary */=0A= +#define SMBntcreateX 0xA2 /* NT create and X */=0A= +#define SMBntcancel 0xA4 /* NT cancel */=0A= +=0A= +/* These are the TRANS2 sub commands */=0A= +#define TRANSACT2_OPEN 0=0A= +#define TRANSACT2_FINDFIRST 1=0A= +#define TRANSACT2_FINDNEXT 2=0A= +#define TRANSACT2_QFSINFO 3=0A= +#define TRANSACT2_SETFSINFO 4=0A= +#define TRANSACT2_QPATHINFO 5=0A= +#define TRANSACT2_SETPATHINFO 6=0A= +#define TRANSACT2_QFILEINFO 7=0A= +#define TRANSACT2_SETFILEINFO 8=0A= +#define TRANSACT2_FSCTL 9=0A= +#define TRANSACT2_IOCTL 0xA=0A= +#define TRANSACT2_FINDNOTIFYFIRST 0xB=0A= +#define TRANSACT2_FINDNOTIFYNEXT 0xC=0A= +#define TRANSACT2_MKDIR 0xD=0A= +#define TRANSACT2_SESSION_SETUP 0xE=0A= +#define TRANSACT2_GET_DFS_REFERRAL 0x10=0A= +#define TRANSACT2_REPORT_DFS_INCONSISTANCY 0x11=0A= +=0A= +/* These are the NT transact sub commands. */=0A= +#define NT_TRANSACT_CREATE 1=0A= +#define NT_TRANSACT_IOCTL 2=0A= +#define NT_TRANSACT_SET_SECURITY_DESC 3=0A= +#define NT_TRANSACT_NOTIFY_CHANGE 4=0A= +#define NT_TRANSACT_RENAME 5=0A= +#define NT_TRANSACT_QUERY_SECURITY_DESC 6=0A= +=0A= +/* these are the trans2 sub fields for primary requests */=0A= +#define smb_tpscnt smb_vwv0=0A= +#define smb_tdscnt smb_vwv1=0A= +#define smb_mprcnt smb_vwv2=0A= +#define smb_mdrcnt smb_vwv3=0A= +#define smb_msrcnt smb_vwv4=0A= +#define smb_flags smb_vwv5=0A= +#define smb_timeout smb_vwv6=0A= +#define smb_pscnt smb_vwv9=0A= +#define smb_psoff smb_vwv10=0A= +#define smb_dscnt smb_vwv11=0A= +#define smb_dsoff smb_vwv12=0A= +#define smb_suwcnt smb_vwv13=0A= +#define smb_setup smb_vwv14=0A= +#define smb_setup0 smb_setup=0A= +#define smb_setup1 (smb_setup+2)=0A= +#define smb_setup2 (smb_setup+4)=0A= +=0A= +/* these are for the secondary requests */=0A= +#define smb_spscnt smb_vwv2=0A= +#define smb_spsoff smb_vwv3=0A= +#define smb_spsdisp smb_vwv4=0A= +#define smb_sdscnt smb_vwv5=0A= +#define smb_sdsoff smb_vwv6=0A= +#define smb_sdsdisp smb_vwv7=0A= +#define smb_sfid smb_vwv8=0A= +=0A= +/* and these for responses */=0A= +#define smb_tprcnt smb_vwv0=0A= +#define smb_tdrcnt smb_vwv1=0A= +#define smb_prcnt smb_vwv3=0A= +#define smb_proff smb_vwv4=0A= +#define smb_prdisp smb_vwv5=0A= +#define smb_drcnt smb_vwv6=0A= +#define smb_droff smb_vwv7=0A= +#define smb_drdisp smb_vwv8=0A= +=0A= +/* these are for the NT trans primary request. */=0A= +#define smb_nt_MaxSetupCount smb_vwv0=0A= +#define smb_nt_Flags (smb_vwv0 + 1)=0A= +#define smb_nt_TotalParameterCount (smb_vwv0 + 3)=0A= +#define smb_nt_TotalDataCount (smb_vwv0 + 7)=0A= +#define smb_nt_MaxParameterCount (smb_vwv0 + 11)=0A= +#define smb_nt_MaxDataCount (smb_vwv0 + 15)=0A= +#define smb_nt_ParameterCount (smb_vwv0 + 19)=0A= +#define smb_nt_ParameterOffset (smb_vwv0 + 23)=0A= +#define smb_nt_DataCount (smb_vwv0 + 27)=0A= +#define smb_nt_DataOffset (smb_vwv0 + 31)=0A= +#define smb_nt_SetupCount (smb_vwv0 + 35)=0A= +#define smb_nt_Function (smb_vwv0 + 36)=0A= +#define smb_nt_SetupStart (smb_vwv0 + 38)=0A= +=0A= +/* these are for the NT trans secondary request. */=0A= +#define smb_nts_TotalParameterCount (smb_vwv0 + 3)=0A= +#define smb_nts_TotalDataCount (smb_vwv0 + 7)=0A= +#define smb_nts_ParameterCount (smb_vwv0 + 11)=0A= +#define smb_nts_ParameterOffset (smb_vwv0 + 15)=0A= +#define smb_nts_ParameterDisplacement (smb_vwv0 + 19)=0A= +#define smb_nts_DataCount (smb_vwv0 + 23)=0A= +#define smb_nts_DataOffset (smb_vwv0 + 27)=0A= +#define smb_nts_DataDisplacement (smb_vwv0 + 31)=0A= +=0A= +/* these are for the NT trans reply. */=0A= +#define smb_ntr_TotalParameterCount (smb_vwv0 + 3)=0A= +#define smb_ntr_TotalDataCount (smb_vwv0 + 7)=0A= +#define smb_ntr_ParameterCount (smb_vwv0 + 11)=0A= +#define smb_ntr_ParameterOffset (smb_vwv0 + 15)=0A= +#define smb_ntr_ParameterDisplacement (smb_vwv0 + 19)=0A= +#define smb_ntr_DataCount (smb_vwv0 + 23)=0A= +#define smb_ntr_DataOffset (smb_vwv0 + 27)=0A= +#define smb_ntr_DataDisplacement (smb_vwv0 + 31)=0A= +=0A= +/* these are for the NT create_and_X */=0A= +#define smb_ntcreate_NameLength (smb_vwv0 + 5)=0A= +#define smb_ntcreate_Flags (smb_vwv0 + 7)=0A= +#define smb_ntcreate_RootDirectoryFid (smb_vwv0 + 11)=0A= +#define smb_ntcreate_DesiredAccess (smb_vwv0 + 15)=0A= +#define smb_ntcreate_AllocationSize (smb_vwv0 + 19)=0A= +#define smb_ntcreate_FileAttributes (smb_vwv0 + 27)=0A= +#define smb_ntcreate_ShareAccess (smb_vwv0 + 31)=0A= +#define smb_ntcreate_CreateDisposition (smb_vwv0 + 35)=0A= +#define smb_ntcreate_CreateOptions (smb_vwv0 + 39)=0A= +#define smb_ntcreate_ImpersonationLevel (smb_vwv0 + 43)=0A= +#define smb_ntcreate_SecurityFlags (smb_vwv0 + 47)=0A= +=0A= +/* this is used on a TConX. I'm not sure the name is very helpful = though */=0A= +#define SMB_SUPPORT_SEARCH_BITS 0x0001=0A= +=0A= +/* these are the constants used in the above call. */=0A= +/* DesiredAccess */=0A= +/* File Specific access rights. */=0A= +#define FILE_READ_DATA 0x001=0A= +#define FILE_WRITE_DATA 0x002=0A= +#define FILE_APPEND_DATA 0x004=0A= +#define FILE_READ_EA 0x008=0A= +#define FILE_WRITE_EA 0x010=0A= +#define FILE_EXECUTE 0x020=0A= +#define FILE_DELETE_CHILD 0x040=0A= +#define FILE_READ_ATTRIBUTES 0x080=0A= +#define FILE_WRITE_ATTRIBUTES 0x100=0A= + =0A= +/* Generic access masks & rights. */=0A= +#define SPECIFIC_RIGHTS_MASK 0x00FFFFL=0A= +#define STANDARD_RIGHTS_MASK 0xFF0000L=0A= +#define DELETE_ACCESS (1L<<16)=0A= +#define READ_CONTROL_ACCESS (1L<<17)=0A= +#define WRITE_DAC_ACCESS (1L<<18)=0A= +#define WRITE_OWNER_ACCESS (1L<<19)=0A= +#define SYNCHRONIZE_ACCESS (1L<<20)=0A= +#define SYSTEM_SECURITY_ACCESS (1L<<24)=0A= +=0A= +/* Flags field. */=0A= +#define REQUEST_OPLOCK 2=0A= +#define REQUEST_BATCH_OPLOCK 4=0A= +#define OPEN_DIRECTORY 8=0A= +=0A= +/* ShareAccess field. */=0A= +#define FILE_SHARE_NONE 0 /* Cannot be used in bitmask. */=0A= +#define FILE_SHARE_READ 1=0A= +#define FILE_SHARE_WRITE 2=0A= +#define FILE_SHARE_DELETE 4=0A= +=0A= +/* FileAttributesField */=0A= +#define FILE_ATTRIBUTE_READONLY aRONLY=0A= +#define FILE_ATTRIBUTE_HIDDEN aHIDDEN=0A= +#define FILE_ATTRIBUTE_SYSTEM aSYSTEM=0A= +#define FILE_ATTRIBUTE_DIRECTORY aDIR=0A= +#define FILE_ATTRIBUTE_ARCHIVE aARCH=0A= +#define FILE_ATTRIBUTE_NORMAL 0x80L=0A= +#define FILE_ATTRIBUTE_TEMPORARY 0x100L=0A= +#define FILE_ATTRIBUTE_COMPRESSED 0x800L=0A= +#define SAMBA_ATTRIBUTES_MASK 0x7F=0A= +=0A= +/* Flags - combined with attributes. */=0A= +#define FILE_FLAG_WRITE_THROUGH 0x80000000L=0A= +#define FILE_FLAG_NO_BUFFERING 0x20000000L=0A= +#define FILE_FLAG_RANDOM_ACCESS 0x10000000L=0A= +#define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000L=0A= +#define FILE_FLAG_DELETE_ON_CLOSE 0x04000000L=0A= +#define FILE_FLAG_BACKUP_SEMANTICS 0x02000000L=0A= +#define FILE_FLAG_POSIX_SEMANTICS 0x01000000L=0A= +=0A= +/* CreateDisposition field. */=0A= +#define FILE_SUPERSEDE 0=0A= +#define FILE_OPEN 1=0A= +#define FILE_CREATE 2=0A= +#define FILE_OPEN_IF 3=0A= +#define FILE_OVERWRITE 4=0A= +#define FILE_OVERWRITE_IF 5=0A= +=0A= +/* CreateOptions field. */=0A= +#define FILE_DIRECTORY_FILE 0x0001=0A= +#define FILE_WRITE_THROUGH 0x0002=0A= +#define FILE_SEQUENTIAL_ONLY 0x0004=0A= +#define FILE_NON_DIRECTORY_FILE 0x0040=0A= +#define FILE_NO_EA_KNOWLEDGE 0x0200=0A= +#define FILE_EIGHT_DOT_THREE_ONLY 0x0400=0A= +#define FILE_RANDOM_ACCESS 0x0800=0A= +#define FILE_DELETE_ON_CLOSE 0x1000=0A= +=0A= +/* Responses when opening a file. */=0A= +#define FILE_WAS_OPENED 1=0A= +#define FILE_WAS_CREATED 2=0A= +#define FILE_WAS_OVERWRITTEN 3=0A= +=0A= +/* File type flags */=0A= +#define FILE_TYPE_DISK 0=0A= +#define FILE_TYPE_BYTE_MODE_PIPE 1=0A= +#define FILE_TYPE_MESSAGE_MODE_PIPE 2=0A= +#define FILE_TYPE_PRINTER 3=0A= +#define FILE_TYPE_COMM_DEVICE 4=0A= +#define FILE_TYPE_UNKNOWN 0xFFFF=0A= +=0A= +/* Flag for NT transact rename call. */=0A= +#define RENAME_REPLACE_IF_EXISTS 1=0A= +=0A= +/* Filesystem Attributes. */=0A= +#define FILE_CASE_SENSITIVE_SEARCH 0x1=0A= +#define FILE_CASE_PRESERVED_NAMES 0x2=0A= +#define FILE_UNICODE_ON_DISK 0x4=0A= +#define FILE_PERISITANT_ACLS 0x8=0A= +=0A= +/* ChangeNotify flags. */=0A= +#define FILE_NOTIFY_CHANGE_FILE_NAME 0x001=0A= +#define FILE_NOTIFY_CHANGE_DIR_NAME 0x002=0A= +#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x004=0A= +#define FILE_NOTIFY_CHANGE_SIZE 0x008=0A= +#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x010=0A= +#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x020=0A= +#define FILE_NOTIFY_CHANGE_CREATION 0x040=0A= +#define FILE_NOTIFY_CHANGE_EA 0x080=0A= +#define FILE_NOTIFY_CHANGE_SECURITY 0x100=0A= +=0A= +/* where to find the base of the SMB packet proper */=0A= +#define smb_base(buf) (((char *)(buf))+4)=0A= +=0A= +=0A= +#define SMB_SUCCESS 0 /* The request was successful. */=0A= +#define ERRDOS 0x01 /* Error is from the core DOS operating system = set. */=0A= +#define ERRSRV 0x02 /* Error is generated by the server network file = manager.*/=0A= +#define ERRHRD 0x03 /* Error is an hardware error. */=0A= +#define ERRCMD 0xFF /* Command was not in the "SMB" format. */=0A= +=0A= +/* Error codes for the ERRSRV class */=0A= +=0A= +#define ERRerror 1 /* Non specific error code */=0A= +#define ERRbadpw 2 /* Bad password */=0A= +#define ERRbadtype 3 /* reserved */=0A= +#define ERRaccess 4 /* No permissions to do the requested operation = */=0A= +#define ERRinvnid 5 /* tid invalid */=0A= +#define ERRinvnetname 6 /* Invalid servername */=0A= +#define ERRinvdevice 7 /* Invalid device */=0A= +#define ERRqfull 49 /* Print queue full */=0A= +#define ERRqtoobig 50 /* Queued item too big */=0A= +#define ERRinvpfid 52 /* Invalid print file in smb_fid */=0A= +#define ERRsmbcmd 64 /* Unrecognised command */=0A= +#define ERRsrverror 65 /* smb server internal error */=0A= +#define ERRfilespecs 67 /* fid and pathname invalid combination */=0A= +#define ERRbadlink 68 /* reserved */=0A= +#define ERRbadpermits 69 /* Access specified for a file is not valid = */=0A= +#define ERRbadpid 70 /* reserved */=0A= +#define ERRsetattrmode 71 /* attribute mode invalid */=0A= +#define ERRpaused 81 /* Message server paused */=0A= +#define ERRmsgoff 82 /* Not receiving messages */=0A= +#define ERRnoroom 83 /* No room for message */=0A= +#define ERRrmuns 87 /* too many remote usernames */=0A= +#define ERRtimeout 88 /* operation timed out */=0A= +#define ERRnoresource 89 /* No resources currently available for = request. */=0A= +#define ERRtoomanyuids 90 /* too many userids */=0A= +#define ERRbaduid 91 /* bad userid */=0A= +#define ERRuseMPX 250 /* temporarily unable to use raw mode, use MPX = mode */=0A= +#define ERRuseSTD 251 /* temporarily unable to use raw mode, use = standard mode */=0A= +#define ERRcontMPX 252 /* resume MPX mode */=0A= +#define ERRbadPW /* reserved */=0A= +#define ERRnosupport 0xFFFF=0A= +#define ERRunknownsmb 22 /* from NT 3.5 response */=0A= +=0A= +/* Error codes for the ERRHRD class */=0A= +=0A= +#define ERRnowrite 19 /* read only media */=0A= +#define ERRbadunit 20 /* Unknown device */=0A= +#define ERRnotready 21 /* Drive not ready */=0A= +#define ERRbadcmd 22 /* Unknown command */=0A= +#define ERRdata 23 /* Data (CRC) error */=0A= +#define ERRbadreq 24 /* Bad request structure length */=0A= +#define ERRseek 25=0A= +#define ERRbadmedia 26=0A= +#define ERRbadsector 27=0A= +#define ERRnopaper 28=0A= +#define ERRwrite 29 /* write fault */=0A= +#define ERRread 30 /* read fault */=0A= +#define ERRgeneral 31 /* General hardware failure */=0A= +#define ERRwrongdisk 34=0A= +#define ERRFCBunavail 35=0A= +#define ERRsharebufexc 36 /* share buffer exceeded */=0A= +#define ERRdiskfull 39=0A= +=0A= +=0A= +/* SMB-ACCESS */=0A= +#define KEYLEN 20=0A= +#define ACLFILE ".SMB-ACCESS"=0A= +#define S_ACLPERMITALL "permitall:"=0A= +#define S_ACLREADDIR "readdir:"=0A= +#define S_ACLREAD "read:"=0A= +=0A= +#ifndef ENOATTR =0A= +#define ENOATTR 666=0A= +#endif=0A= +=0A= +struct USER_Info {=0A= + int uid;=0A= + int gid;=0A= + uchar lanuser[USERNAME_LEN];=0A= + uchar dbuser[USERNAME_LEN];=0A= +} ;=0A= --- /dev/null Thu Apr 27 11:47:59 2000=0A= +++ ../ntlm_constants.h Wed Apr 26 09:03:24 2000=0A= @@ -0,0 +1,9 @@=0A= +=0A= +=0A= +#define USERNAME_LEN 20=0A= +#define DOMAIN_LEN 9=0A= +#define LINELEN 5120=0A= +=0A= +typedef int BOOL;=0A= +#define True 1=0A= +#define False 0=0A= \ No newline at end of file=0A= --- /dev/null Thu Apr 27 11:47:59 2000=0A= +++ ../ntlm_shm.h Wed Apr 26 09:03:28 2000=0A= @@ -0,0 +1,39 @@=0A= +=0A= +=0A= +=0A= +#if defined(__FreeBSD__)=0A= + /* union semun is defined by including */=0A= + #else=0A= + /* according to X/OPEN we have to define it ourselves */=0A= + union semun {=0A= + int val; /* value for SETVAL */=0A= + struct semid_ds *buf; /* buffer for IPC_STAT, = IPC_SET */=0A= + unsigned short int *array; /* array for GETALL, SETALL = */=0A= + struct seminfo *__buf; /* buffer for IPC_INFO = */=0A= + };=0A= + #endif=0A= +=0A= +=0A= +#define SHM_START_STRING "Apache mod_auth_ntlm"=0A= +=0A= +typedef struct shm_knoten {=0A= + BOOL used;=0A= + int nr;=0A= + uchar name[USERNAME_LEN];=0A= + uchar client_ip[16];=0A= + uchar pw[24];=0A= + uchar cryptkey[8];=0A= + uchar domain[DOMAIN_LEN];=0A= + time_t zeit;=0A= + int req;=0A= + } ShmKnoten; =0A= +=0A= +typedef struct shm_header {=0A= + uchar start[sizeof(SHM_START_STRING)];=0A= + int total_size;=0A= + int max_knoten_anz;=0A= + int knoten_anz;=0A= + } ShmHeader;=0A= +/* HeaderSize aligned on a 8 byte boundary */=0A= +#define ShmHeaderSize ((sizeof(ShmHeader)+7) & ~7)=0A= +#define ShmKnotenSize (sizeof(ShmKnoten))=0A= ------_=_NextPart_000_01BFB02F.F44B99D0 Content-Type: text/plain; name="README.txt" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="README.txt" mod_auth_ntlm version 2.2=0A= =0A= ########################################################################= ##############################################=0A= =0A= I built the module as DSO with apache_1.3.4 and apache_1.3.12.=0A= We run it at freeBSD 3.1=0A= AIX 4.3=0A= LINUX=0A= =0A= apply the patch to apache_1.3.12=0A= changes on existing files:=0A= - http_protocol.c: a second cookie =0A= - alloc.c: no duplicates in the table=0A= - mod_autoindex.c access-restrictions in the file .SMBACCESS (link = with smbaccess.o) =0A= ########################################################################= ##############################################=0A= =0A= Configuration directives:=0A= =0A= * NTLMDomainList filename=0A= in filename the domain is described=0A= format: domain-name PwCheck-pipe-name = domain-controller [backup-domain-controller]=0A= =0A= example: =0A= NTLMDomainList conf/.NTLMDomains=0A= =0A= cat conf/.NTLMDomains=0A= Wien1 /usr/local/var/pwcheck_wien1 = dc1.adv.magwien.gv.at dc3.adv.magwien.gv.at=0A= Wien2 /usr/local/var/pwcheck_wien2 = dc2.adv.magwien.gv.at=0A= =0A= * NTLMDefaultDomain domain-name=0A= =0A= * NTLMCacheTimeout sec=0A= =0A= * NTLMCacheMaxReq r=0A= after r requests the user's password in checked = again=0A= =0A= * NTLMShmSize s=0A= =0A= * AuthType NTLM | basicSMB | OPTIONAL_NTLM=0A= NTLM: ntlm authentication=0A= basicSMB: basic authentication against the = domain-controller=0A= OPTIONAL_NTLM: NTLM authentication if the client = speaks NTLM-protocol=0A= sets the environment variable AUTH_STAT: OK=0A= = INVALID=0A= = CLIENT_CHANGED=0A= = NOT_NTLM=0A= = NOT_ACCEPTED=0A= = NO_SMBACCESS=0A= if AUTH_STAT is OK, NOT_ACCEPTED or = NO_SMBACCESS the environment variable REMOTE_USER ist set=0A= =0A= =0A= * AuthName name=0A= =0A= * NTLMAuthGroupfile filename=0A= =0A= * require user username =0A= valid-user=0A= group groupname=0A= =0A= * NTLMAuthUserFile filename=0A= if NTLM authentication is not successfull, then BASIC = authentication against NTLMAuthUserFile filename=0A= is performed=0A= =0A= * NTLMRequireDomain domainname=0A= =0A= =0A= = ########################################################################= ##################################=0A= =0A= within a directory it is possible to write a file named .SMBACCESS=0A= valid directives =0A= permitall username | @groupname=0A= read username | @groupname=0A= readdir username | @groupname=0A= =0A= ########################################################################= #####################################=0A= =0A= To improve the performance the routine caches authenticated users in = shared memory, the primary key is client-ip.=0A= It is assumed that on one client only one user is working. If there is = another user from the same client, =0A= the stored information from shared memory fails and basic = authentication against the domain-controller is done.=0A= After successfull authentiction a cookie NTLM=3Dusername is set. =0A= If the client sends no cookie, a pseudo-challenge is sent to determine = the username.If a shared-memory entry exists=0A= the password is checked against the stored one.=0A= The directives NTLMCacheTimeout, NTLMCacheMaxReq and NTLMShmSize = influenze this. =0A= =0A= ########################################################################= ###################################=0A= =0A= PwCheck-daemon does basic authentication against the = domain-controller, it communicates with the apache-module via =0A= a named pipe. =0A= sources in PwCheck_1.1.tar.gz =0A= ########################################################################= ####################################=0A= =0A= example entry for mod_auth_ntlm in httpd.conf=0A= =0A= NTLMDomainList conf/.NTLMDomains=0A= NTLMDefaultDomain your.domain=0A= NTLMCacheTimeout 60=0A= NTLMShmSize 4096=0A= NTLMCacheMaxReq 100=0A= =0A= =0A= example .htaccess-file=0A= AuthType NTLM=0A= AuthName Lanuser=0A= require valid-user=0A= =0A= ------_=_NextPart_000_01BFB02F.F44B99D0 Content-Type: application/octet-stream; name="PwCheck_1.1.tar.gz" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="PwCheck_1.1.tar.gz" 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 ZQ3vf5YaS0vLyzW8/1lbWZ7S/y/ymeZ/n9qVTu1Kp/nfp/nfp/nfp/nfp/nfKzkkm+Z/n+Z/n+Z/ n+Z/14bO0/zv0/zv0/zv0/zv0/zv0/zvtMbT/O/0meZ/n+Z/n+Z/d/Fhmv99mv99mv99mv99mv99 mv99mv/dJaDT/O8j9tk0//s0/7sMe5r//dvJ/67VD9OE7n+jhO75S3ZnV9wj57mbCGya/nya/nya /nya/nya/nya/nya/vyLfEbYf/Ojp0D/FoBlDO+eAnxc/u+VpTXy/1mtrS3XG+j/t7oyjf/wZT7K /vv04CUs9m3SfXOFE+0/vfMR2OCQ6nS9U9HWTK2/p9bff1frb6aoysjberO4aPvWuC9/RJM3v0tx gCnTRHyBSSVQysGOtgqVjOM+SgcCe7ZJAJubUbt5thVHc/iIlXPENHt2pipWQLyCRjLaD3lzDHPy Oh60q9kXElyh7HkTY4mNyG4kKgnybsMUD1U0+UMrDvoOnftofdOlTL5m4DAewwDfbMU9JSty7lOV X1vbxeAVFnJp5Hesk297GOuTmTnNXqAxrza/oDwXUXARpyHm9cYqnfACtbi4sziRN1Kodix0iYFh MBxA/Z5P66ehoYviHVJlFKwxS5Uh5qC95ljDFzHpyki/7TMy4cyo9OeIAhI+B3AJkKtNgT2gx5al Cc+KEbzIiKwVD5DDxDA4DAWPUbTvhonE3DohBovJdA5FRcQ3RLTk7ZaTmUVN9HuQDLHMcXPfjw78 yITd5QNHc3T8k1m6/fja0TOqdy83t/Oi5LnOjytjsFJo36Wfh2emjxoZjQ+B2j5oHl2H/+Sx2jv4 uJJdSynjtny8HaPno4KjLj9LSh+d6kaNMZT0DPudAMfd3z+gJ088axOpsiWGfVmFnUBVzHuZnq50 +TJJeYsW0FKVXJZdI4g4x8p+omntAVmCVbOjFRb/dA/FkXzJS7wSaXeasdgq47Ptnd3m3vbuvE7f FV3hOQyPlMT/2IEEE6pAwW4SUPM8aNRwwa9h/43047S8H/2wrfuRwcJQiSqj6qdW/doE5Xul7fUm am9YWn+o65fOFFANa6bqtTHF/Y8tq3jt4+6u0tIexhgAfOArSqYTmo/ouf8xdmZqZAWFTL3zxEaT /b2XzYPNN803B3tnYyZLQ+i1NITGhHU+tKLxSFGC3ApGEl1NjBiqTv+6q+tkadiEzaIu8LbNnrfM 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 AdC+rvcAyAUA ------_=_NextPart_000_01BFB02F.F44B99D0--