]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Samba Winbind ntlm and basic authentication helpers by Francesco Chemolli
authorhno <>
Mon, 20 May 2002 05:42:39 +0000 (05:42 +0000)
committerhno <>
Mon, 20 May 2002 05:42:39 +0000 (05:42 +0000)
18 files changed:
configure.in
helpers/basic_auth/winbind/Makefile.am [new file with mode: 0644]
helpers/basic_auth/winbind/samba_nss.h [new file with mode: 0644]
helpers/basic_auth/winbind/wb_basic_auth.c [new file with mode: 0644]
helpers/basic_auth/winbind/wb_common.c [new file with mode: 0644]
helpers/basic_auth/winbind/wbntlm.h [new file with mode: 0644]
helpers/basic_auth/winbind/winbind_nss_config.h [new file with mode: 0644]
helpers/basic_auth/winbind/winbindd_nss.h [new file with mode: 0644]
helpers/ntlm_auth/Makefile.am
helpers/ntlm_auth/winbind/Makefile.am [new file with mode: 0644]
helpers/ntlm_auth/winbind/patches/wb_common.patch [new file with mode: 0644]
helpers/ntlm_auth/winbind/patches/winbind_nss_config.patch [new file with mode: 0644]
helpers/ntlm_auth/winbind/samba_nss.h [new file with mode: 0644]
helpers/ntlm_auth/winbind/wb_common.c [new file with mode: 0644]
helpers/ntlm_auth/winbind/wb_ntlm_auth.c [new file with mode: 0644]
helpers/ntlm_auth/winbind/wbntlm.h [new file with mode: 0644]
helpers/ntlm_auth/winbind/winbind_nss_config.h [new file with mode: 0644]
helpers/ntlm_auth/winbind/winbindd_nss.h [new file with mode: 0644]

index f2b12a99f3164e30aa56637f055d65b7bd4a8498..c7b5e7f20de38d8ae7a9b2bee96e2c680720a024 100644 (file)
@@ -3,15 +3,15 @@ dnl  Configuration input file for Squid
 dnl
 dnl  Duane Wessels, wessels@nlanr.net, February 1996 (autoconf v2.9)
 dnl
-dnl  $Id: configure.in,v 1.269 2002/05/19 15:07:55 hno Exp $
+dnl  $Id: configure.in,v 1.270 2002/05/19 23:42:39 hno Exp $
 dnl
 dnl
 dnl
 AC_INIT(src/main.c)
 AC_CONFIG_AUX_DIR(cfgaux)
-AM_INIT_AUTOMAKE(squid, 2.6-DEVEL)
+AM_INIT_AUTOMAKE(Squid, 2.6-DEVEL)
 AM_CONFIG_HEADER(include/autoconf.h)
-AC_REVISION($Revision: 1.269 $)dnl
+AC_REVISION($Revision: 1.270 $)dnl
 AC_PREFIX_DEFAULT(/usr/local/squid)
 AM_MAINTAINER_MODE
 
@@ -2254,6 +2254,7 @@ AC_OUTPUT([\
        src/auth/ntlm/helpers/no_check/Makefile \
        src/auth/ntlm/helpers/SMB/Makefile \
        src/auth/ntlm/helpers/SMB/smbval/Makefile \
+       src/auth/ntlm/helpers/winbind/Makefile \
        contrib/Makefile \
        snmplib/Makefile \
        icons/Makefile \
diff --git a/helpers/basic_auth/winbind/Makefile.am b/helpers/basic_auth/winbind/Makefile.am
new file mode 100644 (file)
index 0000000..dd8c498
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#  Makefile for the Squid Object Cache server
+#
+#  $Id: Makefile.am,v 1.1 2002/05/19 23:42:40 hno Exp $
+#
+
+libexec_PROGRAMS = wb_auth
+wb_auth_SOURCES = wb_basic_auth.c wb_common.c
+INCLUDES = -I. -I$(top_builddir)/include -I$(top_srcdir)/include \
+    -I$(top_srcdir)/src
+LDADD = -L$(top_builddir)/lib -lmiscutil -lntlmauth
diff --git a/helpers/basic_auth/winbind/samba_nss.h b/helpers/basic_auth/winbind/samba_nss.h
new file mode 100644 (file)
index 0000000..6165e0b
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef _NSSWITCH_NSS_H
+#define _NSSWITCH_NSS_H
+/* 
+   Unix SMB/Netbios implementation.
+   Version 2.0
+
+   a common place to work out how to define NSS_STATUS on various
+   platforms
+
+   Copyright (C) Tim Potter 2000
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#ifdef HAVE_NSS_COMMON_H
+
+/* Sun Solaris */
+
+#include <nss_common.h>
+#include <nss_dbdefs.h>
+#include <nsswitch.h>
+
+typedef nss_status_t NSS_STATUS;
+
+#define NSS_STATUS_SUCCESS     NSS_SUCCESS
+#define NSS_STATUS_NOTFOUND    NSS_NOTFOUND
+#define NSS_STATUS_UNAVAIL     NSS_UNAVAIL
+#define NSS_STATUS_TRYAGAIN    NSS_TRYAGAIN
+
+#elif HAVE_NSS_H
+
+/* GNU */
+
+#include <nss.h>
+
+typedef enum nss_status NSS_STATUS;
+
+#elif HAVE_NS_API_H
+
+/* SGI IRIX */
+
+/* following required to prevent warnings of double definition
+ * of datum from ns_api.h
+*/
+#ifdef DATUM
+#define _DATUM_DEFINED
+#endif
+
+#include <ns_api.h>
+
+typedef enum
+{
+  NSS_STATUS_SUCCESS=NS_SUCCESS,
+  NSS_STATUS_NOTFOUND=NS_NOTFOUND,
+  NSS_STATUS_UNAVAIL=NS_UNAVAIL,
+  NSS_STATUS_TRYAGAIN=NS_TRYAGAIN
+} NSS_STATUS;
+
+#define NSD_MEM_STATIC 0
+#define NSD_MEM_VOLATILE 1
+#define NSD_MEM_DYNAMIC 2
+
+#elif defined(HPUX)
+/* HP-UX 11 */
+
+#include "nsswitch/hp_nss_common.h"
+#include "nsswitch/hp_nss_dbdefs.h"
+#include <nsswitch.h>
+
+#ifndef _HAVE_TYPEDEF_NSS_STATUS
+#define _HAVE_TYPEDEF_NSS_STATUS
+typedef nss_status_t NSS_STATUS;
+
+#define NSS_STATUS_SUCCESS     NSS_SUCCESS
+#define NSS_STATUS_NOTFOUND    NSS_NOTFOUND
+#define NSS_STATUS_UNAVAIL     NSS_UNAVAIL
+#define NSS_STATUS_TRYAGAIN    NSS_TRYAGAIN
+#endif /* HPUX */
+
+#else /* Nothing's defined. Neither gnu nor sun nor hp */
+
+typedef enum
+{
+  NSS_STATUS_SUCCESS=0,
+  NSS_STATUS_NOTFOUND=1,
+  NSS_STATUS_UNAVAIL=2,
+  NSS_STATUS_TRYAGAIN=3
+} NSS_STATUS;
+
+#endif
+
+#endif /* _NSSWITCH_NSS_H */
diff --git a/helpers/basic_auth/winbind/wb_basic_auth.c b/helpers/basic_auth/winbind/wb_basic_auth.c
new file mode 100644 (file)
index 0000000..ff9db92
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * (C) 2000 Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it>
+ *
+ * Distributed freely under the terms of the GNU General Public License,
+ * version 2. See the file COPYING for licensing details
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+
+#include "wbntlm.h"
+#include "util.h"
+/* stdio.h is included in wbntlm.h */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/time.h>           /* for gettimeofday */
+#include <errno.h>              /* BUG: is this portable? */
+
+#include "winbind_nss_config.h"
+#include "winbindd_nss.h"
+
+char debug_enabled=1;
+char *myname;
+pid_t mypid;
+
+NSS_STATUS winbindd_request(int req_type, 
+                                                                                                               struct winbindd_request *request,
+                                                                                                               struct winbindd_response *response);
+                
+
+void do_authenticate(char *user, char *pass) {
+       struct winbindd_request request;
+       struct winbindd_response response;
+       NSS_STATUS winbindd_result;
+       
+       memset(&request,0,sizeof(struct winbindd_request));
+       memset(&response,0,sizeof(struct winbindd_response));
+
+       
+       strncpy(request.data.auth.user,user,sizeof(fstring)-1);
+       strncpy(request.data.auth.pass,pass,sizeof(fstring)-1);
+
+       winbindd_result = winbindd_request(WINBINDD_PAM_AUTH,
+                                                                                                                                                &request, &response);
+       debug("winbindd result: %d\n",winbindd_result);
+
+       if (winbindd_result==WINBINDD_OK) {
+               SEND("OK");
+       } else {
+               SEND("ERR");
+       }
+
+       return;                                                                                         /* useless */
+}
+
+void manage_request(void) {
+  char buf[BUFFER_SIZE+1];
+       int length;
+       char *c, *user, *pass;
+  
+  if (fgets(buf, BUFFER_SIZE, stdin) == NULL) {
+    warn("fgets() failed! dying..... errno=%d (%s)\n", errno,
+          strerror(errno));
+    exit(1);    /* BIIG buffer */
+  }
+       
+  c=memchr(buf,'\n',BUFFER_SIZE);
+  if (c) {
+    *c='\0';
+               length=c-buf;
+       }
+  else {
+    warn("No newline in '%s'. Dying.\n",buf);
+               exit(1);
+       }
+  
+  debug("Got '%s' from squid (length: %d).\n",buf,length);
+       user=buf;
+
+       pass=memchr(buf,' ',length);
+       if (!pass) {
+               warn("Password not found. Denying access\n");
+               SEND("ERR");
+               return;
+       }
+       *pass='\0';
+       pass++;
+
+       do_authenticate(user,pass);
+
+}
+
+int main (int argc, char ** argv) {
+       if (argc > 0) {                                                         /* should always be true */
+               myname=strrchr(argv[0],'/');
+               if (myname==NULL)
+                       myname=argv[0];
+       } else {
+               myname="(unknown)";
+       }
+       mypid=getpid();
+  debug("ntlm winbindd auth helper build " __DATE__ ", " __TIME__
+        " starting up...\n");
+  /* initialize FDescs */
+  setbuf(stdout, NULL);
+  setbuf(stderr, NULL);
+
+  while(1) {
+    manage_request();
+  }
+  return 0;
+}
diff --git a/helpers/basic_auth/winbind/wb_common.c b/helpers/basic_auth/winbind/wb_common.c
new file mode 100644 (file)
index 0000000..1049529
--- /dev/null
@@ -0,0 +1,398 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 2.0
+
+   winbind client common code
+
+   Copyright (C) Tim Potter 2000
+   Copyright (C) Andrew Tridgell 2000
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#include "winbind_nss_config.h"
+#include "winbindd_nss.h"
+#include "config.h"
+
+
+/* Global variables.  These are effectively the client state information */
+
+int winbindd_fd = -1;           /* fd for winbindd socket */
+static char *excluded_domain;
+
+/* Free a response structure */
+
+void free_response(struct winbindd_response *response)
+{
+       /* Free any allocated extra_data */
+
+       if (response)
+               SAFE_FREE(response->extra_data);
+}
+
+/*
+  smbd needs to be able to exclude lookups for its own domain
+*/
+void winbind_exclude_domain(const char *domain)
+{
+       SAFE_FREE(excluded_domain);
+       excluded_domain = strdup(domain);
+}
+
+
+/* Initialise a request structure */
+
+void init_request(struct winbindd_request *request, int request_type)
+{
+        static char *domain_env;
+        static BOOL initialised;
+
+       request->length = sizeof(struct winbindd_request);
+
+       request->cmd = (enum winbindd_cmd)request_type;
+       request->pid = getpid();
+       request->domain[0] = '\0';
+
+       if (!initialised) {
+               initialised = True;
+               domain_env = getenv(WINBINDD_DOMAIN_ENV);
+       }
+
+       if (domain_env) {
+               strncpy(request->domain, domain_env,
+                       sizeof(request->domain) - 1);
+               request->domain[sizeof(request->domain) - 1] = '\0';
+       }
+}
+
+/* Initialise a response structure */
+
+void init_response(struct winbindd_response *response)
+{
+       /* Initialise return value */
+
+       response->result = WINBINDD_ERROR;
+}
+
+/* Close established socket */
+
+void close_sock(void)
+{
+       if (winbindd_fd != -1) {
+               close(winbindd_fd);
+               winbindd_fd = -1;
+       }
+}
+
+/* Connect to winbindd socket */
+
+int winbind_open_pipe_sock(void)
+{
+       struct sockaddr_un sunaddr;
+       static pid_t our_pid;
+       struct stat st;
+       pstring path;
+       
+       if (our_pid != getpid()) {
+               close_sock();
+               our_pid = getpid();
+       }
+       
+       if (winbindd_fd != -1) {
+               return winbindd_fd;
+       }
+       
+       /* Check permissions on unix socket directory */
+       
+       if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) {
+               return -1;
+       }
+       
+       if (!S_ISDIR(st.st_mode) || 
+           (st.st_uid != 0 && st.st_uid != geteuid())) {
+               return -1;
+       }
+       
+       /* Connect to socket */
+       
+       strncpy(path, WINBINDD_SOCKET_DIR, sizeof(path) - 1);
+       path[sizeof(path) - 1] = '\0';
+       
+       strncat(path, "/", sizeof(path) - 1);
+       path[sizeof(path) - 1] = '\0';
+       
+       strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1);
+       path[sizeof(path) - 1] = '\0';
+       
+       ZERO_STRUCT(sunaddr);
+       sunaddr.sun_family = AF_UNIX;
+       strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1);
+       
+       /* If socket file doesn't exist, don't bother trying to connect
+          with retry.  This is an attempt to make the system usable when
+          the winbindd daemon is not running. */
+
+       if (lstat(path, &st) == -1) {
+               return -1;
+       }
+       
+       /* Check permissions on unix socket file */
+       
+       if (!S_ISSOCK(st.st_mode) || 
+           (st.st_uid != 0 && st.st_uid != geteuid())) {
+               return -1;
+       }
+       
+       /* Connect to socket */
+       
+       if ((winbindd_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+               return -1;
+       }
+       
+       if (connect(winbindd_fd, (struct sockaddr *)&sunaddr, 
+                   sizeof(sunaddr)) == -1) {
+               close_sock();
+               return -1;
+       }
+        
+       return winbindd_fd;
+}
+
+/* Write data to winbindd socket with timeout */
+
+int write_sock(void *buffer, int count)
+{
+       int result, nwritten;
+       
+       /* Open connection to winbind daemon */
+       
+ restart:
+       
+       if (winbind_open_pipe_sock() == -1) {
+               return -1;
+       }
+       
+       /* Write data to socket */
+       
+       nwritten = 0;
+       
+       while(nwritten < count) {
+               struct timeval tv;
+               fd_set r_fds;
+               
+               /* Catch pipe close on other end by checking if a read()
+                  call would not block by calling select(). */
+
+               FD_ZERO(&r_fds);
+               FD_SET(winbindd_fd, &r_fds);
+               ZERO_STRUCT(tv);
+               
+               if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) {
+                       close_sock();
+                       return -1;                   /* Select error */
+               }
+               
+               /* Write should be OK if fd not available for reading */
+               
+               if (!FD_ISSET(winbindd_fd, &r_fds)) {
+                       
+                       /* Do the write */
+                       
+                       result = write(winbindd_fd,
+                                      (char *)buffer + nwritten, 
+                                      count - nwritten);
+                       
+                       if ((result == -1) || (result == 0)) {
+                               
+                               /* Write failed */
+                               
+                               close_sock();
+                               return -1;
+                       }
+                       
+                       nwritten += result;
+                       
+               } else {
+                       
+                       /* Pipe has closed on remote end */
+                       
+                       close_sock();
+                       goto restart;
+               }
+       }
+       
+       return nwritten;
+}
+
+/* Read data from winbindd socket with timeout */
+
+static int read_sock(void *buffer, int count)
+{
+       int result = 0, nread = 0;
+
+       /* Read data from socket */
+       
+       while(nread < count) {
+               
+               result = read(winbindd_fd, (char *)buffer + nread, 
+                             count - nread);
+               
+               if ((result == -1) || (result == 0)) {
+                       
+                       /* Read failed.  I think the only useful thing we
+                          can do here is just return -1 and fail since the
+                          transaction has failed half way through. */
+                       
+                       close_sock();
+                       return -1;
+               }
+               
+               nread += result;
+       }
+       
+       return result;
+}
+
+/* Read reply */
+
+int read_reply(struct winbindd_response *response)
+{
+       int result1, result2 = 0;
+
+       if (!response) {
+               return -1;
+       }
+       
+       /* Read fixed length response */
+       
+       if ((result1 = read_sock(response, sizeof(struct winbindd_response)))
+           == -1) {
+               
+               return -1;
+       }
+       
+       /* We actually send the pointer value of the extra_data field from
+          the server.  This has no meaning in the client's address space
+          so we clear it out. */
+
+       response->extra_data = NULL;
+
+       /* Read variable length response */
+       
+       if (response->length > sizeof(struct winbindd_response)) {
+               int extra_data_len = response->length - 
+                       sizeof(struct winbindd_response);
+               
+               /* Mallocate memory for extra data */
+               
+               if (!(response->extra_data = malloc(extra_data_len))) {
+                       return -1;
+               }
+               
+               if ((result2 = read_sock(response->extra_data, extra_data_len))
+                   == -1) {
+                       free_response(response);
+                       return -1;
+               }
+       }
+       
+       /* Return total amount of data read */
+       
+       return result1 + result2;
+}
+
+/* 
+ * send simple types of requests 
+ */
+
+NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request)
+{
+       struct winbindd_request lrequest;
+
+       /* Check for our tricky environment variable */
+
+       if (getenv(WINBINDD_DONT_ENV)) {
+               return NSS_STATUS_NOTFOUND;
+       }
+
+       /* smbd may have excluded this domain */
+       if (excluded_domain && 
+           strcasecmp(excluded_domain, request->domain) == 0) {
+               return NSS_STATUS_NOTFOUND;
+       }
+
+       if (!request) {
+               ZERO_STRUCT(lrequest);
+               request = &lrequest;
+       }
+       
+       /* Fill in request and send down pipe */
+
+       init_request(request, req_type);
+       
+       if (write_sock(request, sizeof(*request)) == -1) {
+               return NSS_STATUS_UNAVAIL;
+       }
+       
+       return NSS_STATUS_SUCCESS;
+}
+
+/*
+ * Get results from winbindd request
+ */
+
+NSS_STATUS winbindd_get_response(struct winbindd_response *response)
+{
+       struct winbindd_response lresponse;
+
+       if (!response) {
+               ZERO_STRUCT(lresponse);
+               response = &lresponse;
+       }
+
+       init_response(response);
+
+       /* Wait for reply */
+       if (read_reply(response) == -1) {
+               return NSS_STATUS_UNAVAIL;
+       }
+
+       /* Throw away extra data if client didn't request it */
+       if (response == &lresponse) {
+               free_response(response);
+       }
+
+       /* Copy reply data from socket */
+       if (response->result != WINBINDD_OK) {
+               return NSS_STATUS_NOTFOUND;
+       }
+       
+       return NSS_STATUS_SUCCESS;
+}
+
+/* Handle simple types of requests */
+
+NSS_STATUS winbindd_request(int req_type, 
+                                struct winbindd_request *request,
+                                struct winbindd_response *response)
+{
+       NSS_STATUS status;
+
+       status = winbindd_send_request(req_type, request);
+       if (status != NSS_STATUS_SUCCESS) 
+               return(status);
+       return winbindd_get_response(response);
+}
diff --git a/helpers/basic_auth/winbind/wbntlm.h b/helpers/basic_auth/winbind/wbntlm.h
new file mode 100644 (file)
index 0000000..1b01f47
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * (C) 2000 Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it>,
+ *
+ * Distributed freely under the terms of the GNU General Public License,
+ * version 2. See the file COPYING for licensing details
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ */
+
+#ifndef _WBNTLM_H_
+#define _WBNTLM_H_
+
+#include "config.h"
+#include "ntlmauth.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+/*************** CONFIGURATION ***************/
+#ifndef DEBUG
+#define DEBUG
+#endif
+
+/* the attempted entropy source. If it doesn't exist, random() is uesed */
+#define ENTROPY_SOURCE "/dev/urandom"
+
+#define DOMAIN "GCSINT"         /* TODO: fix ntlm_make_challenge */
+
+/************* END CONFIGURATION *************/
+
+/* Debugging stuff */
+extern char *myname;
+static char *__foo;
+extern pid_t mypid;
+extern char debug_enabled;
+
+#ifdef DEBUG
+#define __DO_DEBUG 1
+#else
+#define __DO_DEBUG 0
+#endif
+
+#ifdef __GNUC__     /* this is really a gcc-ism */
+#define warn(X...)  fprintf(stderr,"%s[%d](%s:%d): ", myname, mypid, \
+                    ((__foo=strrchr(__FILE__,'/'))==NULL?__FILE__:__foo+1),\
+                    __LINE__);\
+                    fprintf(stderr,X)
+#define debug(X...) if(__DO_DEBUG && debug_enabled) { warn(X); }
+#else /* __GNUC__ */
+static void
+debug(char *format,...)
+{
+}
+static void
+warn(char *format,...)
+{
+}
+#endif /* __GNUC__ */
+
+
+
+/* A couple of harmless helper macros */
+#define SEND(X) debug("sending '%s' to squid\n",X); printf(X "\n");
+#ifdef __GNUC__
+#define SEND2(X,Y...) debug("sending '" X "' to squid\n",Y); \
+                      printf(X "\n",Y)
+#else
+/* no gcc, no debugging. varargs macros are a gcc extension */
+#define SEND2 printf
+#endif
+
+typedef enum {
+  YES,
+  NO,
+  DONTKNOW
+} tristate;
+
+#define CHALLENGE_LEN 8
+#define BUFFER_SIZE 2010
+
+#endif /* _WBNTLM_H_ */
diff --git a/helpers/basic_auth/winbind/winbind_nss_config.h b/helpers/basic_auth/winbind/winbind_nss_config.h
new file mode 100644 (file)
index 0000000..ac80f4a
--- /dev/null
@@ -0,0 +1,148 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 2.0
+
+   Winbind daemon for ntdom nss module
+
+   Copyright (C) Tim Potter 2000
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#ifndef _WINBIND_NSS_CONFIG_H
+#define _WINBIND_NSS_CONFIG_H
+
+/* Include header files from data in config.h file */
+
+#include "config.h"
+
+#include <stdio.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_UNIXSOCKET
+#include <sys/un.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <pwd.h>
+#include "samba_nss.h"
+
+/* Declarations for functions in winbind_nss.c
+   needed in winbind_nss_solaris.c (solaris wrapper to nss) */
+
+NSS_STATUS _nss_winbind_setpwent(void);
+NSS_STATUS _nss_winbind_endpwent(void);
+NSS_STATUS _nss_winbind_getpwent_r(struct passwd* result, char* buffer,
+                                  size_t buflen, int* errnop);
+NSS_STATUS _nss_winbind_getpwuid_r(uid_t, struct passwd*, char* buffer,
+                                  size_t buflen, int* errnop);
+NSS_STATUS _nss_winbind_getpwnam_r(const char* name, struct passwd* result,
+                                  char* buffer, size_t buflen, int* errnop);
+
+NSS_STATUS _nss_winbind_setgrent(void);
+NSS_STATUS _nss_winbind_endgrent(void);
+NSS_STATUS _nss_winbind_getgrent_r(struct group* result, char* buffer,
+                                  size_t buflen, int* errnop);
+NSS_STATUS _nss_winbind_getgrnam_r(const char *name,
+                                  struct group *result, char *buffer,
+                                  size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid,
+                                  struct group *result, char *buffer,
+                                  size_t buflen, int *errnop);
+
+/* I'm trying really hard not to include anything from smb.h with the
+   result of some silly looking redeclaration of structures. */
+
+#ifndef _PSTRING
+#define _PSTRING
+#define PSTRING_LEN 1024
+#define FSTRING_LEN 256
+typedef char pstring[PSTRING_LEN];
+typedef char fstring[FSTRING_LEN];
+#endif
+
+#ifndef _BOOL
+#define _BOOL                  /* So we don't typedef BOOL again in vfs.h */
+#define False (0)
+#define True (1)
+#define Auto (2)
+typedef int BOOL;
+#endif
+
+#if !defined(uint32)
+#if (SIZEOF_INT == 4)
+#define uint32 unsigned int
+#elif (SIZEOF_LONG == 4)
+#define uint32 unsigned long
+#elif (SIZEOF_SHORT == 4)
+#define uint32 unsigned short
+#endif
+#endif
+
+#if !defined(uint16)
+#if (SIZEOF_SHORT == 4)
+#define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16;
+#else /* SIZEOF_SHORT != 4 */
+#define uint16 unsigned short
+#endif /* SIZEOF_SHORT != 4 */
+#endif
+
+#ifndef uint8
+#define uint8 unsigned char
+#endif
+
+/* zero a structure */
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
+
+/* zero a structure given a pointer to the structure */
+#define ZERO_STRUCTP(x) { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); }
+    
+/* Some systems (SCO) treat UNIX domain sockets as FIFOs */
+
+#ifndef S_IFSOCK
+#define S_IFSOCK S_IFIFO
+#endif
+
+#ifndef S_ISSOCK
+#define S_ISSOCK(mode)  ((mode & S_IFSOCK) == S_IFSOCK)
+#endif
+
+#endif
diff --git a/helpers/basic_auth/winbind/winbindd_nss.h b/helpers/basic_auth/winbind/winbindd_nss.h
new file mode 100644 (file)
index 0000000..a88b120
--- /dev/null
@@ -0,0 +1,202 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 2.0
+
+   Winbind daemon for ntdom nss module
+
+   Copyright (C) Tim Potter 2000
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#ifndef SAFE_FREE
+#define SAFE_FREE(x) do { if(x) {free(x); x=NULL;} } while(0)
+#endif
+
+#ifndef _WINBINDD_NTDOM_H
+#define _WINBINDD_NTDOM_H
+
+#define WINBINDD_SOCKET_NAME "pipe"            /* Name of PF_UNIX socket */
+#define WINBINDD_SOCKET_DIR  "/tmp/.winbindd"  /* Name of PF_UNIX dir */
+
+#define WINBINDD_DOMAIN_ENV  "WINBINDD_DOMAIN" /* Environment variables */
+#define WINBINDD_DONT_ENV    "_NO_WINBINDD"
+
+/* Update this when you change the interface.  */
+
+#define WINBIND_INTERFACE_VERSION 2
+
+/* Socket commands */
+
+enum winbindd_cmd {
+
+       WINBINDD_INTERFACE_VERSION,    /* Always a well known value */
+
+       /* Get users and groups */
+
+       WINBINDD_GETPWNAM,
+       WINBINDD_GETPWUID,
+       WINBINDD_GETGRNAM,
+       WINBINDD_GETGRGID,
+       WINBINDD_GETGROUPS,
+
+       /* Enumerate users and groups */
+
+       WINBINDD_SETPWENT,
+       WINBINDD_ENDPWENT,
+       WINBINDD_GETPWENT,
+       WINBINDD_SETGRENT,
+       WINBINDD_ENDGRENT,
+       WINBINDD_GETGRENT,
+
+       /* PAM authenticate and password change */
+
+       WINBINDD_PAM_AUTH,
+       WINBINDD_PAM_AUTH_CRAP,
+       WINBINDD_PAM_CHAUTHTOK,
+
+       /* List various things */
+
+       WINBINDD_LIST_USERS,         /* List w/o rid->id mapping */
+       WINBINDD_LIST_GROUPS,        /* Ditto */
+       WINBINDD_LIST_TRUSTDOM,
+
+       /* SID conversion */
+
+       WINBINDD_LOOKUPSID,
+       WINBINDD_LOOKUPNAME,
+
+       /* Lookup functions */
+
+       WINBINDD_SID_TO_UID,       
+       WINBINDD_SID_TO_GID,
+       WINBINDD_UID_TO_SID,
+       WINBINDD_GID_TO_SID,
+
+       /* Miscellaneous other stuff */
+
+       WINBINDD_CHECK_MACHACC,     /* Check machine account pw works */
+       WINBINDD_PING,              /* Just tell me winbind is running */
+       WINBINDD_INFO,              /* Various bit of info.  Currently just tidbits */
+
+       /* Placeholder for end of cmd list */
+
+       WINBINDD_NUM_CMDS
+};
+
+/* Winbind request structure */
+
+struct winbindd_request {
+       uint32 length;
+       enum winbindd_cmd cmd;   /* Winbindd command to execute */
+       pid_t pid;               /* pid of calling process */
+
+       union {
+               fstring username;    /* getpwnam */
+               fstring groupname;   /* getgrnam */
+               uid_t uid;           /* getpwuid, uid_to_sid */
+               gid_t gid;           /* getgrgid, gid_to_sid */
+               struct {
+                       fstring user;
+                       fstring pass;
+               } auth;              /* pam_winbind auth module */
+                struct {
+                        unsigned char chal[8];
+                        fstring user;
+                        fstring domain;
+                        fstring lm_resp;
+                        uint16 lm_resp_len;
+                        fstring nt_resp;
+                        uint16 nt_resp_len;
+                } auth_crap;
+                struct {
+                    fstring user;
+                    fstring oldpass;
+                    fstring newpass;
+                } chauthtok;         /* pam_winbind passwd module */
+               fstring sid;         /* lookupsid, sid_to_[ug]id */
+               fstring name;        /* lookupname */
+               uint32 num_entries;  /* getpwent, getgrent */
+       } data;
+       fstring domain;      /* {set,get,end}{pw,gr}ent() */
+};
+
+/* Response values */
+
+enum winbindd_result {
+       WINBINDD_ERROR,
+       WINBINDD_OK
+};
+
+/* Winbind response structure */
+
+struct winbindd_response {
+    
+       /* Header information */
+
+       uint32 length;                        /* Length of response */
+       enum winbindd_result result;          /* Result code */
+
+       /* Fixed length return data */
+       
+       union {
+               int interface_version;  /* Try to ensure this is always in the same spot... */
+               
+               /* getpwnam, getpwuid */
+               
+               struct winbindd_pw {
+                       fstring pw_name;
+                       fstring pw_passwd;
+                       uid_t pw_uid;
+                       gid_t pw_gid;
+                       fstring pw_gecos;
+                       fstring pw_dir;
+                       fstring pw_shell;
+               } pw;
+
+               /* getgrnam, getgrgid */
+
+               struct winbindd_gr {
+                       fstring gr_name;
+                       fstring gr_passwd;
+                       gid_t gr_gid;
+                       int num_gr_mem;
+                       int gr_mem_ofs;   /* offset to group membership */
+               } gr;
+
+               uint32 num_entries; /* getpwent, getgrent */
+               struct winbindd_sid {
+                       fstring sid;        /* lookupname, [ug]id_to_sid */
+                       int type;
+               } sid;
+               struct winbindd_name {
+                       fstring name;       /* lookupsid */
+                       int type;
+               } name;
+               uid_t uid;          /* sid_to_uid */
+               gid_t gid;          /* sid_to_gid */
+               struct winbindd_info {
+                       char winbind_separator;
+                       fstring samba_version;
+               } info;
+       } data;
+
+       /* Variable length return data */
+
+       void *extra_data;               /* getgrnam, getgrgid, getgrent */
+};
+
+#endif
index 249fbd2622a524aceb4c8ca80a6be44a52d7386c..131b3507712eb68d5450202ad8cf85e7a57c8908 100644 (file)
@@ -1,7 +1,7 @@
 #  Makefile for storage modules in the Squid Object Cache server
 #
-#  $Id: Makefile.am,v 1.4 2002/05/19 15:07:55 hno Exp $
+#  $Id: Makefile.am,v 1.5 2002/05/19 23:42:42 hno Exp $
 #
 
-DIST_SUBDIRS   = fakeauth no_check SMB
+DIST_SUBDIRS   = fakeauth no_check SMB winbind
 SUBDIRS                = @NTLM_AUTH_HELPERS@
diff --git a/helpers/ntlm_auth/winbind/Makefile.am b/helpers/ntlm_auth/winbind/Makefile.am
new file mode 100644 (file)
index 0000000..2bfd30f
--- /dev/null
@@ -0,0 +1,11 @@
+#
+#  Makefile for the Squid Object Cache server
+#
+#  $Id: Makefile.am,v 1.1 2002/05/19 23:42:42 hno Exp $
+#
+
+libexec_PROGRAMS = wb_ntlmauth
+wb_ntlmauth_SOURCES = wb_ntlm_auth.c wb_common.c
+INCLUDES = -I. -I$(top_builddir)/include -I$(top_srcdir)/include \
+    -I$(top_srcdir)/src
+LDADD = -L$(top_builddir)/lib -lmiscutil -lntlmauth -lm
diff --git a/helpers/ntlm_auth/winbind/patches/wb_common.patch b/helpers/ntlm_auth/winbind/patches/wb_common.patch
new file mode 100644 (file)
index 0000000..0977120
--- /dev/null
@@ -0,0 +1,11 @@
+--- samba-HEAD/source/nsswitch/wb_common.c     Sat Jan 12 23:12:11 2002
++++ squid-ntlm/src/auth/ntlm/helpers/winbind/wb_common.c       Sat Jan 12 23:45:03 2002
+@@ -25,6 +25,8 @@
+ #include "winbind_nss_config.h"
+ #include "winbindd_nss.h"
++#include "config.h"
++
+ /* Global variables.  These are effectively the client state information */
diff --git a/helpers/ntlm_auth/winbind/patches/winbind_nss_config.patch b/helpers/ntlm_auth/winbind/patches/winbind_nss_config.patch
new file mode 100644 (file)
index 0000000..209d4f1
--- /dev/null
@@ -0,0 +1,20 @@
+--- samba-HEAD/source/nsswitch/winbind_nss_config.h    Wed Sep  5 10:11:16 2001
++++ squid-ntlm/src/auth/ntlm/helpers/winbind/winbind_nss_config.h      Sat Nov 24 00:32:05 2001
+@@ -27,7 +27,7 @@
+ /* Include header files from data in config.h file */
+-#include <config.h>
++#include "config.h"
+ #include <stdio.h>
+@@ -63,7 +63,7 @@
+ #include <sys/stat.h>
+ #include <errno.h>
+ #include <pwd.h>
+-#include "nsswitch/nss.h"
++#include "samba_nss.h"
+ /* Declarations for functions in winbind_nss.c
+    needed in winbind_nss_solaris.c (solaris wrapper to nss) */
diff --git a/helpers/ntlm_auth/winbind/samba_nss.h b/helpers/ntlm_auth/winbind/samba_nss.h
new file mode 100644 (file)
index 0000000..6165e0b
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef _NSSWITCH_NSS_H
+#define _NSSWITCH_NSS_H
+/* 
+   Unix SMB/Netbios implementation.
+   Version 2.0
+
+   a common place to work out how to define NSS_STATUS on various
+   platforms
+
+   Copyright (C) Tim Potter 2000
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#ifdef HAVE_NSS_COMMON_H
+
+/* Sun Solaris */
+
+#include <nss_common.h>
+#include <nss_dbdefs.h>
+#include <nsswitch.h>
+
+typedef nss_status_t NSS_STATUS;
+
+#define NSS_STATUS_SUCCESS     NSS_SUCCESS
+#define NSS_STATUS_NOTFOUND    NSS_NOTFOUND
+#define NSS_STATUS_UNAVAIL     NSS_UNAVAIL
+#define NSS_STATUS_TRYAGAIN    NSS_TRYAGAIN
+
+#elif HAVE_NSS_H
+
+/* GNU */
+
+#include <nss.h>
+
+typedef enum nss_status NSS_STATUS;
+
+#elif HAVE_NS_API_H
+
+/* SGI IRIX */
+
+/* following required to prevent warnings of double definition
+ * of datum from ns_api.h
+*/
+#ifdef DATUM
+#define _DATUM_DEFINED
+#endif
+
+#include <ns_api.h>
+
+typedef enum
+{
+  NSS_STATUS_SUCCESS=NS_SUCCESS,
+  NSS_STATUS_NOTFOUND=NS_NOTFOUND,
+  NSS_STATUS_UNAVAIL=NS_UNAVAIL,
+  NSS_STATUS_TRYAGAIN=NS_TRYAGAIN
+} NSS_STATUS;
+
+#define NSD_MEM_STATIC 0
+#define NSD_MEM_VOLATILE 1
+#define NSD_MEM_DYNAMIC 2
+
+#elif defined(HPUX)
+/* HP-UX 11 */
+
+#include "nsswitch/hp_nss_common.h"
+#include "nsswitch/hp_nss_dbdefs.h"
+#include <nsswitch.h>
+
+#ifndef _HAVE_TYPEDEF_NSS_STATUS
+#define _HAVE_TYPEDEF_NSS_STATUS
+typedef nss_status_t NSS_STATUS;
+
+#define NSS_STATUS_SUCCESS     NSS_SUCCESS
+#define NSS_STATUS_NOTFOUND    NSS_NOTFOUND
+#define NSS_STATUS_UNAVAIL     NSS_UNAVAIL
+#define NSS_STATUS_TRYAGAIN    NSS_TRYAGAIN
+#endif /* HPUX */
+
+#else /* Nothing's defined. Neither gnu nor sun nor hp */
+
+typedef enum
+{
+  NSS_STATUS_SUCCESS=0,
+  NSS_STATUS_NOTFOUND=1,
+  NSS_STATUS_UNAVAIL=2,
+  NSS_STATUS_TRYAGAIN=3
+} NSS_STATUS;
+
+#endif
+
+#endif /* _NSSWITCH_NSS_H */
diff --git a/helpers/ntlm_auth/winbind/wb_common.c b/helpers/ntlm_auth/winbind/wb_common.c
new file mode 100644 (file)
index 0000000..1a1f5c0
--- /dev/null
@@ -0,0 +1,403 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 2.0
+
+   winbind client common code
+
+   Copyright (C) Tim Potter 2000
+   Copyright (C) Andrew Tridgell 2000
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#include "winbind_nss_config.h"
+#include "winbindd_nss.h"
+#include "config.h"
+
+
+/* Global variables.  These are effectively the client state information */
+
+int winbindd_fd = -1;          /* fd for winbindd socket */
+static char *excluded_domain;
+
+/* Free a response structure */
+
+void
+free_response(struct winbindd_response *response)
+{
+    /* Free any allocated extra_data */
+
+    if (response)
+       SAFE_FREE(response->extra_data);
+}
+
+/*
+  smbd needs to be able to exclude lookups for its own domain
+*/
+void
+winbind_exclude_domain(const char *domain)
+{
+    SAFE_FREE(excluded_domain);
+    excluded_domain = strdup(domain);
+}
+
+
+/* Initialise a request structure */
+
+void
+init_request(struct winbindd_request *request, int request_type)
+{
+    static char *domain_env;
+    static BOOL initialised;
+
+    request->length = sizeof(struct winbindd_request);
+
+    request->cmd = (enum winbindd_cmd) request_type;
+    request->pid = getpid();
+    request->domain[0] = '\0';
+
+    if (!initialised) {
+       initialised = True;
+       domain_env = getenv(WINBINDD_DOMAIN_ENV);
+    }
+
+    if (domain_env) {
+       strncpy(request->domain, domain_env, sizeof(request->domain) - 1);
+       request->domain[sizeof(request->domain) - 1] = '\0';
+    }
+}
+
+/* Initialise a response structure */
+
+void
+init_response(struct winbindd_response *response)
+{
+    /* Initialise return value */
+
+    response->result = WINBINDD_ERROR;
+}
+
+/* Close established socket */
+
+void
+close_sock(void)
+{
+    if (winbindd_fd != -1) {
+       close(winbindd_fd);
+       winbindd_fd = -1;
+    }
+}
+
+/* Connect to winbindd socket */
+
+int
+winbind_open_pipe_sock(void)
+{
+    struct sockaddr_un sunaddr;
+    static pid_t our_pid;
+    struct stat st;
+    pstring path;
+
+    if (our_pid != getpid()) {
+       close_sock();
+       our_pid = getpid();
+    }
+
+    if (winbindd_fd != -1) {
+       return winbindd_fd;
+    }
+
+    /* Check permissions on unix socket directory */
+
+    if (lstat(WINBINDD_SOCKET_DIR, &st) == -1) {
+       return -1;
+    }
+
+    if (!S_ISDIR(st.st_mode) || (st.st_uid != 0 && st.st_uid != geteuid())) {
+       return -1;
+    }
+
+    /* Connect to socket */
+
+    strncpy(path, WINBINDD_SOCKET_DIR, sizeof(path) - 1);
+    path[sizeof(path) - 1] = '\0';
+
+    strncat(path, "/", sizeof(path) - 1);
+    path[sizeof(path) - 1] = '\0';
+
+    strncat(path, WINBINDD_SOCKET_NAME, sizeof(path) - 1);
+    path[sizeof(path) - 1] = '\0';
+
+    ZERO_STRUCT(sunaddr);
+    sunaddr.sun_family = AF_UNIX;
+    strncpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path) - 1);
+
+    /* If socket file doesn't exist, don't bother trying to connect
+     * with retry.  This is an attempt to make the system usable when
+     * the winbindd daemon is not running. */
+
+    if (lstat(path, &st) == -1) {
+       return -1;
+    }
+
+    /* Check permissions on unix socket file */
+
+    if (!S_ISSOCK(st.st_mode) || (st.st_uid != 0 && st.st_uid != geteuid())) {
+       return -1;
+    }
+
+    /* Connect to socket */
+
+    if ((winbindd_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+       return -1;
+    }
+
+    if (connect(winbindd_fd, (struct sockaddr *) &sunaddr,
+           sizeof(sunaddr)) == -1) {
+       close_sock();
+       return -1;
+    }
+
+    return winbindd_fd;
+}
+
+/* Write data to winbindd socket with timeout */
+
+int
+write_sock(void *buffer, int count)
+{
+    int result, nwritten;
+
+    /* Open connection to winbind daemon */
+
+  restart:
+
+    if (winbind_open_pipe_sock() == -1) {
+       return -1;
+    }
+
+    /* Write data to socket */
+
+    nwritten = 0;
+
+    while (nwritten < count) {
+       struct timeval tv;
+       fd_set r_fds;
+
+       /* Catch pipe close on other end by checking if a read()
+        * call would not block by calling select(). */
+
+       FD_ZERO(&r_fds);
+       FD_SET(winbindd_fd, &r_fds);
+       ZERO_STRUCT(tv);
+
+       if (select(winbindd_fd + 1, &r_fds, NULL, NULL, &tv) == -1) {
+           close_sock();
+           return -1;          /* Select error */
+       }
+
+       /* Write should be OK if fd not available for reading */
+
+       if (!FD_ISSET(winbindd_fd, &r_fds)) {
+
+           /* Do the write */
+
+           result = write(winbindd_fd,
+               (char *) buffer + nwritten, count - nwritten);
+
+           if ((result == -1) || (result == 0)) {
+
+               /* Write failed */
+
+               close_sock();
+               return -1;
+           }
+
+           nwritten += result;
+
+       } else {
+
+           /* Pipe has closed on remote end */
+
+           close_sock();
+           goto restart;
+       }
+    }
+
+    return nwritten;
+}
+
+/* Read data from winbindd socket with timeout */
+
+static int
+read_sock(void *buffer, int count)
+{
+    int result = 0, nread = 0;
+
+    /* Read data from socket */
+
+    while (nread < count) {
+
+       result = read(winbindd_fd, (char *) buffer + nread, count - nread);
+
+       if ((result == -1) || (result == 0)) {
+
+           /* Read failed.  I think the only useful thing we
+            * can do here is just return -1 and fail since the
+            * transaction has failed half way through. */
+
+           close_sock();
+           return -1;
+       }
+
+       nread += result;
+    }
+
+    return result;
+}
+
+/* Read reply */
+
+int
+read_reply(struct winbindd_response *response)
+{
+    int result1, result2 = 0;
+
+    if (!response) {
+       return -1;
+    }
+
+    /* Read fixed length response */
+
+    if ((result1 = read_sock(response, sizeof(struct winbindd_response)))
+       == -1) {
+
+       return -1;
+    }
+
+    /* We actually send the pointer value of the extra_data field from
+     * the server.  This has no meaning in the client's address space
+     * so we clear it out. */
+
+    response->extra_data = NULL;
+
+    /* Read variable length response */
+
+    if (response->length > sizeof(struct winbindd_response)) {
+       int extra_data_len = response->length -
+           sizeof(struct winbindd_response);
+
+       /* Mallocate memory for extra data */
+
+       if (!(response->extra_data = malloc(extra_data_len))) {
+           return -1;
+       }
+
+       if ((result2 = read_sock(response->extra_data, extra_data_len))
+           == -1) {
+           free_response(response);
+           return -1;
+       }
+    }
+
+    /* Return total amount of data read */
+
+    return result1 + result2;
+}
+
+/* 
+ * send simple types of requests 
+ */
+
+NSS_STATUS
+winbindd_send_request(int req_type, struct winbindd_request * request)
+{
+    struct winbindd_request lrequest;
+
+    /* Check for our tricky environment variable */
+
+    if (getenv(WINBINDD_DONT_ENV)) {
+       return NSS_STATUS_NOTFOUND;
+    }
+
+    /* smbd may have excluded this domain */
+    if (excluded_domain && strcasecmp(excluded_domain, request->domain) == 0) {
+       return NSS_STATUS_NOTFOUND;
+    }
+
+    if (!request) {
+       ZERO_STRUCT(lrequest);
+       request = &lrequest;
+    }
+
+    /* Fill in request and send down pipe */
+
+    init_request(request, req_type);
+
+    if (write_sock(request, sizeof(*request)) == -1) {
+       return NSS_STATUS_UNAVAIL;
+    }
+
+    return NSS_STATUS_SUCCESS;
+}
+
+/*
+ * Get results from winbindd request
+ */
+
+NSS_STATUS
+winbindd_get_response(struct winbindd_response * response)
+{
+    struct winbindd_response lresponse;
+
+    if (!response) {
+       ZERO_STRUCT(lresponse);
+       response = &lresponse;
+    }
+
+    init_response(response);
+
+    /* Wait for reply */
+    if (read_reply(response) == -1) {
+       return NSS_STATUS_UNAVAIL;
+    }
+
+    /* Throw away extra data if client didn't request it */
+    if (response == &lresponse) {
+       free_response(response);
+    }
+
+    /* Copy reply data from socket */
+    if (response->result != WINBINDD_OK) {
+       return NSS_STATUS_NOTFOUND;
+    }
+
+    return NSS_STATUS_SUCCESS;
+}
+
+/* Handle simple types of requests */
+
+NSS_STATUS
+winbindd_request(int req_type,
+    struct winbindd_request * request, struct winbindd_response * response)
+{
+    NSS_STATUS status;
+
+    status = winbindd_send_request(req_type, request);
+    if (status != NSS_STATUS_SUCCESS)
+       return (status);
+    return winbindd_get_response(response);
+}
diff --git a/helpers/ntlm_auth/winbind/wb_ntlm_auth.c b/helpers/ntlm_auth/winbind/wb_ntlm_auth.c
new file mode 100644 (file)
index 0000000..247c824
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * (C) 2000 Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it>
+ * (C) 2002 Andrew Bartlett <abartlet@samba.org>
+ *
+ * Distributed freely under the terms of the GNU General Public License,
+ * version 2. See the file COPYING for licensing details
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+/*
+ * TODO:
+ * -add handling of the -d flag
+ * -move all squid-helper-protocol-related operations to helper functions
+ * -remove the hard-coded target NT domain name
+ *
+ * - MAYBE move squid-helper-protocol-related opetations to an external
+ *   library?
+ */
+
+
+#include "wbntlm.h"
+#include "util.h"
+/* stdio.h is included in wbntlm.h */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <sys/time.h>          /* for gettimeofday */
+#include <errno.h>             /* BUG: is this portable? */
+
+#ifdef HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+
+#include "winbind_nss_config.h"
+#include "winbindd_nss.h"
+
+#ifndef min
+#define min(x,y) ((x)<(y)?(x):(y))
+#endif
+
+void
+authfail(char *domain, char *user, char *reason)
+{
+    /* TODO: -move away from SEND-type gcc-isms
+     *       -prepare for protocol extension as soon as rbcollins is ready
+     */
+    SEND2("NA %s\\%s auth failure because: %s", domain, user, reason);
+}
+
+void
+authok(const char *domain, const char *user)
+{
+    SEND2("AF %s\\%s", domain, user);
+}
+
+void
+sendchallenge(const char *challenge)
+{
+    SEND2("TT %s", challenge);
+}
+
+void
+helperfail(const char *reason)
+{
+    SEND2("BH %s", reason);
+}
+
+char debug_enabled = 0;
+char *myname;
+pid_t mypid;
+
+static void
+lc(char *string)
+{
+    char *p = string, c;
+    while ((c = *p)) {
+       *p = tolower(c);
+       p++;
+    }
+}
+
+static void
+uc(char *string)
+{
+    char *p = string, c;
+    while ((c = *p)) {
+       *p = toupper(c);
+       p++;
+    }
+}
+
+
+
+NSS_STATUS winbindd_request(int req_type,
+    struct winbindd_request *request, struct winbindd_response *response);
+
+
+static tristate have_urandom = DONTKNOW;
+FILE *urandom_file = NULL;
+
+void
+init_random()
+{
+    if (have_urandom == DONTKNOW) {
+       int result = 0;
+       struct stat st;
+       result = stat(ENTROPY_SOURCE, &st);
+       if (result != 0 || !(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
+           debug("Entropy source " ENTROPY_SOURCE " is unavailable\n");
+           have_urandom = NO;
+       }
+       if ((urandom_file = fopen(ENTROPY_SOURCE, "r")) == NULL) {
+           unsigned int seed;
+           struct timeval t;
+           warn("Can't open entropy source " ENTROPY_SOURCE "\n");
+           have_urandom = NO;
+           gettimeofday(&t, NULL);
+           seed = squid_random() * getpid() * t.tv_sec * t.tv_usec;
+           squid_srandom(seed);
+       } else {
+           have_urandom = YES;
+       }
+    }
+}
+
+static unsigned char challenge[CHALLENGE_LEN + 1];
+static char *
+build_challenge(void)
+{
+    size_t gotchars;
+    unsigned char j;
+    switch (have_urandom) {
+    case YES:
+       if ((gotchars = fread(&challenge, CHALLENGE_LEN, 1, urandom_file)) == 0) {
+           /* couldn't get a challenge. Fall back to random() and friends.
+            * notice that even a single changed byte is good enough for us */
+           have_urandom = NO;
+           return build_challenge();
+       }
+       return challenge;
+    case NO:
+       if (!(squid_random() % 100)) {  /* sometimes */
+           init_random();
+       }
+       for (j = 0; j < CHALLENGE_LEN; j++)
+           challenge[j] = (unsigned char) (squid_random() % 256);
+       return challenge;
+    default:
+       warn("Critical internal error. Somebody forgot to initialize "
+           "the random system. Exiting.\n");
+       exit(1);
+    }
+}
+
+lstring lmhash, nthash;
+static char have_nthash = 0;   /* simple flag. A tad dirty.. */
+
+void
+do_authenticate(ntlm_authenticate * auth, int auth_length)
+{
+    lstring tmp;
+    int tocopy;
+    NSS_STATUS winbindd_result;
+    struct winbindd_request request;
+    struct winbindd_response response;
+    char *domain, *user;
+
+    memset(&request, 0, sizeof(struct winbindd_request));
+
+    memset(&response, 0, sizeof(struct winbindd_response));
+
+    /* domain */
+    tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->domain);
+    if (tmp.str == NULL || tmp.l == 0) {       /* no domain supplied */
+       request.data.auth_crap.domain[0] = 0;
+    } else {
+       tocopy = min(tmp.l + 1, sizeof(fstring));
+       xstrncpy(request.data.auth_crap.domain, tmp.str, tocopy);
+    }
+
+    domain = request.data.auth_crap.domain;    /* just a shortcut */
+
+    /* username */
+    tmp = ntlm_fetch_string((char *) auth, auth_length, &auth->user);
+    if (tmp.str == NULL || tmp.l == 0) {
+       authfail(domain, "-", "No username in request");
+       return;
+    }
+
+    tocopy = min(sizeof(fstring), tmp.l + 1);
+    xstrncpy(request.data.auth_crap.user, tmp.str, tocopy);
+    user = request.data.auth_crap.user;
+
+    /* now the LM hash */
+    lmhash = ntlm_fetch_string((char *) auth, auth_length, &auth->lmresponse);
+    switch (lmhash.l) {
+    case 0:
+       warn("No lm hash provided by user %s\\%s\n", domain, user);
+       request.data.auth_crap.lm_resp_len = 0;
+       break;
+    case 24:
+       memcpy(request.data.auth_crap.lm_resp, lmhash.str, 24);
+       request.data.auth_crap.lm_resp_len = 24;
+       break;
+    default:
+       authfail(domain, user, "Broken LM hash response");
+       return;
+    }
+
+    nthash = ntlm_fetch_string((char *) auth, auth_length, &auth->ntresponse);
+    switch (nthash.l) {
+    case 0:
+       debug("no nthash\n");
+       request.data.auth_crap.nt_resp_len = 0;
+       break;
+    case 24:
+       memcpy(request.data.auth_crap.nt_resp, nthash.str, 24);
+       request.data.auth_crap.nt_resp_len = 24;
+       break;
+    default:
+       debug("nthash len = %d\n", nthash.l);
+       authfail(domain, user, "Broken NT hash response");
+       return;
+    }
+
+    debug("Checking user '%s\\%s' lmhash len =%d, have_nthash=%d, "
+       "nthash len=%d\n", domain, user, lmhash.l, have_nthash, nthash.l);
+
+    memcpy(request.data.auth_crap.chal, challenge, CHALLENGE_LEN);
+
+    winbindd_result = winbindd_request(WINBINDD_PAM_AUTH_CRAP,
+       &request, &response);
+    debug("winbindd result: %d\n", winbindd_result);
+
+    if (winbindd_result == WINBINDD_OK) {
+       lc(domain);
+       lc(user);
+       authok(domain, user);
+    } else {
+       char error_buf[200];
+       snprintf(error_buf, sizeof(error_buf), "Authentication Failure (%s)",
+           response.data.auth.error_string);
+       authfail(domain, user, error_buf);
+    }
+    return;                    /* useless */
+}
+
+void
+manage_request(char *target_domain)
+{
+    char buf[BUFFER_SIZE + 1];
+    char *c, *decoded;
+    ntlmhdr *fast_header;
+
+
+    if (fgets(buf, BUFFER_SIZE, stdin) == NULL) {
+       warn("fgets() failed! dying..... errno=%d (%s)\n", errno,
+           strerror(errno));
+       exit(1);                /* BIIG buffer */
+    }
+
+    c = memchr(buf, '\n', BUFFER_SIZE);
+    if (c)
+       *c = '\0';
+    else {
+       warn("No newline in '%s'. Dying.\n", buf);
+       exit(1);
+    }
+
+    debug("Got '%s' from squid.\n", buf);
+    if (memcmp(buf, "YR", 2) == 0) {   /* refresh-request */
+       sendchallenge(ntlm_make_challenge(target_domain, NULL,
+               build_challenge(), CHALLENGE_LEN));
+       return;
+    }
+    if (strncmp(buf, "KK ", 3) != 0) { /* not an auth-request */
+       helperfail("illegal request received");
+       warn("Illegal request received: '%s'\n", buf);
+       return;
+    }
+    /* At this point I'm sure it's a KK */
+    decoded = base64_decode(buf + 3);
+    if (!decoded) {            /* decoding failure, return error */
+       authfail("-", "-", "Auth-format error, base64-decoding error");
+       return;
+    }
+    fast_header = (struct _ntlmhdr *) decoded;
+
+    /* sanity-check: it IS a NTLMSSP packet, isn't it? */
+    if (memcmp(fast_header->signature, "NTLMSSP", 8) != 0) {
+       authfail("-", "-", "Broken NTLM packet, missing NTLMSSP signature");
+       return;
+    }
+    /* Understand what we got */
+    switch (fast_header->type) {
+    case NTLM_NEGOTIATE:
+       authfail("-", "-", "Received neg-request while expecting auth packet");
+       return;
+    case NTLM_CHALLENGE:
+       authfail("-", "-", "Received challenge. Refusing to abide");
+       return;
+    case NTLM_AUTHENTICATE:
+       do_authenticate((ntlm_authenticate *) decoded,
+           (strlen(buf) - 3) * 3 / 4);
+       return;
+    default:
+       helperfail("Unknown authentication packet type");
+       return;
+    }
+    /* notreached */
+    return;
+}
+
+static char *
+get_winbind_domain(void)
+{
+    struct winbindd_response response;
+    char *domain;
+
+    ZERO_STRUCT(response);
+
+    /* Send off request */
+
+    if (winbindd_request(WINBINDD_DOMAIN_NAME, NULL, &response) !=
+       NSS_STATUS_SUCCESS) {
+       warn("could not obtain winbind domain name!\n");
+       exit(1);
+    }
+
+    domain = strdup(response.data.domain_name);
+    uc(domain);
+
+    warn("target domain is %s\n", domain);
+    return domain;
+}
+
+char *
+process_options(int argc, char *argv[])
+{
+    int opt;
+    char *target_domain = NULL;
+
+    while (-1 != (opt = getopt(argc, argv, "d"))) {
+       switch (opt) {
+       case 'd':
+           debug_enabled = 1;
+           break;
+       default:
+           warn("Unknown option: -%c. Exiting\n", opt);
+           exit(1);
+           break;              /* not reached */
+       }
+       if (optind >= argc - 1) {
+           target_domain = argv[optind];
+           warn("target domain is %s\n", target_domain);
+       }
+    }
+    return target_domain;
+}
+
+void
+check_winbindd()
+{
+    NSS_STATUS r;
+    struct winbindd_request request;
+    struct winbindd_response response;
+    r = winbindd_request(WINBINDD_INTERFACE_VERSION, &request, &response);
+    if (r != WINBINDD_OK) {
+       warn("Can't contact winbindd. Dying\n");
+       exit(1);
+    }
+    if (response.data.interface_version != WINBIND_INTERFACE_VERSION) {
+       warn("Winbind protocol mismatch. Align squid and samba. Dying\n");
+       exit(1);
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+    char *target_domain;
+    if (argc > 0) {            /* should always be true */
+       myname = strrchr(argv[0], '/');
+       if (myname == NULL)
+           myname = argv[0];
+       else
+           myname++;
+    } else {
+       myname = "(unknown)";
+    }
+    mypid = getpid();
+    target_domain = process_options(argc, argv);
+    debug("ntlm winbindd auth helper build " __DATE__ ", " __TIME__
+       " starting up...\n");
+
+    check_winbindd();
+
+    if (target_domain == NULL) {
+       target_domain = get_winbind_domain();
+    }
+
+    /* initialize FDescs */
+    setbuf(stdout, NULL);
+    setbuf(stderr, NULL);
+    init_random();
+    while (1) {
+       manage_request(target_domain);
+    }
+    return 0;
+}
diff --git a/helpers/ntlm_auth/winbind/wbntlm.h b/helpers/ntlm_auth/winbind/wbntlm.h
new file mode 100644 (file)
index 0000000..7edccbc
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * (C) 2000 Francesco Chemolli <kinkie@kame.usr.dsi.unimi.it>,
+ *
+ * Distributed freely under the terms of the GNU General Public License,
+ * version 2. See the file COPYING for licensing details
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ */
+
+#ifndef _WBNTLM_H_
+#define _WBNTLM_H_
+
+#include "config.h"
+#include "ntlmauth.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+/*************** CONFIGURATION ***************/
+#ifndef DEBUG
+#define DEBUG
+#endif
+
+/* the attempted entropy source. If it doesn't exist, random() is uesed */
+#define ENTROPY_SOURCE "/dev/urandom"
+
+/************* END CONFIGURATION *************/
+
+/* Debugging stuff */
+extern char *myname;
+static char *__foo;
+extern pid_t mypid;
+extern char debug_enabled;
+
+#ifdef DEBUG
+#define __DO_DEBUG 1
+#else
+#define __DO_DEBUG 0
+#endif
+
+#if defined(__GNUC__) || defined(__ICC)    /* this is really a gcc-ism */
+#define warn(X...)  fprintf(stderr,"%s[%d](%s:%d): ", myname, mypid, \
+                    ((__foo=strrchr(__FILE__,'/'))==NULL?__FILE__:__foo+1),\
+                    __LINE__);\
+                    fprintf(stderr,X)
+#define debug(X...) if(__DO_DEBUG && debug_enabled) { warn(X); }
+#else /* __GNUC__ */
+static void
+debug(char *format,...)
+{
+}
+static void
+warn(char *format,...)
+{
+}
+#endif /* __GNUC__ */
+
+
+
+/* A couple of harmless helper macros */
+#define SEND(X) debug("sending '%s' to squid\n",X); printf(X "\n");
+#if defined(__GNUC__) || defined (__ICC)
+#define SEND2(X,Y...) debug("sending '" X "' to squid\n",Y); \
+                      printf(X "\n",Y)
+#else
+/* no gcc, no debugging. varargs macros are a gcc extension */
+#define SEND2 printf
+#endif
+
+typedef enum {
+  YES,
+  NO,
+  DONTKNOW
+} tristate;
+
+#define CHALLENGE_LEN 8
+#define BUFFER_SIZE 2010
+
+#endif /* _WBNTLM_H_ */
diff --git a/helpers/ntlm_auth/winbind/winbind_nss_config.h b/helpers/ntlm_auth/winbind/winbind_nss_config.h
new file mode 100644 (file)
index 0000000..ac80f4a
--- /dev/null
@@ -0,0 +1,148 @@
+/* 
+   Unix SMB/Netbios implementation.
+   Version 2.0
+
+   Winbind daemon for ntdom nss module
+
+   Copyright (C) Tim Potter 2000
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#ifndef _WINBIND_NSS_CONFIG_H
+#define _WINBIND_NSS_CONFIG_H
+
+/* Include header files from data in config.h file */
+
+#include "config.h"
+
+#include <stdio.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+
+#ifdef HAVE_UNIXSOCKET
+#include <sys/un.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <pwd.h>
+#include "samba_nss.h"
+
+/* Declarations for functions in winbind_nss.c
+   needed in winbind_nss_solaris.c (solaris wrapper to nss) */
+
+NSS_STATUS _nss_winbind_setpwent(void);
+NSS_STATUS _nss_winbind_endpwent(void);
+NSS_STATUS _nss_winbind_getpwent_r(struct passwd* result, char* buffer,
+                                  size_t buflen, int* errnop);
+NSS_STATUS _nss_winbind_getpwuid_r(uid_t, struct passwd*, char* buffer,
+                                  size_t buflen, int* errnop);
+NSS_STATUS _nss_winbind_getpwnam_r(const char* name, struct passwd* result,
+                                  char* buffer, size_t buflen, int* errnop);
+
+NSS_STATUS _nss_winbind_setgrent(void);
+NSS_STATUS _nss_winbind_endgrent(void);
+NSS_STATUS _nss_winbind_getgrent_r(struct group* result, char* buffer,
+                                  size_t buflen, int* errnop);
+NSS_STATUS _nss_winbind_getgrnam_r(const char *name,
+                                  struct group *result, char *buffer,
+                                  size_t buflen, int *errnop);
+NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid,
+                                  struct group *result, char *buffer,
+                                  size_t buflen, int *errnop);
+
+/* I'm trying really hard not to include anything from smb.h with the
+   result of some silly looking redeclaration of structures. */
+
+#ifndef _PSTRING
+#define _PSTRING
+#define PSTRING_LEN 1024
+#define FSTRING_LEN 256
+typedef char pstring[PSTRING_LEN];
+typedef char fstring[FSTRING_LEN];
+#endif
+
+#ifndef _BOOL
+#define _BOOL                  /* So we don't typedef BOOL again in vfs.h */
+#define False (0)
+#define True (1)
+#define Auto (2)
+typedef int BOOL;
+#endif
+
+#if !defined(uint32)
+#if (SIZEOF_INT == 4)
+#define uint32 unsigned int
+#elif (SIZEOF_LONG == 4)
+#define uint32 unsigned long
+#elif (SIZEOF_SHORT == 4)
+#define uint32 unsigned short
+#endif
+#endif
+
+#if !defined(uint16)
+#if (SIZEOF_SHORT == 4)
+#define uint16 __ERROR___CANNOT_DETERMINE_TYPE_FOR_INT16;
+#else /* SIZEOF_SHORT != 4 */
+#define uint16 unsigned short
+#endif /* SIZEOF_SHORT != 4 */
+#endif
+
+#ifndef uint8
+#define uint8 unsigned char
+#endif
+
+/* zero a structure */
+#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x))
+
+/* zero a structure given a pointer to the structure */
+#define ZERO_STRUCTP(x) { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); }
+    
+/* Some systems (SCO) treat UNIX domain sockets as FIFOs */
+
+#ifndef S_IFSOCK
+#define S_IFSOCK S_IFIFO
+#endif
+
+#ifndef S_ISSOCK
+#define S_ISSOCK(mode)  ((mode & S_IFSOCK) == S_IFSOCK)
+#endif
+
+#endif
diff --git a/helpers/ntlm_auth/winbind/winbindd_nss.h b/helpers/ntlm_auth/winbind/winbindd_nss.h
new file mode 100644 (file)
index 0000000..476dc71
--- /dev/null
@@ -0,0 +1,216 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   Winbind daemon for ntdom nss module
+
+   Copyright (C) Tim Potter 2000
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#ifndef SAFE_FREE
+#define SAFE_FREE(x) do { if(x) {free(x); x=NULL;} } while(0)
+#endif
+
+#ifndef _WINBINDD_NTDOM_H
+#define _WINBINDD_NTDOM_H
+
+#define WINBINDD_SOCKET_NAME "pipe"            /* Name of PF_UNIX socket */
+#define WINBINDD_SOCKET_DIR  "/tmp/.winbindd"  /* Name of PF_UNIX dir */
+
+#define WINBINDD_DOMAIN_ENV  "WINBINDD_DOMAIN" /* Environment variables */
+#define WINBINDD_DONT_ENV    "_NO_WINBINDD"
+
+/* Update this when you change the interface.  */
+
+#define WINBIND_INTERFACE_VERSION 4
+
+/* Socket commands */
+
+enum winbindd_cmd {
+
+       WINBINDD_INTERFACE_VERSION,    /* Always a well known value */
+
+       /* Get users and groups */
+
+       WINBINDD_GETPWNAM,
+       WINBINDD_GETPWUID,
+       WINBINDD_GETGRNAM,
+       WINBINDD_GETGRGID,
+       WINBINDD_GETGROUPS,
+
+       /* Enumerate users and groups */
+
+       WINBINDD_SETPWENT,
+       WINBINDD_ENDPWENT,
+       WINBINDD_GETPWENT,
+       WINBINDD_SETGRENT,
+       WINBINDD_ENDGRENT,
+       WINBINDD_GETGRENT,
+
+       /* PAM authenticate and password change */
+
+       WINBINDD_PAM_AUTH,
+       WINBINDD_PAM_AUTH_CRAP,
+       WINBINDD_PAM_CHAUTHTOK,
+
+       /* List various things */
+
+       WINBINDD_LIST_USERS,         /* List w/o rid->id mapping */
+       WINBINDD_LIST_GROUPS,        /* Ditto */
+       WINBINDD_LIST_TRUSTDOM,
+
+       /* SID conversion */
+
+       WINBINDD_LOOKUPSID,
+       WINBINDD_LOOKUPNAME,
+
+       /* Lookup functions */
+
+       WINBINDD_SID_TO_UID,       
+       WINBINDD_SID_TO_GID,
+       WINBINDD_UID_TO_SID,
+       WINBINDD_GID_TO_SID,
+
+       /* Miscellaneous other stuff */
+
+       WINBINDD_CHECK_MACHACC,     /* Check machine account pw works */
+       WINBINDD_PING,              /* Just tell me winbind is running */
+       WINBINDD_INFO,              /* Various bit of info.  Currently just tidbits */
+       WINBINDD_DOMAIN_NAME,       /* The domain this winbind server is a member of (lp_workgroup()) */
+
+       WINBINDD_SHOW_SEQUENCE, /* display sequence numbers of domains */
+
+       /* Placeholder for end of cmd list */
+
+       WINBINDD_NUM_CMDS
+};
+
+/* Winbind request structure */
+
+struct winbindd_request {
+       uint32 length;
+       enum winbindd_cmd cmd;   /* Winbindd command to execute */
+       pid_t pid;               /* pid of calling process */
+
+       union {
+               fstring username;    /* getpwnam */
+               fstring groupname;   /* getgrnam */
+               uid_t uid;           /* getpwuid, uid_to_sid */
+               gid_t gid;           /* getgrgid, gid_to_sid */
+               struct {
+                       fstring user;
+                       fstring pass;
+               } auth;              /* pam_winbind auth module */
+                struct {
+                        unsigned char chal[8];
+                        fstring user;
+                        fstring domain;
+                        fstring lm_resp;
+                        uint16 lm_resp_len;
+                        fstring nt_resp;
+                        uint16 nt_resp_len;
+                } auth_crap;
+                struct {
+                    fstring user;
+                    fstring oldpass;
+                    fstring newpass;
+                } chauthtok;         /* pam_winbind passwd module */
+               fstring sid;         /* lookupsid, sid_to_[ug]id */
+               struct {
+                       fstring dom_name;       /* lookupname */
+                       fstring name;       
+               } name;
+               uint32 num_entries;  /* getpwent, getgrent */
+       } data;
+       fstring domain;      /* {set,get,end}{pw,gr}ent() */
+};
+
+/* Response values */
+
+enum winbindd_result {
+       WINBINDD_ERROR,
+       WINBINDD_OK
+};
+
+/* Winbind response structure */
+
+struct winbindd_response {
+    
+       /* Header information */
+
+       uint32 length;                        /* Length of response */
+       enum winbindd_result result;          /* Result code */
+
+       /* Fixed length return data */
+       
+       union {
+               int interface_version;  /* Try to ensure this is always in the same spot... */
+               
+               /* getpwnam, getpwuid */
+               
+               struct winbindd_pw {
+                       fstring pw_name;
+                       fstring pw_passwd;
+                       uid_t pw_uid;
+                       gid_t pw_gid;
+                       fstring pw_gecos;
+                       fstring pw_dir;
+                       fstring pw_shell;
+               } pw;
+
+               /* getgrnam, getgrgid */
+
+               struct winbindd_gr {
+                       fstring gr_name;
+                       fstring gr_passwd;
+                       gid_t gr_gid;
+                       int num_gr_mem;
+                       int gr_mem_ofs;   /* offset to group membership */
+               } gr;
+
+               uint32 num_entries; /* getpwent, getgrent */
+               struct winbindd_sid {
+                       fstring sid;        /* lookupname, [ug]id_to_sid */
+                       int type;
+               } sid;
+               struct winbindd_name {
+                       fstring dom_name;       /* lookupsid */
+                       fstring name;       
+                       int type;
+               } name;
+               uid_t uid;          /* sid_to_uid */
+               gid_t gid;          /* sid_to_gid */
+               struct winbindd_info {
+                       char winbind_separator;
+                       fstring samba_version;
+               } info;
+               fstring domain_name;
+
+               struct auth_reply {
+                       uint32 nt_status;
+                       fstring nt_status_string;
+                       fstring error_string;
+                       int pam_error;
+               } auth;
+       } data;
+
+       /* Variable length return data */
+
+       void *extra_data;               /* getgrnam, getgrgid, getgrent */
+};
+
+#endif