diff options
author | Stefan Metzmacher <metze@samba.org> | 2004-05-24 17:41:47 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:56:12 -0500 |
commit | 7fb1be73734915e027f86aca9ba62b86c56ca787 (patch) | |
tree | b66be4fc8eedb1ed5c20bbc29493e3a6353bcfff /source4/nsswitch | |
parent | f1a8a690fcd9e8824dade9278e83902a6229b092 (diff) | |
download | samba-7fb1be73734915e027f86aca9ba62b86c56ca787.tar.gz samba-7fb1be73734915e027f86aca9ba62b86c56ca787.tar.bz2 samba-7fb1be73734915e027f86aca9ba62b86c56ca787.zip |
r853: remove a real big bunch of unused code
I really think that this is needed to get a better overview of what is currently used
Also this stuff is really out of date
so if we really ever need some of this stuff back,
a 'svn copy' from the SAMBA_3_0 branch should be no big problem...
metze
(This used to be commit 972598d511c64f29bdc849fe58c9c82fbcf6a4a2)
Diffstat (limited to 'source4/nsswitch')
32 files changed, 0 insertions, 13755 deletions
diff --git a/source4/nsswitch/README b/source4/nsswitch/README deleted file mode 100644 index 9f0c581df6..0000000000 --- a/source4/nsswitch/README +++ /dev/null @@ -1,13 +0,0 @@ -This extension provides a "wins" module for NSS on glibc2/Linux. This -allows you to use a WINS entry in /etc/nsswitch.conf for hostname -resolution, allowing you to resolve netbios names via start unix -gethostbyname() calls. The end result is that you can use netbios -names as host names in unix apps. - -1) run configure -2) run "make nsswitch" -3) cp nsswitch/libnss_wins.so /lib/libnss_wins.so.2 -4) add a wins entry to the hosts line in /etc/nsswitch.conf -5) use it - -tridge@linuxcare.com diff --git a/source4/nsswitch/config.m4 b/source4/nsswitch/config.m4 deleted file mode 100644 index 2d5efe0eb6..0000000000 --- a/source4/nsswitch/config.m4 +++ /dev/null @@ -1,105 +0,0 @@ -################################################# -# Check whether winbind is supported on this platform. If so we need to -# build and install client programs, sbin programs and shared libraries - -AC_MSG_CHECKING(whether to build winbind) - -# Initially, the value of $host_os decides whether winbind is supported - -case "$host_os" in - *linux*|*irix*) - HAVE_WINBIND=yes - ;; - *solaris*) - HAVE_WINBIND=yes - WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_solaris.o" - WINBIND_NSS_EXTRA_LIBS="-lsocket" - ;; - *hpux11*) - HAVE_WINBIND=yes - WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_solaris.o" - ;; - *) - HAVE_WINBIND=no - winbind_no_reason=", unsupported on $host_os" - ;; -esac - -AC_SUBST(WINBIND_NSS_EXTRA_OBJS) -AC_SUBST(WINBIND_NSS_EXTRA_LIBS) - -# Check the setting of --with-winbindd - -AC_ARG_WITH(winbind, -[ --with-winbind Build winbind (default, if supported by OS)], -[ - case "$withval" in - yes) - HAVE_WINBIND=yes - ;; - no) - HAVE_WINBIND=no - winbind_reason="" - ;; - esac ], -) - -# We need unix domain sockets for winbind -if test x"$HAVE_WINBIND" = x"yes"; then - if test x"$samba_cv_unixsocket" = x"no"; then - winbind_no_reason=", no unix domain socket support on $host_os" - HAVE_WINBIND=no - fi -fi - -# Display test results - -if test x"$HAVE_WINBIND" = x"yes"; then - AC_MSG_RESULT(yes) - AC_DEFINE(WITH_WINBIND,1,[Whether to build winbind]) - - EXTRA_BIN_PROGS="$EXTRA_BIN_PROGS bin/wbinfo\$(EXEEXT)" - EXTRA_SBIN_PROGS="$EXTRA_SBIN_PROGS bin/winbindd\$(EXEEXT)" - if test x"$BLDSHARED" = x"true"; then - case "$host_os" in - *irix*) - SHLIB_PROGS="$SHLIB_PROGS nsswitch/libns_winbind.so" - ;; - *) - SHLIB_PROGS="$SHLIB_PROGS nsswitch/libnss_winbind.so" - ;; - esac - if test x"$with_pam" = x"yes"; then - SHLIB_PROGS="$SHLIB_PROGS nsswitch/pam_winbind.so" - fi - fi -else - AC_MSG_RESULT(no$winbind_no_reason) -fi - -# Solaris has some extra fields in struct passwd that need to be -# initialised otherwise nscd crashes. Unfortunately autoconf < 2.50 -# doesn't have the AC_CHECK_MEMBER macro which would be handy for checking -# this. - -#AC_CHECK_MEMBER(struct passwd.pw_comment, -# AC_DEFINE(HAVE_PASSWD_PW_COMMENT, 1, [Defined if struct passwd has pw_comment field]), -# [#include <pwd.h>]) - -AC_CACHE_CHECK([whether struct passwd has pw_comment],samba_cv_passwd_pw_comment, [ - AC_TRY_COMPILE([#include <pwd.h>],[struct passwd p; p.pw_comment;], - samba_cv_passwd_pw_comment=yes,samba_cv_passwd_pw_comment=no)]) -if test x"$samba_cv_passwd_pw_comment" = x"yes"; then - AC_DEFINE(HAVE_PASSWD_PW_COMMENT,1,[Whether struct passwd has pw_comment]) -fi - -#AC_CHECK_MEMBER(struct passwd.pw_age, -# AC_DEFINE(HAVE_PASSWD_PW_AGE, 1, [Defined if struct passwd has pw_age field]), -# [#include <pwd.h>]) - -AC_CACHE_CHECK([whether struct passwd has pw_age],samba_cv_passwd_pw_age, [ - AC_TRY_COMPILE([#include <pwd.h>],[struct passwd p; p.pw_age;], - samba_cv_passwd_pw_age=yes,samba_cv_passwd_pw_age=no)]) -if test x"$samba_cv_passwd_pw_age" = x"yes"; then - AC_DEFINE(HAVE_PASSWD_PW_AGE,1,[Whether struct passwd has pw_age]) -fi diff --git a/source4/nsswitch/hp_nss_common.h b/source4/nsswitch/hp_nss_common.h deleted file mode 100644 index 5bd5374182..0000000000 --- a/source4/nsswitch/hp_nss_common.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _HP_NSS_COMMON_H -#define _HP_NSS_COMMON_H - -/* - Unix SMB/CIFS implementation. - - Donated by HP to enable Winbindd to build on HPUX 11.x. - Copyright (C) Jeremy Allison 2002. - - 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_SYNCH_H -#include <synch.h> -#endif -#ifdef HAVE_PTHREAD_H -#include <pthread.h> -#endif - -typedef enum { - NSS_SUCCESS, - NSS_NOTFOUND, - NSS_UNAVAIL, - NSS_TRYAGAIN -} nss_status_t; - -struct nss_backend; - -typedef nss_status_t (*nss_backend_op_t)(struct nss_backend *, void *args); - -struct nss_backend { - nss_backend_op_t *ops; - int n_ops; -}; -typedef struct nss_backend nss_backend_t; -typedef int nss_dbop_t; - -#endif /* _HP_NSS_COMMON_H */ diff --git a/source4/nsswitch/hp_nss_dbdefs.h b/source4/nsswitch/hp_nss_dbdefs.h deleted file mode 100644 index bd24772e33..0000000000 --- a/source4/nsswitch/hp_nss_dbdefs.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef _HP_NSS_DBDEFS_H -#define _HP_NSS_DBDEFS_H - -/* - Unix SMB/CIFS implementation. - - Donated by HP to enable Winbindd to build on HPUX 11.x. - Copyright (C) Jeremy Allison 2002. - - 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 <errno.h> -#include <netdb.h> -#include <limits.h> - -#ifndef NSS_INCLUDE_UNSAFE -#define NSS_INCLUDE_UNSAFE 1 /* Build old, MT-unsafe interfaces, */ -#endif /* NSS_INCLUDE_UNSAFE */ - -enum nss_netgr_argn { - NSS_NETGR_MACHINE, - NSS_NETGR_USER, - NSS_NETGR_DOMAIN, - NSS_NETGR_N -}; - -enum nss_netgr_status { - NSS_NETGR_FOUND, - NSS_NETGR_NO, - NSS_NETGR_NOMEM -}; - -typedef unsigned nss_innetgr_argc; -typedef char **nss_innetgr_argv; - -struct nss_innetgr_1arg { - nss_innetgr_argc argc; - nss_innetgr_argv argv; -}; - -typedef struct { - void *result; /* "result" parameter to getXbyY_r() */ - char *buffer; /* "buffer" " " */ - int buflen; /* "buflen" " " */ -} nss_XbyY_buf_t; - -extern nss_XbyY_buf_t *_nss_XbyY_buf_alloc(int struct_size, int buffer_size); -extern void _nss_XbyY_buf_free(nss_XbyY_buf_t *); - -union nss_XbyY_key { - uid_t uid; - gid_t gid; - const char *name; - int number; - struct { - long net; - int type; - } netaddr; - struct { - const char *addr; - int len; - int type; - } hostaddr; - struct { - union { - const char *name; - int port; - } serv; - const char *proto; - } serv; - void *ether; -}; - -typedef struct nss_XbyY_args { - nss_XbyY_buf_t buf; - int stayopen; - /* - * Support for setXXXent(stayopen) - * Used only in hosts, protocols, - * networks, rpc, and services. - */ - int (*str2ent)(const char *instr, int instr_len, void *ent, char *buffer, int buflen); - union nss_XbyY_key key; - - void *returnval; - int erange; - int h_errno; - nss_status_t status; -} nss_XbyY_args_t; - -#endif /* _NSS_DBDEFS_H */ diff --git a/source4/nsswitch/nss.h b/source4/nsswitch/nss.h deleted file mode 100644 index d83a5e237e..0000000000 --- a/source4/nsswitch/nss.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef _NSSWITCH_NSS_H -#define _NSSWITCH_NSS_H -/* - Unix SMB/CIFS implementation. - - 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) && defined(HAVE_NSSWITCH_H) -/* 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/source4/nsswitch/pam_winbind.c b/source4/nsswitch/pam_winbind.c deleted file mode 100644 index 123f670366..0000000000 --- a/source4/nsswitch/pam_winbind.c +++ /dev/null @@ -1,754 +0,0 @@ -/* pam_winbind module - - Copyright Andrew Tridgell <tridge@samba.org> 2000 - Copyright Tim Potter <tpot@samba.org> 2000 - Copyright Andrew Bartlett <abartlet@samba.org> 2002 - - largely based on pam_userdb by Christian Gafton <gafton@redhat.com> - also contains large slabs of code from pam_unix by Elliot Lee <sopwith@redhat.com> - (see copyright below for full details) -*/ - -#include "pam_winbind.h" - -/* data tokens */ - -#define MAX_PASSWD_TRIES 3 - -/* some syslogging */ -static void _pam_log(int err, const char *format, ...) -{ - va_list args; - - va_start(args, format); - openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH); - vsyslog(err, format, args); - va_end(args); - closelog(); -} - -static int _pam_parse(int argc, const char **argv) -{ - int ctrl; - /* step through arguments */ - for (ctrl = 0; argc-- > 0; ++argv) { - - /* generic options */ - - if (!strcmp(*argv,"debug")) - ctrl |= WINBIND_DEBUG_ARG; - else if (!strcasecmp(*argv, "use_authtok")) - ctrl |= WINBIND_USE_AUTHTOK_ARG; - else if (!strcasecmp(*argv, "use_first_pass")) - ctrl |= WINBIND_USE_FIRST_PASS_ARG; - else if (!strcasecmp(*argv, "try_first_pass")) - ctrl |= WINBIND_TRY_FIRST_PASS_ARG; - else if (!strcasecmp(*argv, "unknown_ok")) - ctrl |= WINBIND_UNKNOWN_OK_ARG; - else { - _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv); - } - } - - return ctrl; -} - -/* --- authentication management functions --- */ - -/* Attempt a conversation */ - -static int converse(pam_handle_t *pamh, int nargs, - struct pam_message **message, - struct pam_response **response) -{ - int retval; - struct pam_conv *conv; - - retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ; - if (retval == PAM_SUCCESS) { - retval = conv->conv(nargs, (const struct pam_message **)message, - response, conv->appdata_ptr); - } - - return retval; /* propagate error status */ -} - - -static int _make_remark(pam_handle_t * pamh, int type, const char *text) -{ - int retval = PAM_SUCCESS; - - struct pam_message *pmsg[1], msg[1]; - struct pam_response *resp; - - pmsg[0] = &msg[0]; - msg[0].msg = text; - msg[0].msg_style = type; - - resp = NULL; - retval = converse(pamh, 1, pmsg, &resp); - - if (resp) { - _pam_drop_reply(resp, 1); - } - return retval; -} - -static int pam_winbind_request(enum winbindd_cmd req_type, - struct winbindd_request *request, - struct winbindd_response *response) -{ - - /* Fill in request and send down pipe */ - init_request(request, req_type); - - if (write_sock(request, sizeof(*request)) == -1) { - _pam_log(LOG_ERR, "write to socket failed!"); - close_sock(); - return PAM_SERVICE_ERR; - } - - /* Wait for reply */ - if (read_reply(response) == -1) { - _pam_log(LOG_ERR, "read from socket failed!"); - close_sock(); - return PAM_SERVICE_ERR; - } - - /* We are done with the socket - close it and avoid mischeif */ - close_sock(); - - /* Copy reply data from socket */ - if (response->result != WINBINDD_OK) { - if (response->data.auth.pam_error != PAM_SUCCESS) { - _pam_log(LOG_ERR, "request failed: %s, PAM error was %d, NT error was %s", - response->data.auth.error_string, - response->data.auth.pam_error, - response->data.auth.nt_status_string); - return response->data.auth.pam_error; - } else { - _pam_log(LOG_ERR, "request failed, but PAM error 0!"); - return PAM_SERVICE_ERR; - } - } - - return PAM_SUCCESS; -} - -static int pam_winbind_request_log(enum winbindd_cmd req_type, - struct winbindd_request *request, - struct winbindd_response *response, - int ctrl, - const char *user) -{ - int retval; - - retval = pam_winbind_request(req_type, request, response); - - switch (retval) { - case PAM_AUTH_ERR: - /* incorrect password */ - _pam_log(LOG_WARNING, "user `%s' denied access (incorrect password)", user); - return retval; - case PAM_ACCT_EXPIRED: - /* account expired */ - _pam_log(LOG_WARNING, "user `%s' account expired", user); - return retval; - case PAM_AUTHTOK_EXPIRED: - /* password expired */ - _pam_log(LOG_WARNING, "user `%s' password expired", user); - return retval; - case PAM_NEW_AUTHTOK_REQD: - /* password expired */ - _pam_log(LOG_WARNING, "user `%s' new password required", user); - return retval; - case PAM_USER_UNKNOWN: - /* the user does not exist */ - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_NOTICE, "user `%s' not found", - user); - if (ctrl & WINBIND_UNKNOWN_OK_ARG) { - return PAM_IGNORE; - } - return retval; - case PAM_SUCCESS: - if (req_type == WINBINDD_PAM_AUTH) { - /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", user); - } else if (req_type == WINBINDD_PAM_CHAUTHTOK) { - /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' password changed", user); - } else { - /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' OK", user); - } - return retval; - default: - /* we don't know anything about this return value */ - _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s'", - retval, user); - return retval; - } -} - -/* talk to winbindd */ -static int winbind_auth_request(const char *user, const char *pass, int ctrl) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - - strncpy(request.data.auth.user, user, - sizeof(request.data.auth.user)-1); - - strncpy(request.data.auth.pass, pass, - sizeof(request.data.auth.pass)-1); - - - return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user); -} - -/* talk to winbindd */ -static int winbind_chauthtok_request(const char *user, const char *oldpass, - const char *newpass, int ctrl) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - - if (request.data.chauthtok.user == NULL) return -2; - - strncpy(request.data.chauthtok.user, user, - sizeof(request.data.chauthtok.user) - 1); - - if (oldpass != NULL) { - strncpy(request.data.chauthtok.oldpass, oldpass, - sizeof(request.data.chauthtok.oldpass) - 1); - } else { - request.data.chauthtok.oldpass[0] = '\0'; - } - - if (newpass != NULL) { - strncpy(request.data.chauthtok.newpass, newpass, - sizeof(request.data.chauthtok.newpass) - 1); - } else { - request.data.chauthtok.newpass[0] = '\0'; - } - - return pam_winbind_request_log(WINBINDD_PAM_CHAUTHTOK, &request, &response, ctrl, user); -} - -/* - * Checks if a user has an account - * - * return values: - * 1 = User not found - * 0 = OK - * -1 = System error - */ -static int valid_user(const char *user) -{ - if (getpwnam(user)) return 0; - return 1; -} - -static char *_pam_delete(register char *xx) -{ - _pam_overwrite(xx); - _pam_drop(xx); - return NULL; -} - -/* - * obtain a password from the user - */ - -static int _winbind_read_password(pam_handle_t * pamh - ,unsigned int ctrl - ,const char *comment - ,const char *prompt1 - ,const char *prompt2 - ,const char **pass) -{ - int authtok_flag; - int retval; - const char *item; - char *token; - - /* - * make sure nothing inappropriate gets returned - */ - - *pass = token = NULL; - - /* - * which authentication token are we getting? - */ - - authtok_flag = on(WINBIND__OLD_PASSWORD, ctrl) ? PAM_OLDAUTHTOK : PAM_AUTHTOK; - - /* - * should we obtain the password from a PAM item ? - */ - - if (on(WINBIND_TRY_FIRST_PASS_ARG, ctrl) || on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - retval = pam_get_item(pamh, authtok_flag, (const void **) &item); - if (retval != PAM_SUCCESS) { - /* very strange. */ - _pam_log(LOG_ALERT, - "pam_get_item returned error to unix-read-password" - ); - return retval; - } else if (item != NULL) { /* we have a password! */ - *pass = item; - item = NULL; - return PAM_SUCCESS; - } else if (on(WINBIND_USE_FIRST_PASS_ARG, ctrl)) { - return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */ - } else if (on(WINBIND_USE_AUTHTOK_ARG, ctrl) - && off(WINBIND__OLD_PASSWORD, ctrl)) { - return PAM_AUTHTOK_RECOVER_ERR; - } - } - /* - * getting here implies we will have to get the password from the - * user directly. - */ - - { - struct pam_message msg[3], *pmsg[3]; - struct pam_response *resp; - int i, replies; - - /* prepare to converse */ - - if (comment != NULL) { - pmsg[0] = &msg[0]; - msg[0].msg_style = PAM_TEXT_INFO; - msg[0].msg = comment; - i = 1; - } else { - i = 0; - } - - pmsg[i] = &msg[i]; - msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = prompt1; - replies = 1; - - if (prompt2 != NULL) { - pmsg[i] = &msg[i]; - msg[i].msg_style = PAM_PROMPT_ECHO_OFF; - msg[i++].msg = prompt2; - ++replies; - } - /* so call the conversation expecting i responses */ - resp = NULL; - retval = converse(pamh, i, pmsg, &resp); - - if (resp != NULL) { - - /* interpret the response */ - - if (retval == PAM_SUCCESS) { /* a good conversation */ - - token = x_strdup(resp[i - replies].resp); - if (token != NULL) { - if (replies == 2) { - - /* verify that password entered correctly */ - if (!resp[i - 1].resp - || strcmp(token, resp[i - 1].resp)) { - _pam_delete(token); /* mistyped */ - retval = PAM_AUTHTOK_RECOVER_ERR; - _make_remark(pamh ,PAM_ERROR_MSG, MISTYPED_PASS); - } - } - } else { - _pam_log(LOG_NOTICE - ,"could not recover authentication token"); - } - - } - /* - * tidy up the conversation (resp_retcode) is ignored - * -- what is it for anyway? AGM - */ - - _pam_drop_reply(resp, i); - - } else { - retval = (retval == PAM_SUCCESS) - ? PAM_AUTHTOK_RECOVER_ERR : retval; - } - } - - if (retval != PAM_SUCCESS) { - if (on(WINBIND_DEBUG_ARG, ctrl)) - _pam_log(LOG_DEBUG, - "unable to obtain a password"); - return retval; - } - /* 'token' is the entered password */ - - /* we store this password as an item */ - - retval = pam_set_item(pamh, authtok_flag, token); - _pam_delete(token); /* clean it up */ - if (retval != PAM_SUCCESS - || (retval = pam_get_item(pamh, authtok_flag - ,(const void **) &item)) - != PAM_SUCCESS) { - - _pam_log(LOG_CRIT, "error manipulating password"); - return retval; - - } - - *pass = item; - item = NULL; /* break link to password */ - - return PAM_SUCCESS; -} - -PAM_EXTERN -int pam_sm_authenticate(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - const char *username; - const char *password; - int retval = PAM_AUTH_ERR; - - /* parse arguments */ - int ctrl = _pam_parse(argc, argv); - - /* Get the username */ - retval = pam_get_user(pamh, &username, NULL); - if ((retval != PAM_SUCCESS) || (!username)) { - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_DEBUG,"can not get the username"); - return PAM_SERVICE_ERR; - } - - retval = _winbind_read_password(pamh, ctrl, NULL, - "Password: ", NULL, - &password); - - if (retval != PAM_SUCCESS) { - _pam_log(LOG_ERR, "Could not retrieve user's password"); - return PAM_AUTHTOK_ERR; - } - - if (ctrl & WINBIND_DEBUG_ARG) { - - /* Let's not give too much away in the log file */ - -#ifdef DEBUG_PASSWORD - _pam_log(LOG_INFO, "Verify user `%s' with password `%s'", - username, password); -#else - _pam_log(LOG_INFO, "Verify user `%s'", username); -#endif - } - - /* Now use the username to look up password */ - return winbind_auth_request(username, password, ctrl); -} - -PAM_EXTERN -int pam_sm_setcred(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - return PAM_SUCCESS; -} - -/* - * Account management. We want to verify that the account exists - * before returning PAM_SUCCESS - */ -PAM_EXTERN -int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - const char *username; - int retval = PAM_USER_UNKNOWN; - - /* parse arguments */ - int ctrl = _pam_parse(argc, argv); - - /* Get the username */ - retval = pam_get_user(pamh, &username, NULL); - if ((retval != PAM_SUCCESS) || (!username)) { - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_DEBUG,"can not get the username"); - return PAM_SERVICE_ERR; - } - - /* Verify the username */ - retval = valid_user(username); - switch (retval) { - case -1: - /* some sort of system error. The log was already printed */ - return PAM_SERVICE_ERR; - case 1: - /* the user does not exist */ - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_NOTICE, "user `%s' not found", - username); - if (ctrl & WINBIND_UNKNOWN_OK_ARG) - return PAM_IGNORE; - return PAM_USER_UNKNOWN; - case 0: - /* Otherwise, the authentication looked good */ - _pam_log(LOG_NOTICE, "user '%s' granted acces", username); - return PAM_SUCCESS; - default: - /* we don't know anything about this return value */ - _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s'", - retval, username); - return PAM_SERVICE_ERR; - } - - /* should not be reached */ - return PAM_IGNORE; -} -PAM_EXTERN -int pam_sm_open_session(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - /* parse arguments */ - int ctrl = _pam_parse(argc, argv); - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_open_session handler"); - return PAM_SUCCESS; -} -PAM_EXTERN -int pam_sm_close_session(pam_handle_t *pamh, int flags, - int argc, const char **argv) -{ - /* parse arguments */ - int ctrl = _pam_parse(argc, argv); - if (ctrl & WINBIND_DEBUG_ARG) - _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_close_session handler"); - return PAM_SUCCESS; -} - - - -PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags, - int argc, const char **argv) -{ - unsigned int lctrl; - int retval; - unsigned int ctrl = _pam_parse(argc, argv); - - /* <DO NOT free() THESE> */ - const char *user; - char *pass_old, *pass_new; - /* </DO NOT free() THESE> */ - - char *Announce; - - int retry = 0; - - /* - * First get the name of a user - */ - retval = pam_get_user(pamh, &user, "Username: "); - if (retval == PAM_SUCCESS) { - if (user == NULL) { - _pam_log(LOG_ERR, "username was NULL!"); - return PAM_USER_UNKNOWN; - } - if (retval == PAM_SUCCESS && on(WINBIND_DEBUG_ARG, ctrl)) - _pam_log(LOG_DEBUG, "username [%s] obtained", - user); - } else { - if (on(WINBIND_DEBUG_ARG, ctrl)) - _pam_log(LOG_DEBUG, - "password - could not identify user"); - return retval; - } - - /* - * obtain and verify the current password (OLDAUTHTOK) for - * the user. - */ - - if (flags & PAM_PRELIM_CHECK) { - - /* instruct user what is happening */ -#define greeting "Changing password for " - Announce = (char *) malloc(sizeof(greeting) + strlen(user)); - if (Announce == NULL) { - _pam_log(LOG_CRIT, - "password - out of memory"); - return PAM_BUF_ERR; - } - (void) strcpy(Announce, greeting); - (void) strcpy(Announce + sizeof(greeting) - 1, user); -#undef greeting - - lctrl = ctrl | WINBIND__OLD_PASSWORD; - retval = _winbind_read_password(pamh, lctrl - ,Announce - ,"(current) NT password: " - ,NULL - ,(const char **) &pass_old); - free(Announce); - - if (retval != PAM_SUCCESS) { - _pam_log(LOG_NOTICE - ,"password - (old) token not obtained"); - return retval; - } - /* verify that this is the password for this user */ - - retval = winbind_auth_request(user, pass_old, ctrl); - - if (retval != PAM_ACCT_EXPIRED - && retval != PAM_AUTHTOK_EXPIRED - && retval != PAM_NEW_AUTHTOK_REQD - && retval != PAM_SUCCESS) { - pass_old = NULL; - return retval; - } - - retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old); - pass_old = NULL; - if (retval != PAM_SUCCESS) { - _pam_log(LOG_CRIT, - "failed to set PAM_OLDAUTHTOK"); - } - } else if (flags & PAM_UPDATE_AUTHTOK) { - - /* - * obtain the proposed password - */ - - /* - * get the old token back. - */ - - retval = pam_get_item(pamh, PAM_OLDAUTHTOK - ,(const void **) &pass_old); - - if (retval != PAM_SUCCESS) { - _pam_log(LOG_NOTICE, "user not authenticated"); - return retval; - } - - lctrl = ctrl; - - if (on(WINBIND_USE_AUTHTOK_ARG, lctrl)) { - ctrl = WINBIND_USE_FIRST_PASS_ARG | lctrl; - } - retry = 0; - retval = PAM_AUTHTOK_ERR; - while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) { - /* - * use_authtok is to force the use of a previously entered - * password -- needed for pluggable password strength checking - */ - - retval = _winbind_read_password(pamh, lctrl - ,NULL - ,"Enter new NT password: " - ,"Retype new NT password: " - ,(const char **) &pass_new); - - if (retval != PAM_SUCCESS) { - if (on(WINBIND_DEBUG_ARG, ctrl)) { - _pam_log(LOG_ALERT - ,"password - new password not obtained"); - } - pass_old = NULL;/* tidy up */ - return retval; - } - - /* - * At this point we know who the user is and what they - * propose as their new password. Verify that the new - * password is acceptable. - */ - - if (pass_new[0] == '\0') {/* "\0" password = NULL */ - pass_new = NULL; - } - } - - /* - * By reaching here we have approved the passwords and must now - * rebuild the password database file. - */ - - retval = winbind_chauthtok_request(user, pass_old, pass_new, ctrl); - _pam_overwrite(pass_new); - _pam_overwrite(pass_old); - pass_old = pass_new = NULL; - } else { - retval = PAM_SERVICE_ERR; - } - - return retval; -} - -#ifdef PAM_STATIC - -/* static module data */ - -struct pam_module _pam_winbind_modstruct = { - MODULE_NAME, - pam_sm_authenticate, - pam_sm_setcred, - pam_sm_acct_mgmt, - pam_sm_open_session, - pam_sm_close_session, - pam_sm_chauthtok -}; - -#endif - -/* - * Copyright (c) Andrew Tridgell <tridge@samba.org> 2000 - * Copyright (c) Tim Potter <tpot@samba.org> 2000 - * Copyright (c) Andrew Bartlettt <abartlet@samba.org> 2002 - * Copyright (c) Jan Rêkorajski 1999. - * Copyright (c) Andrew G. Morgan 1996-8. - * Copyright (c) Alex O. Yuriev, 1996. - * Copyright (c) Cristian Gafton 1996. - * Copyright (C) Elliot Lee <sopwith@redhat.com> 1996, Red Hat Software. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * ALTERNATIVELY, this product may be distributed under the terms of - * the GNU Public License, in which case the provisions of the GPL are - * required INSTEAD OF the above restrictions. (This clause is - * necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * THIS SOFTWARE IS PROVIDED `AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ diff --git a/source4/nsswitch/pam_winbind.h b/source4/nsswitch/pam_winbind.h deleted file mode 100644 index fae635d806..0000000000 --- a/source4/nsswitch/pam_winbind.h +++ /dev/null @@ -1,93 +0,0 @@ -/* pam_winbind header file - (Solaris needs some macros from Linux for common PAM code) - - Shirish Kalele 2000 -*/ - -#ifdef HAVE_FEATURES_H -#include <features.h> -#endif - -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <syslog.h> -#include <stdarg.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <errno.h> - -#include <config.h> - -#define MODULE_NAME "pam_winbind" -#define PAM_SM_AUTH -#define PAM_SM_ACCOUNT -#define PAM_SM_PASSWORD - -#if defined(SUNOS5) || defined(SUNOS4) || defined(HPUX) - -/* Solaris always uses dynamic pam modules */ -#define PAM_EXTERN extern -#include <security/pam_appl.h> - -#define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR -#endif - -#ifdef HAVE_SECURITY_PAM_MODULES_H -#include <security/pam_modules.h> -#endif - -#ifdef HAVE_SECURITY__PAM_MACROS_H -#include <security/_pam_macros.h> -#else -/* Define required macros from (Linux PAM 0.68) security/_pam_macros.h */ -#define _pam_drop_reply(/* struct pam_response * */ reply, /* int */ replies) \ -do { \ - int reply_i; \ - \ - for (reply_i=0; reply_i<replies; ++reply_i) { \ - if (reply[reply_i].resp) { \ - _pam_overwrite(reply[reply_i].resp); \ - free(reply[reply_i].resp); \ - } \ - } \ - if (reply) \ - free(reply); \ -} while (0) - -#define _pam_overwrite(x) \ -do { \ - register char *__xx__; \ - if ((__xx__=(x))) \ - while (*__xx__) \ - *__xx__++ = '\0'; \ -} while (0) - -/* - * Don't just free it, forget it too. - */ - -#define _pam_drop(X) SAFE_FREE(X) - -#define x_strdup(s) ( (s) ? strdup(s):NULL ) -#endif - -#define WINBIND_DEBUG_ARG (1<<0) -#define WINBIND_USE_AUTHTOK_ARG (1<<1) -#define WINBIND_UNKNOWN_OK_ARG (1<<2) -#define WINBIND_TRY_FIRST_PASS_ARG (1<<3) -#define WINBIND_USE_FIRST_PASS_ARG (1<<4) -#define WINBIND__OLD_PASSWORD (1<<5) - -/* - * here is the string to inform the user that the new passwords they - * typed were not the same. - */ - -#define MISTYPED_PASS "Sorry, passwords do not match" - -#define on(x, y) (x & y) -#define off(x, y) (!(x & y)) - -#include "winbind_client.h" diff --git a/source4/nsswitch/wb_client.c b/source4/nsswitch/wb_client.c deleted file mode 100644 index 6f4d895839..0000000000 --- a/source4/nsswitch/wb_client.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - winbind client 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 "includes.h" -#include "nsswitch/nss.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -NSS_STATUS winbindd_request(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); - -/* Fetch the list of groups a user is a member of from winbindd. This is - used by winbind_getgroups. */ - -static int wb_getgroups(const char *user, gid_t **groups) -{ - struct winbindd_request request; - struct winbindd_response response; - int result; - - /* Call winbindd */ - - fstrcpy(request.data.username, user); - - ZERO_STRUCT(response); - - result = winbindd_request(WINBINDD_GETGROUPS, &request, &response); - - if (result == NSS_STATUS_SUCCESS) { - - /* Return group list. Don't forget to free the group list - when finished. */ - - *groups = (gid_t *)response.extra_data; - return response.data.num_entries; - } - - return -1; -} - -/* Return a list of groups the user is a member of. This function is - useful for large systems where inverting the group database would be too - time consuming. If size is zero, list is not modified and the total - number of groups for the user is returned. */ - -int winbind_getgroups(const char *user, int size, gid_t *list) -{ - gid_t *groups = NULL; - int result, i; - - /* - * Don't do the lookup if the name has no separator _and_ we are not in - * 'winbind use default domain' mode. - */ - - if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain())) - return -1; - - /* Fetch list of groups */ - - result = wb_getgroups(user, &groups); - - if (size == 0) - goto done; - - if (result > size) { - result = -1; - errno = EINVAL; /* This is what getgroups() does */ - goto done; - } - - /* Copy list of groups across */ - - for (i = 0; i < result; i++) { - list[i] = groups[i]; - } - - done: - SAFE_FREE(groups); - return result; -} diff --git a/source4/nsswitch/wb_common.c b/source4/nsswitch/wb_common.c deleted file mode 100644 index 89c751a4ef..0000000000 --- a/source4/nsswitch/wb_common.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - winbind client common code - - Copyright (C) Tim Potter 2000 - Copyright (C) Andrew Tridgell 2000 - Copyright (C) Andrew Bartlett 2002 - - - 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_client.h" - -/* Global variables. These are effectively the client state information */ - -int winbindd_fd = -1; /* fd for winbindd socket */ - -/* Free a response structure */ - -void free_response(struct winbindd_response *response) -{ - /* Free any allocated extra_data */ - - if (response) - SAFE_FREE(response->extra_data); -} - -/* Initialise a request structure */ - -void init_request(struct winbindd_request *request, int request_type) -{ - request->length = sizeof(struct winbindd_request); - - request->cmd = (enum winbindd_cmd)request_type; - request->pid = getpid(); - -} - -/* 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; - } -} - -/* Make sure socket handle isn't stdin, stdout or stderr */ -#define RECURSION_LIMIT 3 - -static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */) -{ - int new_fd; - if (fd >= 0 && fd <= 2) { -#ifdef F_DUPFD - if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) { - return -1; - } - /* Parinoia */ - if (new_fd < 3) { - close(new_fd); - return -1; - } - close(fd); - return new_fd; -#else - if (limit <= 0) - return -1; - - new_fd = dup(fd); - if (new_fd == -1) - return -1; - - /* use the program stack to hold our list of FDs to close */ - new_fd = make_nonstd_fd_internals(new_fd, limit - 1); - close(fd); - return new_fd; -#endif - } - return fd; -} - -static int make_safe_fd(int fd) -{ - int result, flags; - int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT); - if (new_fd == -1) { - close(fd); - return -1; - } - /* Socket should be closed on exec() */ - -#ifdef FD_CLOEXEC - result = flags = fcntl(new_fd, F_GETFD, 0); - if (flags >= 0) { - flags |= FD_CLOEXEC; - result = fcntl( new_fd, F_SETFD, flags ); - } - if (result < 0) { - close(new_fd); - return -1; - } -#endif - return new_fd; -} - -/* Connect to winbindd socket */ - -int winbind_open_pipe_sock(void) -{ -#ifdef HAVE_UNIXSOCKET - struct sockaddr_un sunaddr; - static pid_t our_pid; - struct stat st; - pstring path; - int fd; - - 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 ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { - return -1; - } - - if ((winbindd_fd = make_safe_fd( fd)) == -1) { - return winbindd_fd; - } - - if (connect(winbindd_fd, (struct sockaddr *)&sunaddr, - sizeof(sunaddr)) == -1) { - close_sock(); - return -1; - } - - return winbindd_fd; -#else - return -1; -#endif /* HAVE_UNIXSOCKET */ -} - -/* Write data to winbindd socket */ - -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 */ - -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; - } - - 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/source4/nsswitch/wbinfo.c b/source4/nsswitch/wbinfo.c deleted file mode 100644 index 68dc178bcd..0000000000 --- a/source4/nsswitch/wbinfo.c +++ /dev/null @@ -1,891 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind status program. - - Copyright (C) Tim Potter 2000-2002 - Copyright (C) Andrew Bartlett 2002 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "winbindd.h" -#include "debug.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -extern int winbindd_fd; - -static char winbind_separator(void) -{ - struct winbindd_response response; - static BOOL got_sep; - static char sep; - - if (got_sep) - return sep; - - ZERO_STRUCT(response); - - /* Send off request */ - - if (winbindd_request(WINBINDD_INFO, NULL, &response) != - NSS_STATUS_SUCCESS) { - d_printf("could not obtain winbind separator!\n"); - /* HACK: (this module should not call lp_ funtions) */ - return *lp_winbind_separator(); - } - - sep = response.data.info.winbind_separator; - got_sep = True; - - if (!sep) { - d_printf("winbind separator was NULL!\n"); - /* HACK: (this module should not call lp_ funtions) */ - sep = *lp_winbind_separator(); - } - - return sep; -} - -static const char *get_winbind_domain(void) -{ - struct winbindd_response response; - static fstring winbind_domain; - - ZERO_STRUCT(response); - - /* Send off request */ - - if (winbindd_request(WINBINDD_DOMAIN_NAME, NULL, &response) != - NSS_STATUS_SUCCESS) { - d_printf("could not obtain winbind domain name!\n"); - - /* HACK: (this module should not call lp_ funtions) */ - return lp_workgroup(); - } - - fstrcpy(winbind_domain, response.data.domain_name); - - return winbind_domain; - -} - -/* Copy of parse_domain_user from winbindd_util.c. Parse a string of the - form DOMAIN/user into a domain and a user */ - -static BOOL parse_wbinfo_domain_user(const char *domuser, fstring domain, - fstring user) -{ - - char *p = strchr(domuser,winbind_separator()); - - if (!p) { - fstrcpy(user, domuser); - fstrcpy(domain, get_winbind_domain()); - return True; - } - - fstrcpy(user, p+1); - fstrcpy(domain, domuser); - domain[PTR_DIFF(p, domuser)] = 0; - strupper(domain); - - return True; -} - -/* List groups a user is a member of */ - -static BOOL wbinfo_get_usergroups(char *user) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - int i; - - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.username, user); - - result = winbindd_request(WINBINDD_GETGROUPS, &request, &response); - - if (result != NSS_STATUS_SUCCESS) - return False; - - for (i = 0; i < response.data.num_entries; i++) - d_printf("%d\n", (int)((gid_t *)response.extra_data)[i]); - - SAFE_FREE(response.extra_data); - - return True; -} - -/* Convert NetBIOS name to IP */ - -static BOOL wbinfo_wins_byname(char *name) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.winsreq, name); - - if (winbindd_request(WINBINDD_WINS_BYNAME, &request, &response) != - NSS_STATUS_SUCCESS) { - return False; - } - - /* Display response */ - - printf("%s\n", response.data.winsresp); - - return True; -} - -/* Convert IP to NetBIOS name */ - -static BOOL wbinfo_wins_byip(char *ip) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.winsreq, ip); - - if (winbindd_request(WINBINDD_WINS_BYIP, &request, &response) != - NSS_STATUS_SUCCESS) { - return False; - } - - /* Display response */ - - printf("%s\n", response.data.winsresp); - - return True; -} - -/* List trusted domains */ - -static BOOL wbinfo_list_domains(void) -{ - struct winbindd_response response; - fstring name; - - ZERO_STRUCT(response); - - /* Send request */ - - if (winbindd_request(WINBINDD_LIST_TRUSTDOM, NULL, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - if (response.extra_data) { - const char *extra_data = (char *)response.extra_data; - - while(next_token(&extra_data, name, ",", sizeof(fstring))) - d_printf("%s\n", name); - - SAFE_FREE(response.extra_data); - } - - return True; -} - - -/* show sequence numbers */ -static BOOL wbinfo_show_sequence(void) -{ - struct winbindd_response response; - - ZERO_STRUCT(response); - - /* Send request */ - - if (winbindd_request(WINBINDD_SHOW_SEQUENCE, NULL, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - if (response.extra_data) { - char *extra_data = (char *)response.extra_data; - d_printf("%s", extra_data); - SAFE_FREE(response.extra_data); - } - - return True; -} - -/* Check trust account password */ - -static BOOL wbinfo_check_secret(void) -{ - struct winbindd_response response; - NSS_STATUS result; - - ZERO_STRUCT(response); - - result = winbindd_request(WINBINDD_CHECK_MACHACC, NULL, &response); - - d_printf("checking the trust secret via RPC calls %s\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); - - if (result != NSS_STATUS_SUCCESS) - d_printf("error code was %s (0x%x)\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status); - - return result == NSS_STATUS_SUCCESS; -} - -/* Convert uid to sid */ - -static BOOL wbinfo_uid_to_sid(uid_t uid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - request.data.uid = uid; - - if (winbindd_request(WINBINDD_UID_TO_SID, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%s\n", response.data.sid.sid); - - return True; -} - -/* Convert gid to sid */ - -static BOOL wbinfo_gid_to_sid(gid_t gid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - request.data.gid = gid; - - if (winbindd_request(WINBINDD_GID_TO_SID, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%s\n", response.data.sid.sid); - - return True; -} - -/* Convert sid to uid */ - -static BOOL wbinfo_sid_to_uid(char *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request(WINBINDD_SID_TO_UID, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%d\n", (int)response.data.uid); - - return True; -} - -static BOOL wbinfo_sid_to_gid(char *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send request */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request(WINBINDD_SID_TO_GID, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%d\n", (int)response.data.gid); - - return True; -} - -/* Convert sid to string */ - -static BOOL wbinfo_lookupsid(char *sid) -{ - struct winbindd_request request; - struct winbindd_response response; - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - /* Send off request */ - - fstrcpy(request.data.sid, sid); - - if (winbindd_request(WINBINDD_LOOKUPSID, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%s%c%s %d\n", response.data.name.dom_name, - winbind_separator(), response.data.name.name, - response.data.name.type); - - return True; -} - -/* Convert string to sid */ - -static BOOL wbinfo_lookupname(char *name) -{ - struct winbindd_request request; - struct winbindd_response response; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - parse_wbinfo_domain_user(name, request.data.name.dom_name, - request.data.name.name); - - if (winbindd_request(WINBINDD_LOOKUPNAME, &request, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Display response */ - - d_printf("%s %d\n", response.data.sid.sid, response.data.sid.type); - - return True; -} - -/* Authenticate a user with a plaintext password */ - -static BOOL wbinfo_auth(char *username) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - char *p; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - p = strchr(username, '%'); - - if (p) { - *p = 0; - fstrcpy(request.data.auth.user, username); - fstrcpy(request.data.auth.pass, p + 1); - *p = '%'; - } else - fstrcpy(request.data.auth.user, username); - - result = winbindd_request(WINBINDD_PAM_AUTH, &request, &response); - - /* Display response */ - - d_printf("plaintext password authentication %s\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); - - if (response.data.auth.nt_status) - d_printf("error code was %s (0x%x)\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status); - - return result == NSS_STATUS_SUCCESS; -} - -/* Authenticate a user with a challenge/response */ - -static BOOL wbinfo_auth_crap(char *username) -{ - struct winbindd_request request; - struct winbindd_response response; - NSS_STATUS result; - fstring name_user; - fstring name_domain; - fstring pass; - char *p; - - /* Send off request */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - p = strchr(username, '%'); - - if (p) { - *p = 0; - fstrcpy(pass, p + 1); - } - - parse_wbinfo_domain_user(username, name_domain, name_user); - - fstrcpy(request.data.auth_crap.user, name_user); - - fstrcpy(request.data.auth_crap.domain, name_domain); - - generate_random_buffer(request.data.auth_crap.chal, 8, False); - - SMBencrypt(pass, request.data.auth_crap.chal, - (uchar *)request.data.auth_crap.lm_resp); - SMBNTencrypt(pass, request.data.auth_crap.chal, - (uchar *)request.data.auth_crap.nt_resp); - - request.data.auth_crap.lm_resp_len = 24; - request.data.auth_crap.nt_resp_len = 24; - - result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); - - /* Display response */ - - d_printf("challenge/response password authentication %s\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed"); - - if (response.data.auth.nt_status) - d_printf("error code was %s (0x%x)\n", - response.data.auth.nt_status_string, - response.data.auth.nt_status); - - return result == NSS_STATUS_SUCCESS; -} - -/* Print domain users */ - -static BOOL print_domain_users(void) -{ - struct winbindd_response response; - const char *extra_data; - fstring name; - - /* Send request to winbind daemon */ - - ZERO_STRUCT(response); - - if (winbindd_request(WINBINDD_LIST_USERS, NULL, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Look through extra data */ - - if (!response.extra_data) - return False; - - extra_data = (const char *)response.extra_data; - - while(next_token(&extra_data, name, ",", sizeof(fstring))) - d_printf("%s\n", name); - - SAFE_FREE(response.extra_data); - - return True; -} - -/* Print domain groups */ - -static BOOL print_domain_groups(void) -{ - struct winbindd_response response; - const char *extra_data; - fstring name; - - ZERO_STRUCT(response); - - if (winbindd_request(WINBINDD_LIST_GROUPS, NULL, &response) != - NSS_STATUS_SUCCESS) - return False; - - /* Look through extra data */ - - if (!response.extra_data) - return False; - - extra_data = (const char *)response.extra_data; - - while(next_token(&extra_data, name, ",", sizeof(fstring))) - d_printf("%s\n", name); - - SAFE_FREE(response.extra_data); - - return True; -} - -/* Set the authorised user for winbindd access in secrets.tdb */ - -static BOOL wbinfo_set_auth_user(char *username) -{ - char *password; - fstring user, domain; - - /* Separate into user and password */ - - parse_wbinfo_domain_user(username, domain, user); - - password = strchr(user, '%'); - - if (password) { - *password = 0; - password++; - } else - password = ""; - - /* Store or remove DOMAIN\username%password in secrets.tdb */ - - secrets_init(); - - if (user[0]) { - - if (!secrets_store(SECRETS_AUTH_USER, user, - strlen(user) + 1)) { - d_fprintf(stderr, "error storing username\n"); - return False; - } - - /* We always have a domain name added by the - parse_wbinfo_domain_user() function. */ - - if (!secrets_store(SECRETS_AUTH_DOMAIN, domain, - strlen(domain) + 1)) { - d_fprintf(stderr, "error storing domain name\n"); - return False; - } - - } else { - secrets_delete(SECRETS_AUTH_USER); - secrets_delete(SECRETS_AUTH_DOMAIN); - } - - if (password[0]) { - - if (!secrets_store(SECRETS_AUTH_PASSWORD, password, - strlen(password) + 1)) { - d_fprintf(stderr, "error storing password\n"); - return False; - } - - } else - secrets_delete(SECRETS_AUTH_PASSWORD); - - return True; -} - -static void wbinfo_get_auth_user(void) -{ - char *user, *domain, *password; - - /* Lift data from secrets file */ - - secrets_init(); - - user = secrets_fetch(SECRETS_AUTH_USER, NULL); - domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); - password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); - - if (!user && !domain && !password) { - d_printf("No authorised user configured\n"); - return; - } - - /* Pretty print authorised user info */ - - d_printf("%s%s%s%s%s\n", domain ? domain : "", domain ? "\\" : "", - user, password ? "%" : "", password ? password : ""); - - SAFE_FREE(user); - SAFE_FREE(domain); - SAFE_FREE(password); -} - -static BOOL wbinfo_ping(void) -{ - NSS_STATUS result; - - result = winbindd_request(WINBINDD_PING, NULL, NULL); - - /* Display response */ - - d_printf("'ping' to winbindd %s on fd %d\n", - (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd); - - return result == NSS_STATUS_SUCCESS; -} - -/* Main program */ - -enum { - OPT_SET_AUTH_USER = 1000, - OPT_GET_AUTH_USER, - OPT_SEQUENCE -}; - -int main(int argc, char **argv) -{ - int opt; - - poptContext pc; - static char *string_arg; - static int int_arg; - BOOL got_command = False; - int result = 1; - - struct poptOption long_options[] = { - POPT_AUTOHELP - - /* longName, shortName, argInfo, argPtr, value, descrip, - argDesc */ - - { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users"}, - { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups" }, - { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP (WINS)", "NETBIOS-NAME" }, - { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name (WINS)", "IP" }, - { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" }, - { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name", "SID" }, - { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" , "UID" }, - { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" }, - { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" }, - { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" }, - { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" }, - { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" }, - { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "show sequence numbers of all domains" }, - { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" }, - { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" }, - { "set-auth-user", 'A', POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" }, - { "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL }, - { "ping", 'p', POPT_ARG_NONE, 0, 'p', "'ping' winbindd to see if it is alive" }, - { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version}, - { 0, 0, 0, 0 } - }; - - /* Samba client initialisation */ - - if (!lp_load(dyn_CONFIGFILE, True, False, False)) { - d_fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n", - dyn_CONFIGFILE, strerror(errno)); - exit(1); - } - - if (!init_names()) - return 1; - - load_interfaces(); - - /* Parse options */ - - pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0); - - /* Parse command line options */ - - if (argc == 1) { - poptPrintHelp(pc, stderr, 0); - return 1; - } - - while((opt = poptGetNextOpt(pc)) != -1) { - if (got_command) { - d_fprintf(stderr, "No more than one command may be specified at once.\n"); - exit(1); - } - got_command = True; - } - - poptFreeContext(pc); - - pc = poptGetContext(NULL, argc, (const char **)argv, long_options, - POPT_CONTEXT_KEEP_FIRST); - - while((opt = poptGetNextOpt(pc)) != -1) { - switch (opt) { - case 'u': - if (!print_domain_users()) { - d_printf("Error looking up domain users\n"); - goto done; - } - break; - case 'g': - if (!print_domain_groups()) { - d_printf("Error looking up domain groups\n"); - goto done; - } - break; - case 's': - if (!wbinfo_lookupsid(string_arg)) { - d_printf("Could not lookup sid %s\n", string_arg); - goto done; - } - break; - case 'n': - if (!wbinfo_lookupname(string_arg)) { - d_printf("Could not lookup name %s\n", string_arg); - goto done; - } - break; - case 'N': - if (!wbinfo_wins_byname(string_arg)) { - d_printf("Could not lookup WINS by name %s\n", string_arg); - goto done; - } - break; - case 'I': - if (!wbinfo_wins_byip(string_arg)) { - d_printf("Could not lookup WINS by IP %s\n", string_arg); - goto done; - } - break; - case 'U': - if (!wbinfo_uid_to_sid(int_arg)) { - d_printf("Could not convert uid %d to sid\n", int_arg); - goto done; - } - break; - case 'G': - if (!wbinfo_gid_to_sid(int_arg)) { - d_printf("Could not convert gid %d to sid\n", - int_arg); - goto done; - } - break; - case 'S': - if (!wbinfo_sid_to_uid(string_arg)) { - d_printf("Could not convert sid %s to uid\n", - string_arg); - goto done; - } - break; - case 'Y': - if (!wbinfo_sid_to_gid(string_arg)) { - d_printf("Could not convert sid %s to gid\n", - string_arg); - goto done; - } - break; - case 't': - if (!wbinfo_check_secret()) { - d_printf("Could not check secret\n"); - goto done; - } - break; - case 'm': - if (!wbinfo_list_domains()) { - d_printf("Could not list trusted domains\n"); - goto done; - } - break; - case OPT_SEQUENCE: - if (!wbinfo_show_sequence()) { - d_printf("Could not show sequence numbers\n"); - goto done; - } - break; - case 'r': - if (!wbinfo_get_usergroups(string_arg)) { - d_printf("Could not get groups for user %s\n", - string_arg); - goto done; - } - break; - case 'a': { - BOOL got_error = False; - - if (!wbinfo_auth(string_arg)) { - d_printf("Could not authenticate user %s with " - "plaintext password\n", string_arg); - got_error = True; - } - - if (!wbinfo_auth_crap(string_arg)) { - d_printf("Could not authenticate user %s with " - "challenge/response\n", string_arg); - got_error = True; - } - - if (got_error) - goto done; - break; - } - case 'p': { - if (!wbinfo_ping()) { - d_printf("could not ping winbindd!\n"); - goto done; - } - break; - } - case OPT_SET_AUTH_USER: - wbinfo_set_auth_user(string_arg); - break; - case OPT_GET_AUTH_USER: - wbinfo_get_auth_user(); - break; - default: - d_fprintf(stderr, "Invalid option\n"); - poptPrintHelp(pc, stderr, 0); - goto done; - } - } - - result = 0; - - /* Exit code */ - - done: - poptFreeContext(pc); - return result; -} diff --git a/source4/nsswitch/winbind_client.h b/source4/nsswitch/winbind_client.h deleted file mode 100644 index 4de2d57cc7..0000000000 --- a/source4/nsswitch/winbind_client.h +++ /dev/null @@ -1,16 +0,0 @@ -#include "winbind_nss_config.h" -#include "winbindd_nss.h" - -void init_request(struct winbindd_request *req,int rq_type); -NSS_STATUS winbindd_send_request(int req_type, - struct winbindd_request *request); -NSS_STATUS winbindd_get_response(struct winbindd_response *response); -NSS_STATUS winbindd_request(int req_type, - struct winbindd_request *request, - struct winbindd_response *response); -int winbind_open_pipe_sock(void); -int write_sock(void *buffer, int count); -int read_reply(struct winbindd_response *response); -void close_sock(void); -void free_response(struct winbindd_response *response); - diff --git a/source4/nsswitch/winbind_nss.c b/source4/nsswitch/winbind_nss.c deleted file mode 100644 index 0b4c0ce1d0..0000000000 --- a/source4/nsswitch/winbind_nss.c +++ /dev/null @@ -1,1341 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Windows NT Domain nsswitch 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. -*/ - -#include "winbind_client.h" - -#ifdef HAVE_NS_API_H -#undef VOLATILE - -#include <ns_daemon.h> -#endif - -#define MAX_GETPWENT_USERS 250 -#define MAX_GETGRENT_USERS 250 - -/* Prototypes from wb_common.c */ - -extern int winbindd_fd; - - -#ifdef HAVE_NS_API_H -/* IRIX version */ - -static int send_next_request(nsd_file_t *, struct winbindd_request *); -static int do_list(int state, nsd_file_t *rq); - -static nsd_file_t *current_rq = NULL; -static int current_winbind_xid = 0; -static int next_winbind_xid = 0; - -typedef struct winbind_xid { - int xid; - nsd_file_t *rq; - struct winbindd_request *request; - struct winbind_xid *next; -} winbind_xid_t; - -static winbind_xid_t *winbind_xids = (winbind_xid_t *)0; - -static int -winbind_xid_new(int xid, nsd_file_t *rq, struct winbindd_request *request) -{ - winbind_xid_t *new; - - nsd_logprintf(NSD_LOG_LOW, - "entering winbind_xid_new xid = %d rq = 0x%x, request = 0x%x\n", - xid, rq, request); - new = (winbind_xid_t *)nsd_calloc(1,sizeof(winbind_xid_t)); - if (!new) { - nsd_logprintf(NSD_LOG_RESOURCE,"winbind_xid_new: failed malloc\n"); - return NSD_ERROR; - } - - new->xid = xid; - new->rq = rq; - new->request = request; - new->next = winbind_xids; - winbind_xids = new; - - return NSD_CONTINUE; -} - -/* -** This routine will look down the xid list and return the request -** associated with an xid. We remove the record if it is found. -*/ -nsd_file_t * -winbind_xid_lookup(int xid, struct winbindd_request **requestp) -{ - winbind_xid_t **last, *dx; - nsd_file_t *result=0; - - for (last = &winbind_xids, dx = winbind_xids; dx && (dx->xid != xid); - last = &dx->next, dx = dx->next); - if (dx) { - *last = dx->next; - result = dx->rq; - *requestp = dx->request; - SAFE_FREE(dx); - } - nsd_logprintf(NSD_LOG_LOW, - "entering winbind_xid_lookup xid = %d rq = 0x%x, request = 0x%x\n", - xid, result, dx->request); - - return result; -} - -static int -winbind_startnext_timeout(nsd_file_t **rqp, nsd_times_t *to) -{ - nsd_file_t *rq; - struct winbindd_request *request; - - nsd_logprintf(NSD_LOG_MIN, "timeout (winbind startnext)\n"); - rq = to->t_file; - *rqp = rq; - nsd_timeout_remove(rq); - request = to->t_clientdata; - return(send_next_request(rq, request)); -} - -static void -dequeue_request() -{ - nsd_file_t *rq; - struct winbindd_request *request; - - /* - * Check for queued requests - */ - if (winbind_xids) { - nsd_logprintf(NSD_LOG_MIN, "timeout (winbind) unqueue xid %d\n", - current_winbind_xid); - rq = winbind_xid_lookup(current_winbind_xid++, &request); - /* cause a timeout on the queued request so we can send it */ - nsd_timeout_new(rq,1,winbind_startnext_timeout,request); - } -} - -static int -do_request(nsd_file_t *rq, struct winbindd_request *request) -{ - if (winbind_xids == NULL) { - /* - * No outstanding requests. - * Send off the request to winbindd - */ - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) sending request\n"); - return(send_next_request(rq, request)); - } else { - /* - * Just queue it up for now - previous callout or timout - * will start it up - */ - nsd_logprintf(NSD_LOG_MIN, - "lookup (winbind): queue request xid = %d\n", - next_winbind_xid); - return(winbind_xid_new(next_winbind_xid++, rq, request)); - } -} - -static int -winbind_callback(nsd_file_t **rqp, int fd) -{ - struct winbindd_response response; - struct winbindd_pw *pw = &response.data.pw; - struct winbindd_gr *gr = &response.data.gr; - nsd_file_t *rq; - NSS_STATUS status; - fstring result; - char *members; - int i, maxlen; - - dequeue_request(); - - nsd_logprintf(NSD_LOG_MIN, "entering callback (winbind)\n"); - - rq = current_rq; - *rqp = rq; - - nsd_timeout_remove(rq); - nsd_callback_remove(fd); - - ZERO_STRUCT(response); - status = winbindd_get_response(&response); - - if (status != NSS_STATUS_SUCCESS) { - /* free any extra data area in response structure */ - free_response(&response); - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) returning not found, status = %d\n", - status); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - - maxlen = sizeof(result) - 1; - - switch ((int)rq->f_cmd_data) { - case WINBINDD_WINS_BYNAME: - case WINBINDD_WINS_BYIP: - snprintf(result,maxlen,"%s\n",response.data.winsresp); - break; - case WINBINDD_GETPWUID: - case WINBINDD_GETPWNAM: - snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s\n", - pw->pw_name, - pw->pw_passwd, - pw->pw_uid, - pw->pw_gid, - pw->pw_gecos, - pw->pw_dir, - pw->pw_shell); - break; - case WINBINDD_GETGRNAM: - case WINBINDD_GETGRGID: - if (gr->num_gr_mem && response.extra_data) - members = response.extra_data; - else - members = ""; - snprintf(result,maxlen,"%s:%s:%d:%s\n", - gr->gr_name, gr->gr_passwd, gr->gr_gid, members); - break; - case WINBINDD_SETGRENT: - case WINBINDD_SETPWENT: - nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - SETPWENT/SETGRENT\n"); - free_response(&response); - return(do_list(1,rq)); - case WINBINDD_GETGRENT: - case WINBINDD_GETGRLST: - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) - %d GETGRENT responses\n", - response.data.num_entries); - if (response.data.num_entries) { - gr = (struct winbindd_gr *)response.extra_data; - if (! gr ) { - nsd_logprintf(NSD_LOG_MIN, " no extra_data\n"); - free_response(&response); - return NSD_ERROR; - } - members = (char *)response.extra_data + - (response.data.num_entries * sizeof(struct winbindd_gr)); - for (i = 0; i < response.data.num_entries; i++) { - snprintf(result,maxlen,"%s:%s:%d:%s\n", - gr->gr_name, gr->gr_passwd, gr->gr_gid, - &members[gr->gr_mem_ofs]); - nsd_logprintf(NSD_LOG_MIN, " GETGRENT %s\n",result); - nsd_append_element(rq,NS_SUCCESS,result,strlen(result)); - gr++; - } - } - i = response.data.num_entries; - free_response(&response); - if (i < MAX_GETPWENT_USERS) - return(do_list(2,rq)); - else - return(do_list(1,rq)); - case WINBINDD_GETPWENT: - nsd_logprintf(NSD_LOG_MIN, - "callback (winbind) - %d GETPWENT responses\n", - response.data.num_entries); - if (response.data.num_entries) { - pw = (struct winbindd_pw *)response.extra_data; - if (! pw ) { - nsd_logprintf(NSD_LOG_MIN, " no extra_data\n"); - free_response(&response); - return NSD_ERROR; - } - for (i = 0; i < response.data.num_entries; i++) { - snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s", - pw->pw_name, - pw->pw_passwd, - pw->pw_uid, - pw->pw_gid, - pw->pw_gecos, - pw->pw_dir, - pw->pw_shell); - nsd_logprintf(NSD_LOG_MIN, " GETPWENT %s\n",result); - nsd_append_element(rq,NS_SUCCESS,result,strlen(result)); - pw++; - } - } - i = response.data.num_entries; - free_response(&response); - if (i < MAX_GETPWENT_USERS) - return(do_list(2,rq)); - else - return(do_list(1,rq)); - case WINBINDD_ENDGRENT: - case WINBINDD_ENDPWENT: - nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - ENDPWENT/ENDGRENT\n"); - nsd_append_element(rq,NS_SUCCESS,"\n",1); - free_response(&response); - return NSD_NEXT; - default: - free_response(&response); - nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - no valid command\n"); - return NSD_NEXT; - } - nsd_logprintf(NSD_LOG_MIN, "callback (winbind) %s\n", result); - /* free any extra data area in response structure */ - free_response(&response); - nsd_set_result(rq,NS_SUCCESS,result,strlen(result),VOLATILE); - return NSD_OK; -} - -static int -winbind_timeout(nsd_file_t **rqp, nsd_times_t *to) -{ - nsd_file_t *rq; - - dequeue_request(); - - nsd_logprintf(NSD_LOG_MIN, "timeout (winbind)\n"); - - rq = to->t_file; - *rqp = rq; - - /* Remove the callback and timeout */ - nsd_callback_remove(winbindd_fd); - nsd_timeout_remove(rq); - - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; -} - -static int -send_next_request(nsd_file_t *rq, struct winbindd_request *request) -{ - NSS_STATUS status; - long timeout; - - timeout = 1000; - - nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) %d to = %d\n", - rq->f_cmd_data, timeout); - status = winbindd_send_request((int)rq->f_cmd_data,request); - SAFE_FREE(request); - - if (status != NSS_STATUS_SUCCESS) { - nsd_logprintf(NSD_LOG_MIN, - "send_next_request (winbind) error status = %d\n",status); - rq->f_status = status; - return NSD_NEXT; - } - - current_rq = rq; - - /* - * Set up callback and timeouts - */ - nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) fd = %d\n",winbindd_fd); - nsd_callback_new(winbindd_fd,winbind_callback,NSD_READ); - nsd_timeout_new(rq,timeout,winbind_timeout,(void *)0); - return NSD_CONTINUE; -} - -int init(void) -{ - nsd_logprintf(NSD_LOG_MIN, "entering init (winbind)\n"); - return(NSD_OK); -} - -int lookup(nsd_file_t *rq) -{ - char *map; - char *key; - struct winbindd_request *request; - - nsd_logprintf(NSD_LOG_MIN, "entering lookup (winbind)\n"); - if (! rq) - return NSD_ERROR; - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0); - if (! map || ! key) { - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) table or key not defined\n"); - rq->f_status = NS_BADREQ; - return NSD_ERROR; - } - - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind %s)\n",map); - - request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request)); - if (! request) { - nsd_logprintf(NSD_LOG_RESOURCE, - "lookup (winbind): failed malloc\n"); - return NSD_ERROR; - } - - if (strcasecmp(map,"passwd.byuid") == 0) { - request->data.uid = atoi(key); - rq->f_cmd_data = (void *)WINBINDD_GETPWUID; - } else if (strcasecmp(map,"passwd.byname") == 0) { - strncpy(request->data.username, key, - sizeof(request->data.username) - 1); - request->data.username[sizeof(request->data.username) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_GETPWNAM; - } else if (strcasecmp(map,"group.byname") == 0) { - strncpy(request->data.groupname, key, - sizeof(request->data.groupname) - 1); - request->data.groupname[sizeof(request->data.groupname) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_GETGRNAM; - } else if (strcasecmp(map,"group.bygid") == 0) { - request->data.gid = atoi(key); - rq->f_cmd_data = (void *)WINBINDD_GETGRGID; - } else if (strcasecmp(map,"hosts.byname") == 0) { - strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1); - request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_WINS_BYNAME; - } else if (strcasecmp(map,"hosts.byaddr") == 0) { - strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1); - request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0'; - rq->f_cmd_data = (void *)WINBINDD_WINS_BYIP; - } else { - /* - * Don't understand this map - just return not found - */ - nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) unknown table\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - - return(do_request(rq, request)); -} - -int list(nsd_file_t *rq) -{ - char *map; - - nsd_logprintf(NSD_LOG_MIN, "entering list (winbind)\n"); - if (! rq) - return NSD_ERROR; - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - if (! map ) { - nsd_logprintf(NSD_LOG_MIN, "list (winbind) table not defined\n"); - rq->f_status = NS_BADREQ; - return NSD_ERROR; - } - - nsd_logprintf(NSD_LOG_MIN, "list (winbind %s)\n",map); - - return (do_list(0,rq)); -} - -static int -do_list(int state, nsd_file_t *rq) -{ - char *map; - struct winbindd_request *request; - - nsd_logprintf(NSD_LOG_MIN, "entering do_list (winbind) state = %d\n",state); - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request)); - if (! request) { - nsd_logprintf(NSD_LOG_RESOURCE, - "do_list (winbind): failed malloc\n"); - return NSD_ERROR; - } - - if (strcasecmp(map,"passwd.byname") == 0) { - switch (state) { - case 0: - rq->f_cmd_data = (void *)WINBINDD_SETPWENT; - break; - case 1: - request->data.num_entries = MAX_GETPWENT_USERS; - rq->f_cmd_data = (void *)WINBINDD_GETPWENT; - break; - case 2: - rq->f_cmd_data = (void *)WINBINDD_ENDPWENT; - break; - default: - nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - } else if (strcasecmp(map,"group.byname") == 0) { - switch (state) { - case 0: - rq->f_cmd_data = (void *)WINBINDD_SETGRENT; - break; - case 1: - request->data.num_entries = MAX_GETGRENT_USERS; - rq->f_cmd_data = (void *)WINBINDD_GETGRENT; - break; - case 2: - rq->f_cmd_data = (void *)WINBINDD_ENDGRENT; - break; - default: - nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - } else { - /* - * Don't understand this map - just return not found - */ - nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown table\n"); - SAFE_FREE(request); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; - } - - return(do_request(rq, request)); -} - -#else - -/* Allocate some space from the nss static buffer. The buffer and buflen - are the pointers passed in by the C library to the _nss_ntdom_* - functions. */ - -static char *get_static(char **buffer, int *buflen, int len) -{ - char *result; - - /* Error check. We return false if things aren't set up right, or - there isn't enough buffer space left. */ - - if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) { - return NULL; - } - - /* Return an index into the static buffer */ - - result = *buffer; - *buffer += len; - *buflen -= len; - - return result; -} - -/* I've copied the strtok() replacement function next_token() from - lib/util_str.c as I really don't want to have to link in any other - objects if I can possibly avoid it. */ - -BOOL next_token(char **ptr,char *buff,char *sep, size_t bufsize) -{ - char *s; - BOOL quoted; - size_t len=1; - - if (!ptr) return(False); - - s = *ptr; - - /* default to simple separators */ - if (!sep) sep = " \t\n\r"; - - /* find the first non sep char */ - while (*s && strchr(sep,*s)) s++; - - /* nothing left? */ - if (! *s) return(False); - - /* copy over the token */ - for (quoted = False; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++) { - if (*s == '\"') { - quoted = !quoted; - } else { - len++; - *buff++ = *s; - } - } - - *ptr = (*s) ? s+1 : s; - *buff = 0; - - return(True); -} - - -/* Fill a pwent structure from a winbindd_response structure. We use - the static data passed to us by libc to put strings and stuff in. - Return NSS_STATUS_TRYAGAIN if we run out of memory. */ - -static NSS_STATUS fill_pwent(struct passwd *result, - struct winbindd_pw *pw, - char **buffer, size_t *buflen) -{ - /* User name */ - - if ((result->pw_name = - get_static(buffer, buflen, strlen(pw->pw_name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_name, pw->pw_name); - - /* Password */ - - if ((result->pw_passwd = - get_static(buffer, buflen, strlen(pw->pw_passwd) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_passwd, pw->pw_passwd); - - /* [ug]id */ - - result->pw_uid = pw->pw_uid; - result->pw_gid = pw->pw_gid; - - /* GECOS */ - - if ((result->pw_gecos = - get_static(buffer, buflen, strlen(pw->pw_gecos) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_gecos, pw->pw_gecos); - - /* Home directory */ - - if ((result->pw_dir = - get_static(buffer, buflen, strlen(pw->pw_dir) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_dir, pw->pw_dir); - - /* Logon shell */ - - if ((result->pw_shell = - get_static(buffer, buflen, strlen(pw->pw_shell) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->pw_shell, pw->pw_shell); - - /* The struct passwd for Solaris has some extra fields which must - be initialised or nscd crashes. */ - -#if HAVE_PASSWD_PW_COMMENT - result->pw_comment = ""; -#endif - -#if HAVE_PASSWD_PW_AGE - result->pw_age = ""; -#endif - - return NSS_STATUS_SUCCESS; -} - -/* Fill a grent structure from a winbindd_response structure. We use - the static data passed to us by libc to put strings and stuff in. - Return NSS_STATUS_TRYAGAIN if we run out of memory. */ - -static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr, - char *gr_mem, char **buffer, size_t *buflen) -{ - fstring name; - int i; - char *tst; - - /* Group name */ - - if ((result->gr_name = - get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->gr_name, gr->gr_name); - - /* Password */ - - if ((result->gr_passwd = - get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy(result->gr_passwd, gr->gr_passwd); - - /* gid */ - - result->gr_gid = gr->gr_gid; - - /* Group membership */ - - if ((gr->num_gr_mem < 0) || !gr_mem) { - gr->num_gr_mem = 0; - } - - /* this next value is a pointer to a pointer so let's align it */ - - /* Calculate number of extra bytes needed to align on pointer size boundry */ - if ((i = (unsigned long)(*buffer) % sizeof(char*)) != 0) - i = sizeof(char*) - i; - - if ((tst = get_static(buffer, buflen, ((gr->num_gr_mem + 1) * - sizeof(char *)+i))) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - result->gr_mem = (char **)(tst + i); - - if (gr->num_gr_mem == 0) { - - /* Group is empty */ - - *(result->gr_mem) = NULL; - return NSS_STATUS_SUCCESS; - } - - /* Start looking at extra data */ - - i = 0; - - while(next_token((char **)&gr_mem, name, ",", sizeof(fstring))) { - - /* Allocate space for member */ - - if (((result->gr_mem)[i] = - get_static(buffer, buflen, strlen(name) + 1)) == NULL) { - - /* Out of memory */ - - return NSS_STATUS_TRYAGAIN; - } - - strcpy((result->gr_mem)[i], name); - i++; - } - - /* Terminate list */ - - (result->gr_mem)[i] = NULL; - - return NSS_STATUS_SUCCESS; -} - -/* - * NSS user functions - */ - -static struct winbindd_response getpwent_response; - -static int ndx_pw_cache; /* Current index into pwd cache */ -static int num_pw_cache; /* Current size of pwd cache */ - -/* Rewind "file pointer" to start of ntdom password database */ - -NSS_STATUS -_nss_winbind_setpwent(void) -{ -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setpwent\n", getpid()); -#endif - - if (num_pw_cache > 0) { - ndx_pw_cache = num_pw_cache = 0; - free_response(&getpwent_response); - } - - return winbindd_request(WINBINDD_SETPWENT, NULL, NULL); -} - -/* Close ntdom password database "file pointer" */ - -NSS_STATUS -_nss_winbind_endpwent(void) -{ -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endpwent\n", getpid()); -#endif - - if (num_pw_cache > 0) { - ndx_pw_cache = num_pw_cache = 0; - free_response(&getpwent_response); - } - - return winbindd_request(WINBINDD_ENDPWENT, NULL, NULL); -} - -/* Fetch the next password entry from ntdom password database */ - -NSS_STATUS -_nss_winbind_getpwent_r(struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - struct winbindd_request request; - static int called_again; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwent\n", getpid()); -#endif - - /* Return an entry from the cache if we have one, or if we are - called again because we exceeded our static buffer. */ - - if ((ndx_pw_cache < num_pw_cache) || called_again) { - goto return_result; - } - - /* Else call winbindd to get a bunch of entries */ - - if (num_pw_cache > 0) { - free_response(&getpwent_response); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(getpwent_response); - - request.data.num_entries = MAX_GETPWENT_USERS; - - ret = winbindd_request(WINBINDD_GETPWENT, &request, - &getpwent_response); - - if (ret == NSS_STATUS_SUCCESS) { - struct winbindd_pw *pw_cache; - - /* Fill cache */ - - ndx_pw_cache = 0; - num_pw_cache = getpwent_response.data.num_entries; - - /* Return a result */ - - return_result: - - pw_cache = getpwent_response.extra_data; - - /* Check data is valid */ - - if (pw_cache == NULL) { - return NSS_STATUS_NOTFOUND; - } - - ret = fill_pwent(result, &pw_cache[ndx_pw_cache], - &buffer, &buflen); - - /* Out of memory - try again */ - - if (ret == NSS_STATUS_TRYAGAIN) { - called_again = True; - *errnop = errno = ERANGE; - return ret; - } - - *errnop = errno = 0; - called_again = False; - ndx_pw_cache++; - - /* If we've finished with this lot of results free cache */ - - if (ndx_pw_cache == num_pw_cache) { - ndx_pw_cache = num_pw_cache = 0; - free_response(&getpwent_response); - } - } - - return ret; -} - -/* Return passwd struct from uid */ - -NSS_STATUS -_nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response=0; - - /* If our static buffer needs to be expanded we are called again */ - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - request.data.uid = uid; - - ret = winbindd_request(WINBINDD_GETPWUID, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_pwent(result, &response.data.pw, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - } - - } else { - - /* We've been called again */ - - ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - - keep_response = False; - *errnop = errno = 0; - } - - free_response(&response); - return ret; -} - -/* Return passwd struct from username */ - -NSS_STATUS -_nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getpwnam %s\n", getpid(), name); -#endif - - /* If our static buffer needs to be expanded we are called again */ - - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(response); - ZERO_STRUCT(request); - - strncpy(request.data.username, name, - sizeof(request.data.username) - 1); - request.data.username - [sizeof(request.data.username) - 1] = '\0'; - - ret = winbindd_request(WINBINDD_GETPWNAM, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_pwent(result, &response.data.pw, &buffer, - &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - } - - } else { - - /* We've been called again */ - - ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - - keep_response = False; - *errnop = errno = 0; - } - - free_response(&response); - return ret; -} - -/* - * NSS group functions - */ - -static struct winbindd_response getgrent_response; - -static int ndx_gr_cache; /* Current index into grp cache */ -static int num_gr_cache; /* Current size of grp cache */ - -/* Rewind "file pointer" to start of ntdom group database */ - -NSS_STATUS -_nss_winbind_setgrent(void) -{ -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: setgrent\n", getpid()); -#endif - - if (num_gr_cache > 0) { - ndx_gr_cache = num_gr_cache = 0; - free_response(&getgrent_response); - } - - return winbindd_request(WINBINDD_SETGRENT, NULL, NULL); -} - -/* Close "file pointer" for ntdom group database */ - -NSS_STATUS -_nss_winbind_endgrent(void) -{ -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: endgrent\n", getpid()); -#endif - - if (num_gr_cache > 0) { - ndx_gr_cache = num_gr_cache = 0; - free_response(&getgrent_response); - } - - return winbindd_request(WINBINDD_ENDGRENT, NULL, NULL); -} - -/* Get next entry from ntdom group database */ - -static NSS_STATUS -winbind_getgrent(enum winbindd_cmd cmd, - struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_request request; - static int called_again; - - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrent\n", getpid()); -#endif - - /* Return an entry from the cache if we have one, or if we are - called again because we exceeded our static buffer. */ - - if ((ndx_gr_cache < num_gr_cache) || called_again) { - goto return_result; - } - - /* Else call winbindd to get a bunch of entries */ - - if (num_gr_cache > 0) { - free_response(&getgrent_response); - } - - ZERO_STRUCT(request); - ZERO_STRUCT(getgrent_response); - - request.data.num_entries = MAX_GETGRENT_USERS; - - ret = winbindd_request(cmd, &request, - &getgrent_response); - - if (ret == NSS_STATUS_SUCCESS) { - struct winbindd_gr *gr_cache; - int mem_ofs; - - /* Fill cache */ - - ndx_gr_cache = 0; - num_gr_cache = getgrent_response.data.num_entries; - - /* Return a result */ - - return_result: - - gr_cache = getgrent_response.extra_data; - - /* Check data is valid */ - - if (gr_cache == NULL) { - return NSS_STATUS_NOTFOUND; - } - - /* Fill group membership. The offset into the extra data - for the group membership is the reported offset plus the - size of all the winbindd_gr records returned. */ - - mem_ofs = gr_cache[ndx_gr_cache].gr_mem_ofs + - num_gr_cache * sizeof(struct winbindd_gr); - - ret = fill_grent(result, &gr_cache[ndx_gr_cache], - ((char *)getgrent_response.extra_data)+mem_ofs, - &buffer, &buflen); - - /* Out of memory - try again */ - - if (ret == NSS_STATUS_TRYAGAIN) { - called_again = True; - *errnop = errno = ERANGE; - return ret; - } - - *errnop = 0; - called_again = False; - ndx_gr_cache++; - - /* If we've finished with this lot of results free cache */ - - if (ndx_gr_cache == num_gr_cache) { - ndx_gr_cache = num_gr_cache = 0; - free_response(&getgrent_response); - } - } - - return ret; -} - - -NSS_STATUS -_nss_winbind_getgrent_r(struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - return winbind_getgrent(WINBINDD_GETGRENT, result, buffer, buflen, errnop); -} - -NSS_STATUS -_nss_winbind_getgrlst_r(struct group *result, - char *buffer, size_t buflen, int *errnop) -{ - return winbind_getgrent(WINBINDD_GETGRLST, result, buffer, buflen, errnop); -} - -/* Return group struct from group name */ - -NSS_STATUS -_nss_winbind_getgrnam_r(const char *name, - struct group *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrnam %s\n", getpid(), name); -#endif - - /* If our static buffer needs to be expanded we are called again */ - - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.groupname, name, - sizeof(request.data.groupname)); - request.data.groupname - [sizeof(request.data.groupname) - 1] = '\0'; - - ret = winbindd_request(WINBINDD_GETGRNAM, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - ret = fill_grent(result, &response.data.gr, - response.extra_data, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - } - - } else { - - /* We've been called again */ - - ret = fill_grent(result, &response.data.gr, - response.extra_data, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - - keep_response = False; - *errnop = 0; - } - - free_response(&response); - return ret; -} - -/* Return group struct from gid */ - -NSS_STATUS -_nss_winbind_getgrgid_r(gid_t gid, - struct group *result, char *buffer, - size_t buflen, int *errnop) -{ - NSS_STATUS ret; - static struct winbindd_response response; - struct winbindd_request request; - static int keep_response; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid); -#endif - - /* If our static buffer needs to be expanded we are called again */ - - if (!keep_response) { - - /* Call for the first time */ - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - request.data.gid = gid; - - ret = winbindd_request(WINBINDD_GETGRGID, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - - ret = fill_grent(result, &response.data.gr, - response.extra_data, - &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - } - - } else { - - /* We've been called again */ - - ret = fill_grent(result, &response.data.gr, - response.extra_data, &buffer, &buflen); - - if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; - *errnop = errno = ERANGE; - return ret; - } - - keep_response = False; - *errnop = 0; - } - - free_response(&response); - return ret; -} - -/* Initialise supplementary groups */ - -NSS_STATUS -_nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, - long int *size, gid_t **groups, long int limit, - int *errnop) -{ - NSS_STATUS ret; - struct winbindd_request request; - struct winbindd_response response; - int i; - -#ifdef DEBUG_NSS - fprintf(stderr, "[%5d]: initgroups %s (%d)\n", getpid(), - user, group); -#endif - - ZERO_STRUCT(request); - ZERO_STRUCT(response); - - strncpy(request.data.username, user, - sizeof(request.data.username) - 1); - - ret = winbindd_request(WINBINDD_GETGROUPS, &request, &response); - - if (ret == NSS_STATUS_SUCCESS) { - int num_gids = response.data.num_entries; - gid_t *gid_list = (gid_t *)response.extra_data; - - /* Copy group list to client */ - - for (i = 0; i < num_gids; i++) { - - /* Skip primary group */ - - if (gid_list[i] == group) continue; - - /* Add to buffer */ - - if (*start == *size && limit <= 0) { - (*groups) = realloc( - (*groups), (2 * (*size) + 1) * sizeof(**groups)); - if (! *groups) goto done; - *size = 2 * (*size) + 1; - } - - if (*start == *size) goto done; - - (*groups)[*start] = gid_list[i]; - *start += 1; - - /* Filled buffer? */ - - if (*start == limit) goto done; - } - } - - /* Back to your regularly scheduled programming */ - - done: - return ret; -} - -#endif diff --git a/source4/nsswitch/winbind_nss_config.h b/source4/nsswitch/winbind_nss_config.h deleted file mode 100644 index 2faaa30d1b..0000000000 --- a/source4/nsswitch/winbind_nss_config.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - 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 _WINBIND_NSS_CONFIG_H -#define _WINBIND_NSS_CONFIG_H - -/* Include header files from data in config.h file */ - -#ifndef NO_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> - -#ifdef HAVE_STDLIB_H -#include <stdlib.h> -#endif - -#ifdef HAVE_UNISTD_H -#include <unistd.h> -#endif - -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.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 - -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#else -#ifdef HAVE_SYS_FCNTL_H -#include <sys/fcntl.h> -#endif -#endif - -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> -#include <pwd.h> -#include "nsswitch/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 */ -#ifndef ZERO_STRUCT -#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) -#endif - -/* zero a structure given a pointer to the structure */ -#ifndef ZERO_STRUCTP -#define ZERO_STRUCTP(x) { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } -#endif - -/* 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/source4/nsswitch/winbind_nss_solaris.c b/source4/nsswitch/winbind_nss_solaris.c deleted file mode 100644 index f3bd05b77a..0000000000 --- a/source4/nsswitch/winbind_nss_solaris.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - Solaris NSS wrapper for winbind - - Shirish Kalele 2000 - - Based on Luke Howard's ldap_nss module for Solaris - */ - -/* - Copyright (C) 1997-2003 Luke Howard. - This file is part of the nss_ldap library. - - The nss_ldap 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. - - The nss_ldap 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 the nss_ldap library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -#include <stdlib.h> -#include <sys/types.h> -#include <sys/param.h> -#include <string.h> -#include <pwd.h> -#include "includes.h" -#include <syslog.h> -#if !defined(HPUX) -#include <sys/syslog.h> -#endif /*hpux*/ -#include "winbind_nss_config.h" - -#if defined(HAVE_NSS_COMMON_H) || defined(HPUX) - -#undef NSS_DEBUG - -#ifdef NSS_DEBUG -#define NSS_DEBUG(str) syslog(LOG_DEBUG, "nss_winbind: %s", str); -#else -#define NSS_DEBUG(str) ; -#endif - -#define NSS_ARGS(args) ((nss_XbyY_args_t *)args) - -#define make_pwent_str(dest, src) \ -{ \ - if((dest = get_static(buffer, buflen, strlen(src)+1)) == NULL) \ - { \ - *errnop = ERANGE; \ - NSS_DEBUG("ERANGE error"); \ - return NSS_STATUS_TRYAGAIN; \ - } \ - strcpy(dest, src); \ -} - -static NSS_STATUS _nss_winbind_setpwent_solwrap (nss_backend_t* be, void* args) -{ - NSS_DEBUG("_nss_winbind_setpwent_solwrap"); - return _nss_winbind_setpwent(); -} - -static NSS_STATUS -_nss_winbind_endpwent_solwrap (nss_backend_t * be, void *args) -{ - NSS_DEBUG("_nss_winbind_endpwent_solwrap"); - return _nss_winbind_endpwent(); -} - -static NSS_STATUS -_nss_winbind_getpwent_solwrap (nss_backend_t* be, void *args) -{ - NSS_STATUS ret; - char* buffer = NSS_ARGS(args)->buf.buffer; - int buflen = NSS_ARGS(args)->buf.buflen; - struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; - int* errnop = &NSS_ARGS(args)->erange; - char logmsg[80]; - - ret = _nss_winbind_getpwent_r(result, buffer, - buflen, errnop); - - if(ret == NSS_STATUS_SUCCESS) - { - snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning user: %s\n", - result->pw_name); - NSS_DEBUG(logmsg); - NSS_ARGS(args)->returnval = (void*) result; - } else { - snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning error: %d.\n",ret); - NSS_DEBUG(logmsg); - } - - return ret; -} - -static NSS_STATUS -_nss_winbind_getpwnam_solwrap (nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getpwnam_solwrap"); - - ret = _nss_winbind_getpwnam_r (NSS_ARGS(args)->key.name, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS -_nss_winbind_getpwuid_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getpwuid_solwrap"); - ret = _nss_winbind_getpwuid_r (NSS_ARGS(args)->key.uid, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS _nss_winbind_passwd_destr (nss_backend_t * be, void *args) -{ - SAFE_FREE(be); - NSS_DEBUG("_nss_winbind_passwd_destr"); - return NSS_STATUS_SUCCESS; -} - -static nss_backend_op_t passwd_ops[] = -{ - _nss_winbind_passwd_destr, - _nss_winbind_endpwent_solwrap, /* NSS_DBOP_ENDENT */ - _nss_winbind_setpwent_solwrap, /* NSS_DBOP_SETENT */ - _nss_winbind_getpwent_solwrap, /* NSS_DBOP_GETENT */ - _nss_winbind_getpwnam_solwrap, /* NSS_DBOP_PASSWD_BYNAME */ - _nss_winbind_getpwuid_solwrap /* NSS_DBOP_PASSWD_BYUID */ -}; - -nss_backend_t* -_nss_winbind_passwd_constr (const char* db_name, - const char* src_name, - const char* cfg_args) -{ - nss_backend_t *be; - - if(!(be = (nss_backend_t*) malloc(sizeof(nss_backend_t))) ) - return NULL; - - be->ops = passwd_ops; - be->n_ops = sizeof(passwd_ops) / sizeof(nss_backend_op_t); - - NSS_DEBUG("Initialized nss_winbind passwd backend"); - return be; -} - -/***************************************************************** - GROUP database backend - *****************************************************************/ - -static NSS_STATUS _nss_winbind_setgrent_solwrap (nss_backend_t* be, void* args) -{ - NSS_DEBUG("_nss_winbind_setgrent_solwrap"); - return _nss_winbind_setgrent(); -} - -static NSS_STATUS -_nss_winbind_endgrent_solwrap (nss_backend_t * be, void *args) -{ - NSS_DEBUG("_nss_winbind_endgrent_solwrap"); - return _nss_winbind_endgrent(); -} - -static NSS_STATUS -_nss_winbind_getgrent_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - char* buffer = NSS_ARGS(args)->buf.buffer; - int buflen = NSS_ARGS(args)->buf.buflen; - struct group* result = (struct group*) NSS_ARGS(args)->buf.result; - int* errnop = &NSS_ARGS(args)->erange; - char logmsg[80]; - - ret = _nss_winbind_getgrent_r(result, buffer, - buflen, errnop); - - if(ret == NSS_STATUS_SUCCESS) - { - snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning group: %s\n", result->gr_name); - NSS_DEBUG(logmsg); - NSS_ARGS(args)->returnval = (void*) result; - } else { - snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning error: %d.\n", ret); - NSS_DEBUG(logmsg); - } - - return ret; - -} - -static NSS_STATUS -_nss_winbind_getgrnam_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct group* result = (struct group*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getgrnam_solwrap"); - ret = _nss_winbind_getgrnam_r(NSS_ARGS(args)->key.name, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS -_nss_winbind_getgrgid_solwrap(nss_backend_t* be, void* args) -{ - NSS_STATUS ret; - struct group* result = (struct group*) NSS_ARGS(args)->buf.result; - - NSS_DEBUG("_nss_winbind_getgrgid_solwrap"); - ret = _nss_winbind_getgrgid_r (NSS_ARGS(args)->key.gid, - result, - NSS_ARGS(args)->buf.buffer, - NSS_ARGS(args)->buf.buflen, - &NSS_ARGS(args)->erange); - - if(ret == NSS_STATUS_SUCCESS) - NSS_ARGS(args)->returnval = (void*) result; - - return ret; -} - -static NSS_STATUS -_nss_winbind_getgroupsbymember_solwrap(nss_backend_t* be, void* args) -{ - NSS_DEBUG("_nss_winbind_getgroupsbymember"); - return NSS_STATUS_NOTFOUND; -} - -static NSS_STATUS -_nss_winbind_group_destr (nss_backend_t* be, void* args) -{ - SAFE_FREE(be); - NSS_DEBUG("_nss_winbind_group_destr"); - return NSS_STATUS_SUCCESS; -} - -static nss_backend_op_t group_ops[] = -{ - _nss_winbind_group_destr, - _nss_winbind_endgrent_solwrap, - _nss_winbind_setgrent_solwrap, - _nss_winbind_getgrent_solwrap, - _nss_winbind_getgrnam_solwrap, - _nss_winbind_getgrgid_solwrap, - _nss_winbind_getgroupsbymember_solwrap -}; - -nss_backend_t* -_nss_winbind_group_constr (const char* db_name, - const char* src_name, - const char* cfg_args) -{ - nss_backend_t* be; - - if(!(be = (nss_backend_t*) malloc(sizeof(nss_backend_t))) ) - return NULL; - - be->ops = group_ops; - be->n_ops = sizeof(group_ops) / sizeof(nss_backend_op_t); - - NSS_DEBUG("Initialized nss_winbind group backend"); - return be; -} - -#endif /* SUN_NSS */ - - diff --git a/source4/nsswitch/winbindd.c b/source4/nsswitch/winbindd.c deleted file mode 100644 index 23394f5e8c..0000000000 --- a/source4/nsswitch/winbindd.c +++ /dev/null @@ -1,951 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) by Tim Potter 2000-2002 - Copyright (C) Andrew Tridgell 2002 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -BOOL opt_nocache = False; -BOOL opt_dual_daemon = False; - -/* Reload configuration */ - -static BOOL reload_services_file(BOOL test) -{ - BOOL ret; - pstring logfile; - - if (lp_loaded()) { - pstring fname; - - pstrcpy(fname,lp_configfile()); - if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) { - pstrcpy(dyn_CONFIGFILE,fname); - test = False; - } - } - - snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - - reopen_logs(); - ret = lp_load(dyn_CONFIGFILE,False,False,True); - - snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - - reopen_logs(); - load_interfaces(); - - return(ret); -} - -/******************************************************************* - Print out all talloc memory info. -********************************************************************/ - -void return_all_talloc_info(int msg_type, pid_t src_pid, void *buf, size_t len) -{ - TALLOC_CTX *ctx = talloc_init("info context"); - char *info = NULL; - - if (!ctx) - return; - - info = talloc_describe_all(ctx); - if (info) - DEBUG(10,(info)); - message_send_pid(src_pid, MSG_TALLOC_USAGE, info, info ? strlen(info) + 1: 0, True); - talloc_destroy(ctx); -} - -#if DUMP_CORE - -/**************************************************************************** ** - Prepare to dump a core file - carefully! - **************************************************************************** */ - -static BOOL dump_core(void) -{ - char *p; - pstring dname; - pstrcpy( dname, lp_logfile() ); - if ((p=strrchr(dname,'/'))) - *p=0; - pstrcat( dname, "/corefiles" ); - mkdir( dname, 0700 ); - sys_chown( dname, getuid(), getgid() ); - chmod( dname, 0700 ); - if ( chdir(dname) ) - return( False ); - umask( ~(0700) ); - -#ifdef HAVE_GETRLIMIT -#ifdef RLIMIT_CORE - { - struct rlimit rlp; - getrlimit( RLIMIT_CORE, &rlp ); - rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur ); - setrlimit( RLIMIT_CORE, &rlp ); - getrlimit( RLIMIT_CORE, &rlp ); - DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) ); - } -#endif -#endif - - DEBUG(0,("Dumping core in %s\n",dname)); - abort(); - return( True ); -} /* dump_core */ -#endif - -/**************************************************************************** ** - Handle a fault.. - **************************************************************************** */ - -static void fault_quit(void) -{ -#if DUMP_CORE - dump_core(); -#endif -} - -static void winbindd_status(void) -{ - struct winbindd_cli_state *tmp; - - DEBUG(0, ("winbindd status:\n")); - - /* Print client state information */ - - DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients())); - - if (DEBUGLEVEL >= 2 && winbindd_num_clients()) { - DEBUG(2, ("\tclient list:\n")); - for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) { - DEBUG(2, ("\t\tpid %d, sock %d, rbl %d, wbl %d\n", - tmp->pid, tmp->sock, tmp->read_buf_len, - tmp->write_buf_len)); - } - } -} - -/* Print winbindd status to log file */ - -static void print_winbindd_status(void) -{ - winbindd_status(); - winbindd_idmap_status(); - winbindd_cm_status(); -} - -/* Flush client cache */ - -static void flush_caches(void) -{ - /* Clear cached user and group enumation info */ - wcache_flush_cache(); -} - -/* Handle the signal by unlinking socket and exiting */ - -static void terminate(void) -{ - pstring path; - - winbindd_idmap_close(); - - /* Remove socket file */ - snprintf(path, sizeof(path), "%s/%s", - WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME); - unlink(path); - exit(0); -} - -static BOOL do_sigterm; - -static void termination_handler(int signum) -{ - do_sigterm = True; - sys_select_signal(); -} - -static BOOL do_sigusr2; - -static void sigusr2_handler(int signum) -{ - do_sigusr2 = True; - sys_select_signal(); -} - -static BOOL do_sighup; - -static void sighup_handler(int signum) -{ - do_sighup = True; - sys_select_signal(); -} - -struct dispatch_table { - enum winbindd_cmd cmd; - enum winbindd_result (*fn)(struct winbindd_cli_state *state); - const char *winbindd_cmd_name; -}; - -static struct dispatch_table dispatch_table[] = { - - /* User functions */ - - { WINBINDD_GETPWNAM, winbindd_getpwnam, "GETPWNAM" }, - { WINBINDD_GETPWUID, winbindd_getpwuid, "GETPWUID" }, - - { WINBINDD_SETPWENT, winbindd_setpwent, "SETPWENT" }, - { WINBINDD_ENDPWENT, winbindd_endpwent, "ENDPWENT" }, - { WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" }, - - { WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" }, - - /* Group functions */ - - { WINBINDD_GETGRNAM, winbindd_getgrnam, "GETGRNAM" }, - { WINBINDD_GETGRGID, winbindd_getgrgid, "GETGRGID" }, - { WINBINDD_SETGRENT, winbindd_setgrent, "SETGRENT" }, - { WINBINDD_ENDGRENT, winbindd_endgrent, "ENDGRENT" }, - { WINBINDD_GETGRENT, winbindd_getgrent, "GETGRENT" }, - { WINBINDD_GETGRLST, winbindd_getgrent, "GETGRLST" }, - - /* PAM auth functions */ - - { WINBINDD_PAM_AUTH, winbindd_pam_auth, "PAM_AUTH" }, - { WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" }, - { WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" }, - - /* Enumeration functions */ - - { WINBINDD_LIST_USERS, winbindd_list_users, "LIST_USERS" }, - { WINBINDD_LIST_GROUPS, winbindd_list_groups, "LIST_GROUPS" }, - { WINBINDD_LIST_TRUSTDOM, winbindd_list_trusted_domains, "LIST_TRUSTDOM" }, - { WINBINDD_SHOW_SEQUENCE, winbindd_show_sequence, "SHOW_SEQUENCE" }, - - /* SID related functions */ - - { WINBINDD_LOOKUPSID, winbindd_lookupsid, "LOOKUPSID" }, - { WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" }, - - /* Lookup related functions */ - - { WINBINDD_SID_TO_UID, winbindd_sid_to_uid, "SID_TO_UID" }, - { WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" }, - { WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" }, - { WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" }, - - /* Miscellaneous */ - - { WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct, "CHECK_MACHACC" }, - { WINBINDD_PING, winbindd_ping, "PING" }, - { WINBINDD_INFO, winbindd_info, "INFO" }, - { WINBINDD_INTERFACE_VERSION, winbindd_interface_version, "INTERFACE_VERSION" }, - { WINBINDD_DOMAIN_NAME, winbindd_domain_name, "DOMAIN_NAME" }, - { WINBINDD_NETBIOS_NAME, winbindd_netbios_name, "NETBIOS_NAME" }, - - /* WINS functions */ - - { WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" }, - { WINBINDD_WINS_BYIP, winbindd_wins_byip, "WINS_BYIP" }, - - /* End of list */ - - { WINBINDD_NUM_CMDS, NULL, "NONE" } -}; - -static void process_request(struct winbindd_cli_state *state) -{ - struct dispatch_table *table = dispatch_table; - - /* Free response data - we may be interrupted and receive another - command before being able to send this data off. */ - - SAFE_FREE(state->response.extra_data); - - ZERO_STRUCT(state->response); - - state->response.result = WINBINDD_ERROR; - state->response.length = sizeof(struct winbindd_response); - - /* Process command */ - - for (table = dispatch_table; table->fn; table++) { - if (state->request.cmd == table->cmd) { - DEBUG(10,("process_request: request fn %s\n", table->winbindd_cmd_name )); - state->response.result = table->fn(state); - break; - } - } - - if (!table->fn) - DEBUG(10,("process_request: unknown request fn number %d\n", (int)state->request.cmd )); - - /* In case extra data pointer is NULL */ - - if (!state->response.extra_data) - state->response.length = sizeof(struct winbindd_response); -} - -/* Process a new connection by adding it to the client connection list */ - -static void new_connection(int listen_sock) -{ - struct sockaddr_un sunaddr; - struct winbindd_cli_state *state; - socklen_t len; - int sock; - - /* Accept connection */ - - len = sizeof(sunaddr); - - do { - sock = accept(listen_sock, (struct sockaddr *)&sunaddr, &len); - } while (sock == -1 && errno == EINTR); - - if (sock == -1) - return; - - DEBUG(6,("accepted socket %d\n", sock)); - - /* Create new connection structure */ - - if ((state = (struct winbindd_cli_state *) - malloc(sizeof(*state))) == NULL) - return; - - ZERO_STRUCTP(state); - state->sock = sock; - - state->last_access = time(NULL); - - /* Add to connection list */ - - winbindd_add_client(state); -} - -/* Remove a client connection from client connection list */ - -static void remove_client(struct winbindd_cli_state *state) -{ - /* It's a dead client - hold a funeral */ - - if (state != NULL) { - - /* Close socket */ - - close(state->sock); - - /* Free any getent state */ - - free_getent_state(state->getpwent_state); - free_getent_state(state->getgrent_state); - - /* We may have some extra data that was not freed if the - client was killed unexpectedly */ - - SAFE_FREE(state->response.extra_data); - - /* Remove from list and free */ - - winbindd_remove_client(state); - SAFE_FREE(state); - } -} - - -/* Shutdown client connection which has been idle for the longest time */ - -static BOOL remove_idle_client(void) -{ - struct winbindd_cli_state *state, *remove_state = NULL; - time_t last_access = 0; - int nidle = 0; - - for (state = winbindd_client_list(); state; state = state->next) { - if (state->read_buf_len == 0 && state->write_buf_len == 0 && - !state->getpwent_state && !state->getgrent_state) { - nidle++; - if (!last_access || state->last_access < last_access) { - last_access = state->last_access; - remove_state = state; - } - } - } - - if (remove_state) { - DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n", - nidle, remove_state->sock, (unsigned int)remove_state->pid)); - remove_client(remove_state); - return True; - } - - return False; -} - -/* Process a complete received packet from a client */ - -void winbind_process_packet(struct winbindd_cli_state *state) -{ - /* Process request */ - - /* Ensure null termination of entire request */ - state->request.null_term = '\0'; - - state->pid = state->request.pid; - - process_request(state); - - /* Update client state */ - - state->read_buf_len = 0; - state->write_buf_len = sizeof(struct winbindd_response); - - /* we might need to send it to the dual daemon */ - if (opt_dual_daemon) { - dual_send_request(state); - } -} - -/* Read some data from a client connection */ - -void winbind_client_read(struct winbindd_cli_state *state) -{ - int n; - - /* Read data */ - - n = sys_read(state->sock, state->read_buf_len + - (char *)&state->request, - sizeof(state->request) - state->read_buf_len); - - DEBUG(10,("client_read: read %d bytes. Need %d more for a full request.\n", n, sizeof(state->request) - n - state->read_buf_len )); - - /* Read failed, kill client */ - - if (n == -1 || n == 0) { - DEBUG(5,("read failed on sock %d, pid %d: %s\n", - state->sock, state->pid, - (n == -1) ? strerror(errno) : "EOF")); - - state->finished = True; - return; - } - - /* Update client state */ - - state->read_buf_len += n; - state->last_access = time(NULL); -} - -/* Write some data to a client connection */ - -static void client_write(struct winbindd_cli_state *state) -{ - char *data; - int num_written; - - /* Write some data */ - - if (!state->write_extra_data) { - - /* Write response structure */ - - data = (char *)&state->response + sizeof(state->response) - - state->write_buf_len; - - } else { - - /* Write extra data */ - - data = (char *)state->response.extra_data + - state->response.length - - sizeof(struct winbindd_response) - - state->write_buf_len; - } - - num_written = sys_write(state->sock, data, state->write_buf_len); - - DEBUG(10,("client_write: wrote %d bytes.\n", num_written )); - - /* Write failed, kill cilent */ - - if (num_written == -1 || num_written == 0) { - - DEBUG(3,("write failed on sock %d, pid %d: %s\n", - state->sock, state->pid, - (num_written == -1) ? strerror(errno) : "EOF")); - - state->finished = True; - - SAFE_FREE(state->response.extra_data); - - return; - } - - /* Update client state */ - - state->write_buf_len -= num_written; - state->last_access = time(NULL); - - /* Have we written all data? */ - - if (state->write_buf_len == 0) { - - /* Take care of extra data */ - - if (state->write_extra_data) { - - SAFE_FREE(state->response.extra_data); - - state->write_extra_data = False; - - DEBUG(10,("client_write: client_write: complete response written.\n")); - - } else if (state->response.length > - sizeof(struct winbindd_response)) { - - /* Start writing extra data */ - - state->write_buf_len = - state->response.length - - sizeof(struct winbindd_response); - - DEBUG(10,("client_write: need to write %d extra data bytes.\n", (int)state->write_buf_len)); - - state->write_extra_data = True; - } - } -} - -/* Process incoming clients on listen_sock. We use a tricky non-blocking, - non-forking, non-threaded model which allows us to handle many - simultaneous connections while remaining impervious to many denial of - service attacks. */ - -static void process_loop(void) -{ - /* We'll be doing this a lot */ - - while (1) { - struct winbindd_cli_state *state; - fd_set r_fds, w_fds; - int maxfd, listen_sock, selret; - struct timeval timeout; - - /* Handle messages */ - - message_dispatch(); - - /* rescan the trusted domains list. This must be done - regularly to cope with transitive trusts */ - rescan_trusted_domains(False); - - /* Free up temporary memory */ - - lp_talloc_free(); - main_loop_talloc_free(); - - /* Initialise fd lists for select() */ - - listen_sock = open_winbindd_socket(); - - if (listen_sock == -1) { - perror("open_winbind_socket"); - exit(1); - } - - maxfd = listen_sock; - - FD_ZERO(&r_fds); - FD_ZERO(&w_fds); - FD_SET(listen_sock, &r_fds); - - timeout.tv_sec = WINBINDD_ESTABLISH_LOOP; - timeout.tv_usec = 0; - - if (opt_dual_daemon) { - maxfd = dual_select_setup(&w_fds, maxfd); - } - - /* Set up client readers and writers */ - - state = winbindd_client_list(); - - while (state) { - - /* Dispose of client connection if it is marked as - finished */ - - if (state->finished) { - struct winbindd_cli_state *next = state->next; - - remove_client(state); - state = next; - continue; - } - - /* Select requires we know the highest fd used */ - - if (state->sock > maxfd) - maxfd = state->sock; - - /* Add fd for reading */ - - if (state->read_buf_len != sizeof(state->request)) - FD_SET(state->sock, &r_fds); - - /* Add fd for writing */ - - if (state->write_buf_len) - FD_SET(state->sock, &w_fds); - - state = state->next; - } - - /* Call select */ - - selret = sys_select(maxfd + 1, &r_fds, &w_fds, NULL, &timeout); - - if (selret == 0) - continue; - - if ((selret == -1 && errno != EINTR) || selret == 0) { - - /* Select error, something is badly wrong */ - - perror("select"); - exit(1); - } - - /* Create a new connection if listen_sock readable */ - - if (selret > 0) { - - if (opt_dual_daemon) { - dual_select(&w_fds); - } - - if (FD_ISSET(listen_sock, &r_fds)) { - while (winbindd_num_clients() > WINBINDD_MAX_SIMULTANEOUS_CLIENTS - 1) { - DEBUG(5,("winbindd: Exceeding %d client connections, removing idle connection.\n", - WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); - if (!remove_idle_client()) { - DEBUG(0,("winbindd: Exceeding %d client connections, no idle connection found\n", - WINBINDD_MAX_SIMULTANEOUS_CLIENTS)); - break; - } - } - new_connection(listen_sock); - } - - /* Process activity on client connections */ - - for (state = winbindd_client_list(); state; - state = state->next) { - - /* Data available for reading */ - - if (FD_ISSET(state->sock, &r_fds)) { - - /* Read data */ - - winbind_client_read(state); - - /* - * If we have the start of a - * packet, then check the - * length field to make sure - * the client's not talking - * Mock Swedish. - */ - - if (state->read_buf_len >= sizeof(uint32) - && *(uint32 *) &state->request != sizeof(state->request)) { - DEBUG(0,("process_loop: Invalid request size from pid %d: %d bytes sent, should be %d\n", - state->request.pid, *(uint32 *) &state->request, sizeof(state->request))); - - remove_client(state); - break; - } - - /* A request packet might be - complete */ - - if (state->read_buf_len == - sizeof(state->request)) { - winbind_process_packet(state); - } - } - - /* Data available for writing */ - - if (FD_ISSET(state->sock, &w_fds)) - client_write(state); - } - } - -#if 0 - winbindd_check_cache_size(time(NULL)); -#endif - - /* Check signal handling things */ - - if (do_sigterm) - terminate(); - - if (do_sighup) { - - DEBUG(3, ("got SIGHUP\n")); - - /* Flush various caches */ - - flush_caches(); - reload_services_file(True); - do_sighup = False; - } - - if (do_sigusr2) { - print_winbindd_status(); - do_sigusr2 = False; - } - } -} - - -/* - these are split out from the main winbindd for use by the background daemon - */ -BOOL winbind_setup_common(void) -{ - load_interfaces(); - - if (!secrets_init()) { - - DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n")); - return False; - } - - namecache_enable(); /* Enable netbios namecache */ - - /* Check winbindd parameters are valid */ - - ZERO_STRUCT(server_state); - - if (!winbindd_param_init()) - return False; - - /* Winbind daemon initialisation */ - - if (!winbindd_idmap_init()) - return False; - - /* Unblock all signals we are interested in as they may have been - blocked by the parent process. */ - - BlockSignals(False, SIGINT); - BlockSignals(False, SIGQUIT); - BlockSignals(False, SIGTERM); - BlockSignals(False, SIGUSR1); - BlockSignals(False, SIGUSR2); - BlockSignals(False, SIGHUP); - - /* Setup signal handlers */ - - CatchSignal(SIGINT, termination_handler); /* Exit on these sigs */ - CatchSignal(SIGQUIT, termination_handler); - CatchSignal(SIGTERM, termination_handler); - - CatchSignal(SIGPIPE, SIG_IGN); /* Ignore sigpipe */ - - CatchSignal(SIGUSR2, sigusr2_handler); /* Debugging sigs */ - CatchSignal(SIGHUP, sighup_handler); - - return True; -} - - -/* Main function */ - -struct winbindd_state server_state; /* Server state information */ - - -static void usage(void) -{ - printf("Usage: winbindd [options]\n"); - printf("\t-F daemon in foreground mode\n"); - printf("\t-S log to stdout\n"); - printf("\t-i interactive mode\n"); - printf("\t-B dual daemon mode\n"); - printf("\t-n disable cacheing\n"); - printf("\t-d level set debug level\n"); - printf("\t-s configfile choose smb.conf location\n"); - printf("\t-h show this help message\n"); -} - - int main(int argc, char **argv) -{ - extern BOOL AllowDebugChange; - pstring logfile; - BOOL interactive = False; - BOOL Fork = True; - BOOL log_stdout = False; - int opt; - - /* glibc (?) likes to print "User defined signal 1" and exit if a - SIGUSR[12] is received before a handler is installed */ - - CatchSignal(SIGUSR1, SIG_IGN); - CatchSignal(SIGUSR2, SIG_IGN); - - fault_setup((void (*)(void *))fault_quit ); - - snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - - /* Initialise for running in non-root mode */ - - sec_init(); - - /* Set environment variable so we don't recursively call ourselves. - This may also be useful interactively. */ - - setenv(WINBINDD_DONT_ENV, "1", 1); - - /* Initialise samba/rpc client stuff */ - - while ((opt = getopt(argc, argv, "FSid:s:nhB")) != EOF) { - switch (opt) { - - case 'F': - Fork = False; - break; - case 'S': - log_stdout = True; - break; - /* Don't become a daemon */ - case 'i': - interactive = True; - log_stdout = True; - Fork = False; - break; - - /* dual daemon system */ - case 'B': - opt_dual_daemon = True; - break; - - /* disable cacheing */ - case 'n': - opt_nocache = True; - break; - - /* Run with specified debug level */ - case 'd': - DEBUGLEVEL = atoi(optarg); - AllowDebugChange = False; - break; - - /* Load a different smb.conf file */ - case 's': - pstrcpy(dyn_CONFIGFILE,optarg); - break; - - case 'h': - usage(); - exit(0); - - default: - printf("Unknown option %c\n", (char)opt); - exit(1); - } - } - - if (log_stdout && Fork) { - printf("Can't log to stdout (-S) unless daemon is in foreground +(-F) or interactive (-i)\n"); - usage(); - exit(1); - } - - snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); - setup_logging("winbindd", log_stdout?DEBUG_STDOUT:DEBUG_FILE); - reopen_logs(); - - DEBUG(1, ("winbindd version %s started.\n", VERSION ) ); - DEBUGADD( 1, ( "Copyright The Samba Team 2000-2001\n" ) ); - - if (!reload_services_file(False)) { - DEBUG(0, ("error opening config file\n")); - exit(1); - } - - /* Setup names. */ - - if (!init_names()) - exit(1); - - if (!interactive) { - become_daemon(Fork); - pidfile_create("winbindd"); - } - - -#if HAVE_SETPGID - /* - * If we're interactive we want to set our own process group for - * signal management. - */ - if (interactive) - setpgid( (pid_t)0, (pid_t)0); -#endif - - if (!winbind_setup_common()) { - return 1; - } - - if (opt_dual_daemon) { - do_dual_daemon(); - } - - /* Initialise messaging system */ - - if (!message_init()) { - DEBUG(0, ("unable to initialise messaging system\n")); - exit(1); - } - - register_msg_pool_usage(); - message_register(MSG_REQ_TALLOC_USAGE, return_all_talloc_info); - - /* Loop waiting for requests */ - - process_loop(); - - trustdom_cache_shutdown(); - uni_group_cache_shutdown(); - return 0; -} diff --git a/source4/nsswitch/winbindd.h b/source4/nsswitch/winbindd.h deleted file mode 100644 index 42ef209faf..0000000000 --- a/source4/nsswitch/winbindd.h +++ /dev/null @@ -1,230 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori 2003 - - 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 _WINBINDD_H -#define _WINBINDD_H - -#include "includes.h" -#include "nterr.h" - -#include "winbindd_nss.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Client state structure */ - -struct winbindd_cli_state { - struct winbindd_cli_state *prev, *next; /* Linked list pointers */ - int sock; /* Open socket from client */ - pid_t pid; /* pid of client */ - int read_buf_len, write_buf_len; /* Indexes in request/response */ - BOOL finished; /* Can delete from list */ - BOOL write_extra_data; /* Write extra_data field */ - time_t last_access; /* Time of last access (read or write) */ - struct winbindd_request request; /* Request from client */ - struct winbindd_response response; /* Respose to client */ - struct getent_state *getpwent_state; /* State for getpwent() */ - struct getent_state *getgrent_state; /* State for getgrent() */ -}; - -/* State between get{pw,gr}ent() calls */ - -struct getent_state { - struct getent_state *prev, *next; - void *sam_entries; - uint32 sam_entry_index, num_sam_entries; - BOOL got_sam_entries; - fstring domain_name; -}; - -/* Storage for cached getpwent() user entries */ - -struct getpwent_user { - fstring name; /* Account name */ - fstring gecos; /* User information */ - DOM_SID user_sid; /* NT user and primary group SIDs */ - DOM_SID group_sid; -}; - -/* Server state structure */ - -struct winbindd_state { - - /* User and group id pool */ - - uid_t uid_low, uid_high; /* Range of uids to allocate */ - gid_t gid_low, gid_high; /* Range of gids to allocate */ -}; - -extern struct winbindd_state server_state; /* Server information */ - -typedef struct { - char *acct_name; - char *full_name; - DOM_SID *user_sid; /* NT user and primary group SIDs */ - DOM_SID *group_sid; -} WINBIND_USERINFO; - -/* Structures to hold per domain information */ - -struct winbindd_domain { - fstring name; /* Domain name */ - fstring alt_name; /* alt Domain name (if any) */ - DOM_SID sid; /* SID for this domain */ - BOOL native_mode; /* is this a win2k domain in native mode ? */ - - /* Lookup methods for this domain (LDAP or RPC) */ - - struct winbindd_methods *methods; - - /* Private data for the backends (used for connection cache) */ - - void *private; - - /* Sequence number stuff */ - - time_t last_seq_check; - uint32 sequence_number; - - /* Linked list info */ - - struct winbindd_domain *prev, *next; -}; - -/* per-domain methods. This is how LDAP vs RPC is selected - */ -struct winbindd_methods { - /* does this backend provide a consistent view of the data? (ie. is the primary group - always correct) */ - BOOL consistent; - - /* get a list of users, returning a WINBIND_USERINFO for each one */ - NTSTATUS (*query_user_list)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - WINBIND_USERINFO **info); - - /* get a list of domain groups */ - NTSTATUS (*enum_dom_groups)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info); - - /* get a list of domain local groups */ - NTSTATUS (*enum_local_groups)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info); - - /* convert one user or group name to a sid */ - NTSTATUS (*name_to_sid)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *name, - DOM_SID *sid, - enum SID_NAME_USE *type); - - /* convert a sid to a user or group name */ - NTSTATUS (*sid_to_name)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - char **name, - enum SID_NAME_USE *type); - - /* lookup user info for a given SID */ - NTSTATUS (*query_user)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - WINBIND_USERINFO *user_info); - - /* lookup all groups that a user is a member of. The backend - can also choose to lookup by username or rid for this - function */ - NTSTATUS (*lookup_usergroups)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - uint32 *num_groups, DOM_SID ***user_gids); - - /* find all members of the group with the specified group_rid */ - NTSTATUS (*lookup_groupmem)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *group_sid, - uint32 *num_names, - DOM_SID ***sid_mem, char ***names, - uint32 **name_types); - - /* return the current global sequence number */ - NTSTATUS (*sequence_number)(struct winbindd_domain *domain, uint32 *seq); - - /* enumerate trusted domains */ - NTSTATUS (*trusted_domains)(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_domains, - char ***names, - char ***alt_names, - DOM_SID **dom_sids); - - /* find the domain sid */ - NTSTATUS (*domain_sid)(struct winbindd_domain *domain, - DOM_SID *sid); - - /* setup the list of alternate names for the domain, if any */ - NTSTATUS (*alternate_name)(struct winbindd_domain *domain); -}; - -/* Used to glue a policy handle and cli_state together */ - -typedef struct { - struct cli_state *cli; - POLICY_HND pol; -} CLI_POLICY_HND; - -/* Filled out by IDMAP backends */ -struct idmap_methods { - /* Called when backend is first loaded */ - BOOL (*init)(void); - - BOOL (*get_sid_from_uid)(uid_t uid, DOM_SID *sid); - BOOL (*get_sid_from_gid)(gid_t gid, DOM_SID *sid); - - BOOL (*get_uid_from_sid)(DOM_SID *sid, uid_t *uid); - BOOL (*get_gid_from_sid)(DOM_SID *sid, gid_t *gid); - - /* Called when backend is unloaded */ - BOOL (*close)(void); - /* Called to dump backend status */ - void (*status)(void); -}; - -#include "winbindd_proto.h" - -#include "rpc_parse.h" -#include "rpc_client.h" - -#define WINBINDD_ESTABLISH_LOOP 30 -#define WINBINDD_RESCAN_FREQ 300 - -#define DOM_SEQUENCE_NONE ((uint32)-1) - -#endif /* _WINBINDD_H */ diff --git a/source4/nsswitch/winbindd_ads.c b/source4/nsswitch/winbindd_ads.c deleted file mode 100644 index de3757aa44..0000000000 --- a/source4/nsswitch/winbindd_ads.c +++ /dev/null @@ -1,837 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind ADS backend functions - - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -#ifdef HAVE_ADS - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* the realm of our primary LDAP server */ -static char *primary_realm; - - -/* - return our ads connections structure for a domain. We keep the connection - open to make things faster -*/ -static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) -{ - ADS_STRUCT *ads; - ADS_STATUS status; - - if (domain->private) { - return (ADS_STRUCT *)domain->private; - } - - /* we don't want this to affect the users ccache */ - setenv("KRB5CCNAME", "MEMORY:winbind_ccache", 1); - - ads = ads_init(domain->alt_name, domain->name, NULL); - if (!ads) { - DEBUG(1,("ads_init for domain %s failed\n", domain->name)); - return NULL; - } - - /* the machine acct password might have change - fetch it every time */ - SAFE_FREE(ads->auth.password); - ads->auth.password = secrets_fetch_machine_password(); - - if (primary_realm) { - SAFE_FREE(ads->auth.realm); - ads->auth.realm = strdup(primary_realm); - } - - status = ads_connect(ads); - if (!ADS_ERR_OK(status) || !ads->config.realm) { - extern struct winbindd_methods msrpc_methods; - DEBUG(1,("ads_connect for domain %s failed: %s\n", - domain->name, ads_errstr(status))); - ads_destroy(&ads); - - /* if we get ECONNREFUSED then it might be a NT4 - server, fall back to MSRPC */ - if (status.error_type == ADS_ERROR_SYSTEM && - status.err.rc == ECONNREFUSED) { - DEBUG(1,("Trying MSRPC methods\n")); - domain->methods = &msrpc_methods; - } - return NULL; - } - - /* remember our primary realm for trusted domain support */ - if (!primary_realm) { - primary_realm = strdup(ads->config.realm); - } - - domain->private = (void *)ads; - return ads; -} - - -/* Query display info for a realm. This is the basic user list fn */ -static NTSTATUS query_user_list(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - WINBIND_USERINFO **info) -{ - ADS_STRUCT *ads = NULL; - const char *attrs[] = {"userPrincipalName", - "sAMAccountName", - "name", "objectSid", "primaryGroupID", - "sAMAccountType", NULL}; - int i, count; - ADS_STATUS rc; - void *res = NULL; - void *msg = NULL; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - - *num_entries = 0; - - DEBUG(3,("ads: query_user_list\n")); - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs); - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); - goto done; - } - - count = ads_count_replies(ads, res); - if (count == 0) { - DEBUG(1,("query_user_list: No users found\n")); - goto done; - } - - (*info) = talloc_zero(mem_ctx, count * sizeof(**info)); - if (!*info) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - i = 0; - - for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { - char *name, *gecos; - DOM_SID sid; - DOM_SID *sid2; - DOM_SID *group_sid; - uint32 group; - uint32 atype; - - if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype) || - ads_atype_map(atype) != SID_NAME_USER) { - DEBUG(1,("Not a user account? atype=0x%x\n", atype)); - continue; - } - - name = ads_pull_username(ads, mem_ctx, msg); - gecos = ads_pull_string(ads, mem_ctx, msg, "name"); - if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { - DEBUG(1,("No sid for %s !?\n", name)); - continue; - } - if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group)) { - DEBUG(1,("No primary group for %s !?\n", name)); - continue; - } - - sid2 = talloc(mem_ctx, sizeof(*sid2)); - if (!sid2) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - sid_copy(sid2, &sid); - - group_sid = rid_to_talloced_sid(domain, mem_ctx, group); - - (*info)[i].acct_name = name; - (*info)[i].full_name = gecos; - (*info)[i].user_sid = sid2; - (*info)[i].group_sid = group_sid; - i++; - } - - (*num_entries) = i; - status = NT_STATUS_OK; - - DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries))); - -done: - if (res) ads_msgfree(ads, res); - - return status; -} - -/* list all domain groups */ -static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - ADS_STRUCT *ads = NULL; - const char *attrs[] = {"userPrincipalName", "sAMAccountName", - "name", "objectSid", - "sAMAccountType", NULL}; - int i, count; - ADS_STATUS rc; - void *res = NULL; - void *msg = NULL; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - uint32 group_flags; - - *num_entries = 0; - - DEBUG(3,("ads: enum_dom_groups\n")); - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - rc = ads_search_retry(ads, &res, "(objectCategory=group)", attrs); - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc))); - goto done; - } - - count = ads_count_replies(ads, res); - if (count == 0) { - DEBUG(1,("enum_dom_groups: No groups found\n")); - goto done; - } - - (*info) = talloc_zero(mem_ctx, count * sizeof(**info)); - if (!*info) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - i = 0; - - group_flags = ATYPE_GLOBAL_GROUP; - if ( domain->native_mode ) - group_flags |= ATYPE_LOCAL_GROUP; - - for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { - char *name, *gecos; - DOM_SID sid; - uint32 rid; - uint32 account_type; - - if (!ads_pull_uint32(ads, msg, "sAMAccountType", &account_type) || !(account_type & group_flags) ) - continue; - - name = ads_pull_username(ads, mem_ctx, msg); - gecos = ads_pull_string(ads, mem_ctx, msg, "name"); - if (!ads_pull_sid(ads, msg, "objectSid", &sid)) { - DEBUG(1,("No sid for %s !?\n", name)); - continue; - } - - if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) { - DEBUG(1,("No rid for %s !?\n", name)); - continue; - } - - fstrcpy((*info)[i].acct_name, name); - fstrcpy((*info)[i].acct_desc, gecos); - (*info)[i].rid = rid; - i++; - } - - (*num_entries) = i; - - status = NT_STATUS_OK; - - DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries))); - -done: - if (res) ads_msgfree(ads, res); - - return status; -} - -/* list all domain local groups */ -static NTSTATUS enum_local_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - /* - * This is a stub function only as we returned the domain - * ocal groups in enum_dom_groups() if the domain->native field - * was true. This is a simple performance optimization when - * using LDAP. - * - * if we ever need to enumerate domain local groups separately, - * then this the optimization in enum_dom_groups() will need - * to be split out - */ - *num_entries = 0; - - return NT_STATUS_OK; -} - -/* convert a single name to a sid in a domain */ -static NTSTATUS name_to_sid(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *name, - DOM_SID *sid, - enum SID_NAME_USE *type) -{ - ADS_STRUCT *ads; - - DEBUG(3,("ads: name_to_sid\n")); - - ads = ads_cached_connection(domain); - if (!ads) - return NT_STATUS_UNSUCCESSFUL; - - return ads_name_to_sid(ads, name, sid, type); -} - -/* convert a sid to a user or group name */ -static NTSTATUS sid_to_name(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - char **name, - enum SID_NAME_USE *type) -{ - ADS_STRUCT *ads = NULL; - DEBUG(3,("ads: sid_to_name\n")); - ads = ads_cached_connection(domain); - if (!ads) - return NT_STATUS_UNSUCCESSFUL; - - return ads_sid_to_name(ads, mem_ctx, sid, name, type); -} - - -/* convert a DN to a name, SID and name type - this might become a major speed bottleneck if groups have - lots of users, in which case we could cache the results -*/ -static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, - const char *dn, - char **name, uint32 *name_type, DOM_SID *sid) -{ - char *exp; - void *res = NULL; - const char *attrs[] = {"userPrincipalName", "sAMAccountName", - "objectSid", "sAMAccountType", NULL}; - ADS_STATUS rc; - uint32 atype; - char *escaped_dn = escape_ldap_string_alloc(dn); - - if (!escaped_dn) { - return False; - } - - asprintf(&exp, "(distinguishedName=%s)", dn); - rc = ads_search_retry(ads, &res, exp, attrs); - SAFE_FREE(exp); - SAFE_FREE(escaped_dn); - - if (!ADS_ERR_OK(rc)) { - goto failed; - } - - (*name) = ads_pull_username(ads, mem_ctx, res); - - if (!ads_pull_uint32(ads, res, "sAMAccountType", &atype)) { - goto failed; - } - (*name_type) = ads_atype_map(atype); - - if (!ads_pull_sid(ads, res, "objectSid", sid)) { - goto failed; - } - - if (res) ads_msgfree(ads, res); - return True; - -failed: - if (res) ads_msgfree(ads, res); - return False; -} - -/* Lookup user information from a rid */ -static NTSTATUS query_user(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - WINBIND_USERINFO *info) -{ - ADS_STRUCT *ads = NULL; - const char *attrs[] = {"userPrincipalName", - "sAMAccountName", - "name", - "primaryGroupID", NULL}; - ADS_STATUS rc; - int count; - void *msg = NULL; - char *exp; - char *sidstr; - uint32 group_rid; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - DOM_SID *sid2; - fstring sid_string; - - DEBUG(3,("ads: query_user\n")); - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - sidstr = sid_binstring(sid); - asprintf(&exp, "(objectSid=%s)", sidstr); - rc = ads_search_retry(ads, &msg, exp, attrs); - free(exp); - free(sidstr); - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("query_user(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); - goto done; - } - - count = ads_count_replies(ads, msg); - if (count != 1) { - DEBUG(1,("query_user(sid=%s): Not found\n", sid_to_string(sid_string, sid))); - goto done; - } - - info->acct_name = ads_pull_username(ads, mem_ctx, msg); - info->full_name = ads_pull_string(ads, mem_ctx, msg, "name"); - - if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) { - DEBUG(1,("No primary group for %s !?\n", sid_to_string(sid_string, sid))); - goto done; - } - - sid2 = talloc(mem_ctx, sizeof(*sid2)); - if (!sid2) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - sid_copy(sid2, sid); - - info->user_sid = sid2; - - info->group_sid = rid_to_talloced_sid(domain, mem_ctx, group_rid); - - status = NT_STATUS_OK; - - DEBUG(3,("ads query_user gave %s\n", info->acct_name)); -done: - if (msg) ads_msgfree(ads, msg); - - return status; -} - -/* Lookup groups a user is a member of - alternate method, for when - tokenGroups are not available. */ -static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *user_dn, - DOM_SID *primary_group, - uint32 *num_groups, DOM_SID ***user_gids) -{ - ADS_STATUS rc; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - int count; - void *res = NULL; - void *msg = NULL; - char *exp; - ADS_STRUCT *ads; - const char *group_attrs[] = {"objectSid", NULL}; - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - /* buggy server, no tokenGroups. Instead lookup what groups this user - is a member of by DN search on member*/ - if (asprintf(&exp, "(&(member=%s)(objectClass=group))", user_dn) == -1) { - DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn)); - return NT_STATUS_NO_MEMORY; - } - - rc = ads_search_retry(ads, &res, exp, group_attrs); - free(exp); - - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc))); - return ads_ntstatus(rc); - } - - count = ads_count_replies(ads, res); - if (count == 0) { - DEBUG(5,("lookup_usergroups: No supp groups found\n")); - - status = ads_ntstatus(rc); - goto done; - } - - (*user_gids) = talloc_zero(mem_ctx, sizeof(**user_gids) * (count + 1)); - (*user_gids)[0] = primary_group; - - *num_groups = 1; - - for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { - DOM_SID group_sid; - - if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) { - DEBUG(1,("No sid for this group ?!?\n")); - continue; - } - - if (sid_equal(&group_sid, primary_group)) continue; - - (*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids)); - if (!(*user_gids)[*num_groups]) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - sid_copy((*user_gids)[*num_groups], &group_sid); - - (*num_groups)++; - - } - - status = NT_STATUS_OK; - - DEBUG(3,("ads lookup_usergroups (alt) for dn=%s\n", user_dn)); -done: - if (res) ads_msgfree(ads, res); - if (msg) ads_msgfree(ads, msg); - - return status; -} - -/* Lookup groups a user is a member of. */ -static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - uint32 *num_groups, DOM_SID ***user_gids) -{ - ADS_STRUCT *ads = NULL; - const char *attrs[] = {"distinguishedName", NULL}; - const char *attrs2[] = {"tokenGroups", "primaryGroupID", NULL}; - ADS_STATUS rc; - int count; - void *msg = NULL; - char *exp; - char *user_dn; - DOM_SID *sids; - int i; - DOM_SID *primary_group; - uint32 primary_group_rid; - char *sidstr; - fstring sid_string; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - - DEBUG(3,("ads: lookup_usergroups\n")); - *num_groups = 0; - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - if (!(sidstr = sid_binstring(sid))) { - DEBUG(1,("lookup_usergroups(sid=%s) sid_binstring returned NULL\n", sid_to_string(sid_string, sid))); - status = NT_STATUS_NO_MEMORY; - goto done; - } - if (asprintf(&exp, "(objectSid=%s)", sidstr) == -1) { - free(sidstr); - DEBUG(1,("lookup_usergroups(sid=%s) asprintf failed!\n", sid_to_string(sid_string, sid))); - status = NT_STATUS_NO_MEMORY; - goto done; - } - - rc = ads_search_retry(ads, &msg, exp, attrs); - free(exp); - free(sidstr); - - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("lookup_usergroups(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); - goto done; - } - - user_dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName"); - if (!user_dn) { - DEBUG(1,("lookup_usergroups(sid=%s) ads_search did not return a a distinguishedName!\n", sid_to_string(sid_string, sid))); - if (msg) ads_msgfree(ads, msg); - goto done; - } - - if (msg) ads_msgfree(ads, msg); - - rc = ads_search_retry_dn(ads, &msg, user_dn, attrs2); - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); - goto done; - } - - if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) { - DEBUG(1,("%s: No primary group for sid=%s !?\n", domain->name, sid_to_string(sid_string, sid))); - goto done; - } - - primary_group = rid_to_talloced_sid(domain, mem_ctx, primary_group_rid); - - count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids); - - if (msg) ads_msgfree(ads, msg); - - /* there must always be at least one group in the token, - unless we are talking to a buggy Win2k server */ - if (count == 0) { - return lookup_usergroups_alt(domain, mem_ctx, user_dn, - primary_group, - num_groups, user_gids); - } - - (*user_gids) = talloc_zero(mem_ctx, sizeof(**user_gids) * (count + 1)); - (*user_gids)[0] = primary_group; - - *num_groups = 1; - - for (i=0;i<count;i++) { - if (sid_equal(&sids[i], primary_group)) continue; - - (*user_gids)[*num_groups] = talloc(mem_ctx, sizeof(***user_gids)); - if (!(*user_gids)[*num_groups]) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - - sid_copy((*user_gids)[*num_groups], &sids[i]); - (*num_groups)++; - } - - status = NT_STATUS_OK; - DEBUG(3,("ads lookup_usergroups for sid=%s\n", sid_to_string(sid_string, sid))); -done: - return status; -} - -/* - find the members of a group, given a group rid and domain - */ -static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *group_sid, uint32 *num_names, - DOM_SID ***sid_mem, char ***names, - uint32 **name_types) -{ - ADS_STATUS rc; - int count; - void *res=NULL; - ADS_STRUCT *ads = NULL; - char *exp; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - char *sidstr; - const char *attrs[] = {"member", NULL}; - char **members; - int i, num_members; - fstring sid_string; - - *num_names = 0; - - ads = ads_cached_connection(domain); - if (!ads) goto done; - - sidstr = sid_binstring(group_sid); - - /* search for all members of the group */ - asprintf(&exp, "(objectSid=%s)",sidstr); - rc = ads_search_retry(ads, &res, exp, attrs); - free(exp); - free(sidstr); - - if (!ADS_ERR_OK(rc)) { - DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); - goto done; - } - - count = ads_count_replies(ads, res); - if (count == 0) { - status = NT_STATUS_OK; - goto done; - } - - members = ads_pull_strings(ads, mem_ctx, res, "member"); - if (!members) { - /* no members? ok ... */ - status = NT_STATUS_OK; - goto done; - } - - /* now we need to turn a list of members into rids, names and name types - the problem is that the members are in the form of distinguised names - */ - for (i=0;members[i];i++) /* noop */ ; - num_members = i; - - (*sid_mem) = talloc_zero(mem_ctx, sizeof(**sid_mem) * num_members); - (*name_types) = talloc_zero(mem_ctx, sizeof(**name_types) * num_members); - (*names) = talloc_zero(mem_ctx, sizeof(**names) * num_members); - - for (i=0;i<num_members;i++) { - uint32 name_type; - char *name; - DOM_SID sid; - - if (dn_lookup(ads, mem_ctx, members[i], &name, &name_type, &sid)) { - (*names)[*num_names] = name; - (*name_types)[*num_names] = name_type; - (*sid_mem)[*num_names] = talloc(mem_ctx, sizeof(***sid_mem)); - if (!(*sid_mem)[*num_names]) { - status = NT_STATUS_NO_MEMORY; - goto done; - } - sid_copy((*sid_mem)[*num_names], &sid); - (*num_names)++; - } - } - - status = NT_STATUS_OK; - DEBUG(3,("ads lookup_groupmem for sid=%s\n", sid_to_string(sid_string, group_sid))); -done: - if (res) ads_msgfree(ads, res); - - return status; -} - - -/* find the sequence number for a domain */ -static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) -{ - ADS_STRUCT *ads = NULL; - ADS_STATUS rc; - - *seq = DOM_SEQUENCE_NONE; - - ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; - - rc = ads_USN(ads, seq); - if (!ADS_ERR_OK(rc)) { - /* its a dead connection */ - ads_destroy(&ads); - domain->private = NULL; - } - return ads_ntstatus(rc); -} - -/* get a list of trusted domains */ -static NTSTATUS trusted_domains(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_domains, - char ***names, - char ***alt_names, - DOM_SID **dom_sids) -{ - ADS_STRUCT *ads; - ADS_STATUS rc; - - *num_domains = 0; - *names = NULL; - - ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; - - rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, alt_names, dom_sids); - - return ads_ntstatus(rc); -} - -/* find the domain sid for a domain */ -static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) -{ - ADS_STRUCT *ads; - ADS_STATUS rc; - - ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; - - rc = ads_domain_sid(ads, sid); - - if (!ADS_ERR_OK(rc)) { - /* its a dead connection */ - ads_destroy(&ads); - domain->private = NULL; - } - - return ads_ntstatus(rc); -} - - -/* find alternate names list for the domain - for ADS this is the - netbios name */ -static NTSTATUS alternate_name(struct winbindd_domain *domain) -{ - ADS_STRUCT *ads; - ADS_STATUS rc; - TALLOC_CTX *ctx; - char *workgroup; - - ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; - - if (!(ctx = talloc_init("alternate_name"))) { - return NT_STATUS_NO_MEMORY; - } - - rc = ads_workgroup_name(ads, ctx, &workgroup); - - if (ADS_ERR_OK(rc)) { - fstrcpy(domain->name, workgroup); - fstrcpy(domain->alt_name, ads->config.realm); - strupper(domain->alt_name); - strupper(domain->name); - } - - talloc_destroy(ctx); - - return ads_ntstatus(rc); -} - -/* the ADS backend methods are exposed via this structure */ -struct winbindd_methods ads_methods = { - True, - query_user_list, - enum_dom_groups, - enum_local_groups, - name_to_sid, - sid_to_name, - query_user, - lookup_usergroups, - lookup_groupmem, - sequence_number, - trusted_domains, - domain_sid, - alternate_name -}; - -#endif diff --git a/source4/nsswitch/winbindd_cache.c b/source4/nsswitch/winbindd_cache.c deleted file mode 100644 index 5fb59e7467..0000000000 --- a/source4/nsswitch/winbindd_cache.c +++ /dev/null @@ -1,1016 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind cache backend functions - - Copyright (C) Andrew Tridgell 2001 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -struct winbind_cache { - struct winbindd_methods *backend; - TDB_CONTEXT *tdb; -}; - -struct cache_entry { - NTSTATUS status; - uint32 sequence_number; - uint8 *data; - uint32 len, ofs; -}; - -#define WINBINDD_MAX_CACHE_SIZE (50*1024*1024) - -static struct winbind_cache *wcache; - -/* flush the cache */ -void wcache_flush_cache(void) -{ - extern BOOL opt_nocache; - - if (!wcache) return; - if (wcache->tdb) { - tdb_close(wcache->tdb); - wcache->tdb = NULL; - } - if (opt_nocache) return; - - wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000, - TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600); - - if (!wcache->tdb) { - DEBUG(0,("Failed to open winbindd_cache.tdb!\n")); - } -} - -void winbindd_check_cache_size(time_t t) -{ - static time_t last_check_time; - struct stat st; - - if (last_check_time == (time_t)0) - last_check_time = t; - - if (t - last_check_time < 60 && t - last_check_time > 0) - return; - - if (wcache == NULL || wcache->tdb == NULL) { - DEBUG(0, ("Unable to check size of tdb cache - cache not open !\n")); - return; - } - - if (fstat(wcache->tdb->fd, &st) == -1) { - DEBUG(0, ("Unable to check size of tdb cache %s!\n", strerror(errno) )); - return; - } - - if (st.st_size > WINBINDD_MAX_CACHE_SIZE) { - DEBUG(10,("flushing cache due to size (%lu) > (%lu)\n", - (unsigned long)st.st_size, - (unsigned long)WINBINDD_MAX_CACHE_SIZE)); - wcache_flush_cache(); - } -} - -/* get the winbind_cache structure */ -static struct winbind_cache *get_cache(struct winbindd_domain *domain) -{ - extern struct winbindd_methods msrpc_methods; - struct winbind_cache *ret = wcache; - - if (ret) return ret; - - ret = smb_xmalloc(sizeof(*ret)); - ZERO_STRUCTP(ret); - switch (lp_security()) { -#ifdef HAVE_ADS - case SEC_ADS: { - extern struct winbindd_methods ads_methods; - ret->backend = &ads_methods; - break; - } -#endif - default: - ret->backend = &msrpc_methods; - } - - wcache = ret; - wcache_flush_cache(); - - return ret; -} - -/* - free a centry structure -*/ -static void centry_free(struct cache_entry *centry) -{ - if (!centry) return; - SAFE_FREE(centry->data); - free(centry); -} - - -/* - pull a uint32 from a cache entry -*/ -static uint32 centry_uint32(struct cache_entry *centry) -{ - uint32 ret; - if (centry->len - centry->ofs < 4) { - DEBUG(0,("centry corruption? needed 4 bytes, have %d\n", - centry->len - centry->ofs)); - smb_panic("centry_uint32"); - } - ret = IVAL(centry->data, centry->ofs); - centry->ofs += 4; - return ret; -} - -/* - pull a uint8 from a cache entry -*/ -static uint8 centry_uint8(struct cache_entry *centry) -{ - uint8 ret; - if (centry->len - centry->ofs < 1) { - DEBUG(0,("centry corruption? needed 1 bytes, have %d\n", - centry->len - centry->ofs)); - smb_panic("centry_uint32"); - } - ret = CVAL(centry->data, centry->ofs); - centry->ofs += 1; - return ret; -} - -/* pull a string from a cache entry, using the supplied - talloc context -*/ -static char *centry_string(struct cache_entry *centry, TALLOC_CTX *mem_ctx) -{ - uint32 len; - char *ret; - - len = centry_uint8(centry); - - if (len == 0xFF) { - /* a deliberate NULL string */ - return NULL; - } - - if (centry->len - centry->ofs < len) { - DEBUG(0,("centry corruption? needed %d bytes, have %d\n", - len, centry->len - centry->ofs)); - smb_panic("centry_string"); - } - - ret = talloc(mem_ctx, len+1); - if (!ret) { - smb_panic("centry_string out of memory\n"); - } - memcpy(ret,centry->data + centry->ofs, len); - ret[len] = 0; - centry->ofs += len; - return ret; -} - -/* pull a string from a cache entry, using the supplied - talloc context -*/ -static DOM_SID *centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx) -{ - DOM_SID *sid; - char *sid_string; - sid = talloc(mem_ctx, sizeof(*sid)); - if (!sid) return NULL; - - sid_string = centry_string(centry, mem_ctx); - if (!string_to_sid(sid, sid_string)) { - return NULL; - } - return sid; -} - -/* the server is considered down if it can't give us a sequence number */ -static BOOL wcache_server_down(struct winbindd_domain *domain) -{ - if (!wcache->tdb) return False; - return (domain->sequence_number == DOM_SEQUENCE_NONE); -} - - -/* - refresh the domain sequence number. If force is True - then always refresh it, no matter how recently we fetched it -*/ -static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force) -{ - NTSTATUS status; - unsigned time_diff; - unsigned cache_time = lp_winbind_cache_time(); - - /* trying to reconnect is expensive, don't do it too often */ - if (domain->sequence_number == DOM_SEQUENCE_NONE) { - cache_time *= 8; - } - - time_diff = time(NULL) - domain->last_seq_check; - - /* see if we have to refetch the domain sequence number */ - if (!force && (time_diff < cache_time)) { - return; - } - - status = wcache->backend->sequence_number(domain, &domain->sequence_number); - - if (!NT_STATUS_IS_OK(status)) { - domain->sequence_number = DOM_SEQUENCE_NONE; - } - - domain->last_seq_check = time(NULL); -} - -/* - decide if a cache entry has expired -*/ -static BOOL centry_expired(struct winbindd_domain *domain, struct cache_entry *centry) -{ - /* if the server is OK and our cache entry came from when it was down then - the entry is invalid */ - if (domain->sequence_number != DOM_SEQUENCE_NONE && - centry->sequence_number == DOM_SEQUENCE_NONE) { - return True; - } - - /* if the server is down or the cache entry is not older than the - current sequence number then it is OK */ - if (wcache_server_down(domain) || - centry->sequence_number == domain->sequence_number) { - return False; - } - - /* it's expired */ - return True; -} - -/* - fetch an entry from the cache, with a varargs key. auto-fetch the sequence - number and return status -*/ -static struct cache_entry *wcache_fetch(struct winbind_cache *cache, - struct winbindd_domain *domain, - const char *format, ...) PRINTF_ATTRIBUTE(3,4); -static struct cache_entry *wcache_fetch(struct winbind_cache *cache, - struct winbindd_domain *domain, - const char *format, ...) -{ - va_list ap; - char *kstr; - TDB_DATA data; - struct cache_entry *centry; - TDB_DATA key; - - refresh_sequence_number(domain, False); - - va_start(ap, format); - smb_xvasprintf(&kstr, format, ap); - va_end(ap); - - key.dptr = kstr; - key.dsize = strlen(kstr); - data = tdb_fetch(wcache->tdb, key); - free(kstr); - if (!data.dptr) { - /* a cache miss */ - return NULL; - } - - centry = smb_xmalloc(sizeof(*centry)); - centry->data = data.dptr; - centry->len = data.dsize; - centry->ofs = 0; - - if (centry->len < 8) { - /* huh? corrupt cache? */ - centry_free(centry); - return NULL; - } - - centry->status = NT_STATUS(centry_uint32(centry)); - centry->sequence_number = centry_uint32(centry); - - if (centry_expired(domain, centry)) { - extern BOOL opt_dual_daemon; - - if (opt_dual_daemon) { - extern BOOL background_process; - background_process = True; - } else { - centry_free(centry); - return NULL; - } - } - - return centry; -} - -/* - make sure we have at least len bytes available in a centry -*/ -static void centry_expand(struct cache_entry *centry, uint32 len) -{ - uint8 *p; - if (centry->len - centry->ofs >= len) return; - centry->len *= 2; - p = realloc(centry->data, centry->len); - if (!p) { - DEBUG(0,("out of memory: needed %d bytes in centry_expand\n", centry->len)); - smb_panic("out of memory in centry_expand"); - } - centry->data = p; -} - -/* - push a uint32 into a centry -*/ -static void centry_put_uint32(struct cache_entry *centry, uint32 v) -{ - centry_expand(centry, 4); - SIVAL(centry->data, centry->ofs, v); - centry->ofs += 4; -} - -/* - push a uint8 into a centry -*/ -static void centry_put_uint8(struct cache_entry *centry, uint8 v) -{ - centry_expand(centry, 1); - SCVAL(centry->data, centry->ofs, v); - centry->ofs += 1; -} - -/* - push a string into a centry - */ -static void centry_put_string(struct cache_entry *centry, const char *s) -{ - int len; - - if (!s) { - /* null strings are marked as len 0xFFFF */ - centry_put_uint8(centry, 0xFF); - return; - } - - len = strlen(s); - /* can't handle more than 254 char strings. Truncating is probably best */ - if (len > 254) len = 254; - centry_put_uint8(centry, len); - centry_expand(centry, len); - memcpy(centry->data + centry->ofs, s, len); - centry->ofs += len; -} - -static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid) -{ - int len; - fstring sid_string; - centry_put_string(centry, sid_to_string(sid_string, sid)); -} - -/* - start a centry for output. When finished, call centry_end() -*/ -struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status) -{ - struct cache_entry *centry; - - if (!wcache->tdb) return NULL; - - centry = smb_xmalloc(sizeof(*centry)); - - centry->len = 8192; /* reasonable default */ - centry->data = smb_xmalloc(centry->len); - centry->ofs = 0; - centry->sequence_number = domain->sequence_number; - centry_put_uint32(centry, NT_STATUS_V(status)); - centry_put_uint32(centry, centry->sequence_number); - return centry; -} - -/* - finish a centry and write it to the tdb -*/ -static void centry_end(struct cache_entry *centry, const char *format, ...) PRINTF_ATTRIBUTE(2,3); -static void centry_end(struct cache_entry *centry, const char *format, ...) -{ - va_list ap; - char *kstr; - TDB_DATA key, data; - - va_start(ap, format); - smb_xvasprintf(&kstr, format, ap); - va_end(ap); - - key.dptr = kstr; - key.dsize = strlen(kstr); - data.dptr = centry->data; - data.dsize = centry->ofs; - - tdb_store(wcache->tdb, key, data, TDB_REPLACE); - free(kstr); -} - -static void wcache_save_name_to_sid(struct winbindd_domain *domain, - NTSTATUS status, - const char *name, DOM_SID *sid, - enum SID_NAME_USE type) -{ - struct cache_entry *centry; - uint32 len; - fstring uname; - fstring sid_string; - - centry = centry_start(domain, status); - if (!centry) return; - centry_put_sid(centry, sid); - fstrcpy(uname, name); - strupper(uname); - centry_end(centry, "NS/%s", sid_to_string(sid_string, sid)); - centry_free(centry); -} - -static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS status, - DOM_SID *sid, const char *name, enum SID_NAME_USE type) -{ - struct cache_entry *centry; - fstring sid_string; - - centry = centry_start(domain, status); - if (!centry) return; - if (NT_STATUS_IS_OK(status)) { - centry_put_uint32(centry, type); - centry_put_string(centry, name); - } - centry_end(centry, "SN/%s", sid_to_string(sid_string, sid)); - centry_free(centry); -} - - -static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WINBIND_USERINFO *info) -{ - struct cache_entry *centry; - fstring sid_string; - - centry = centry_start(domain, status); - if (!centry) return; - centry_put_string(centry, info->acct_name); - centry_put_string(centry, info->full_name); - centry_put_sid(centry, info->user_sid); - centry_put_sid(centry, info->group_sid); - centry_end(centry, "U/%s", sid_to_string(sid_string, info->user_sid)); - centry_free(centry); -} - - -/* Query display info. This is the basic user list fn */ -static NTSTATUS query_user_list(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - WINBIND_USERINFO **info) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - unsigned int i; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "UL/%s", domain->name); - if (!centry) goto do_query; - - *num_entries = centry_uint32(centry); - - if (*num_entries == 0) goto do_cached; - - (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries)); - if (! (*info)) smb_panic("query_user_list out of memory"); - for (i=0; i<(*num_entries); i++) { - (*info)[i].acct_name = centry_string(centry, mem_ctx); - (*info)[i].full_name = centry_string(centry, mem_ctx); - (*info)[i].user_sid = centry_sid(centry, mem_ctx); - (*info)[i].group_sid = centry_sid(centry, mem_ctx); - } - -do_cached: - status = centry->status; - centry_free(centry); - return status; - -do_query: - *num_entries = 0; - *info = NULL; - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - - status = cache->backend->query_user_list(domain, mem_ctx, num_entries, info); - - /* and save it */ - refresh_sequence_number(domain, True); - centry = centry_start(domain, status); - if (!centry) goto skip_save; - centry_put_uint32(centry, *num_entries); - for (i=0; i<(*num_entries); i++) { - centry_put_string(centry, (*info)[i].acct_name); - centry_put_string(centry, (*info)[i].full_name); - centry_put_sid(centry, (*info)[i].user_sid); - centry_put_sid(centry, (*info)[i].group_sid); - if (cache->backend->consistent) { - /* when the backend is consistent we can pre-prime some mappings */ - wcache_save_name_to_sid(domain, NT_STATUS_OK, - (*info)[i].acct_name, - (*info)[i].user_sid, - SID_NAME_USER); - wcache_save_sid_to_name(domain, NT_STATUS_OK, - (*info)[i].user_sid, - (*info)[i].acct_name, - SID_NAME_USER); - wcache_save_user(domain, NT_STATUS_OK, &(*info)[i]); - } - } - centry_end(centry, "UL/%s", domain->name); - centry_free(centry); - -skip_save: - return status; -} - -/* list all domain groups */ -static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - unsigned int i; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "GL/%s/domain", domain->name); - if (!centry) goto do_query; - - *num_entries = centry_uint32(centry); - - if (*num_entries == 0) goto do_cached; - - (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries)); - if (! (*info)) smb_panic("enum_dom_groups out of memory"); - for (i=0; i<(*num_entries); i++) { - fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx)); - fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx)); - (*info)[i].rid = centry_uint32(centry); - } - -do_cached: - status = centry->status; - centry_free(centry); - return status; - -do_query: - *num_entries = 0; - *info = NULL; - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - - status = cache->backend->enum_dom_groups(domain, mem_ctx, num_entries, info); - - /* and save it */ - refresh_sequence_number(domain, True); - centry = centry_start(domain, status); - if (!centry) goto skip_save; - centry_put_uint32(centry, *num_entries); - for (i=0; i<(*num_entries); i++) { - centry_put_string(centry, (*info)[i].acct_name); - centry_put_string(centry, (*info)[i].acct_desc); - centry_put_uint32(centry, (*info)[i].rid); - } - centry_end(centry, "GL/%s/domain", domain->name); - centry_free(centry); - -skip_save: - return status; -} - -/* list all domain groups */ -static NTSTATUS enum_local_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - unsigned int i; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "GL/%s/local", domain->name); - if (!centry) goto do_query; - - *num_entries = centry_uint32(centry); - - if (*num_entries == 0) goto do_cached; - - (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries)); - if (! (*info)) smb_panic("enum_dom_groups out of memory"); - for (i=0; i<(*num_entries); i++) { - fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx)); - fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx)); - (*info)[i].rid = centry_uint32(centry); - } - -do_cached: - - /* If we are returning cached data and the domain controller - is down then we don't know whether the data is up to date - or not. Return NT_STATUS_MORE_PROCESSING_REQUIRED to - indicate this. */ - - if (wcache_server_down(domain)) { - DEBUG(10, ("query_user_list: returning cached user list and server was down\n")); - status = NT_STATUS_MORE_PROCESSING_REQUIRED; - } else - status = centry->status; - - centry_free(centry); - return status; - -do_query: - *num_entries = 0; - *info = NULL; - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - - status = cache->backend->enum_local_groups(domain, mem_ctx, num_entries, info); - - /* and save it */ - refresh_sequence_number(domain, True); - centry = centry_start(domain, status); - if (!centry) goto skip_save; - centry_put_uint32(centry, *num_entries); - for (i=0; i<(*num_entries); i++) { - centry_put_string(centry, (*info)[i].acct_name); - centry_put_string(centry, (*info)[i].acct_desc); - centry_put_uint32(centry, (*info)[i].rid); - } - centry_end(centry, "GL/%s/local", domain->name); - centry_free(centry); - -skip_save: - return status; -} - -/* convert a single name to a sid in a domain */ -static NTSTATUS name_to_sid(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *name, - DOM_SID *sid, - enum SID_NAME_USE *type) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - fstring uname; - DOM_SID *sid2; - - if (!cache->tdb) goto do_query; - - fstrcpy(uname, name); - strupper(uname); - centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname); - if (!centry) goto do_query; - *type = centry_uint32(centry); - sid2 = centry_sid(centry, mem_ctx); - if (!sid2) { - ZERO_STRUCTP(sid); - } else { - sid_copy(sid, sid2); - } - - status = centry->status; - centry_free(centry); - return status; - -do_query: - ZERO_STRUCTP(sid); - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->name_to_sid(domain, mem_ctx, name, sid, type); - - /* and save it */ - wcache_save_name_to_sid(domain, status, name, sid, *type); - - /* We can't save the sid to name mapping as we don't know the - correct case of the name without looking it up */ - - return status; -} - -/* convert a sid to a user or group name. The sid is guaranteed to be in the domain - given */ -static NTSTATUS sid_to_name(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - char **name, - enum SID_NAME_USE *type) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - fstring sid_string; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "SN/%s", sid_to_string(sid_string, sid)); - if (!centry) goto do_query; - if (NT_STATUS_IS_OK(centry->status)) { - *type = centry_uint32(centry); - *name = centry_string(centry, mem_ctx); - } - status = centry->status; - centry_free(centry); - return status; - -do_query: - *name = NULL; - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->sid_to_name(domain, mem_ctx, sid, name, type); - - /* and save it */ - refresh_sequence_number(domain, True); - wcache_save_sid_to_name(domain, status, sid, *name, *type); - wcache_save_name_to_sid(domain, status, *name, sid, *type); - - return status; -} - - -/* Lookup user information from a rid */ -static NTSTATUS query_user(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - WINBIND_USERINFO *info) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - fstring sid_string; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "U/%s", sid_to_string(sid_string, user_sid)); - if (!centry) goto do_query; - - info->acct_name = centry_string(centry, mem_ctx); - info->full_name = centry_string(centry, mem_ctx); - info->user_sid = centry_sid(centry, mem_ctx); - info->group_sid = centry_sid(centry, mem_ctx); - status = centry->status; - centry_free(centry); - return status; - -do_query: - ZERO_STRUCTP(info); - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - - status = cache->backend->query_user(domain, mem_ctx, user_sid, info); - - /* and save it */ - refresh_sequence_number(domain, True); - wcache_save_user(domain, status, info); - - return status; -} - - -/* Lookup groups a user is a member of. */ -static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - uint32 *num_groups, DOM_SID ***user_gids) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - unsigned int i; - fstring sid_string; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "UG/%s", sid_to_string(sid_string, user_sid)); - if (!centry) goto do_query; - - *num_groups = centry_uint32(centry); - - if (*num_groups == 0) goto do_cached; - - (*user_gids) = talloc(mem_ctx, sizeof(**user_gids) * (*num_groups)); - if (! (*user_gids)) smb_panic("lookup_usergroups out of memory"); - for (i=0; i<(*num_groups); i++) { - (*user_gids)[i] = centry_sid(centry, mem_ctx); - } - -do_cached: - status = centry->status; - centry_free(centry); - return status; - -do_query: - (*num_groups) = 0; - (*user_gids) = NULL; - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids); - - /* and save it */ - refresh_sequence_number(domain, True); - centry = centry_start(domain, status); - if (!centry) goto skip_save; - centry_put_uint32(centry, *num_groups); - for (i=0; i<(*num_groups); i++) { - centry_put_sid(centry, (*user_gids)[i]); - } - centry_end(centry, "UG/%s", sid_to_string(sid_string, user_sid)); - centry_free(centry); - -skip_save: - return status; -} - - -static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *group_sid, uint32 *num_names, - DOM_SID ***sid_mem, char ***names, - uint32 **name_types) -{ - struct winbind_cache *cache = get_cache(domain); - struct cache_entry *centry = NULL; - NTSTATUS status; - unsigned int i; - fstring sid_string; - - if (!cache->tdb) goto do_query; - - centry = wcache_fetch(cache, domain, "GM/%s", sid_to_string(sid_string, group_sid)); - if (!centry) goto do_query; - - *num_names = centry_uint32(centry); - - if (*num_names == 0) goto do_cached; - - (*sid_mem) = talloc(mem_ctx, sizeof(**sid_mem) * (*num_names)); - (*names) = talloc(mem_ctx, sizeof(**names) * (*num_names)); - (*name_types) = talloc(mem_ctx, sizeof(**name_types) * (*num_names)); - - if (! (*sid_mem) || ! (*names) || ! (*name_types)) { - smb_panic("lookup_groupmem out of memory"); - } - - for (i=0; i<(*num_names); i++) { - (*sid_mem)[i] = centry_sid(centry, mem_ctx); - (*names)[i] = centry_string(centry, mem_ctx); - (*name_types)[i] = centry_uint32(centry); - } - -do_cached: - status = centry->status; - centry_free(centry); - return status; - -do_query: - (*num_names) = 0; - (*sid_mem) = NULL; - (*names) = NULL; - (*name_types) = NULL; - - - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->lookup_groupmem(domain, mem_ctx, group_sid, num_names, - sid_mem, names, name_types); - - /* and save it */ - refresh_sequence_number(domain, True); - centry = centry_start(domain, status); - if (!centry) goto skip_save; - centry_put_uint32(centry, *num_names); - for (i=0; i<(*num_names); i++) { - centry_put_sid(centry, (*sid_mem)[i]); - centry_put_string(centry, (*names)[i]); - centry_put_uint32(centry, (*name_types)[i]); - } - centry_end(centry, "GM/%s", sid_to_string(sid_string, group_sid)); - centry_free(centry); - -skip_save: - return status; -} - -/* find the sequence number for a domain */ -static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) -{ - refresh_sequence_number(domain, False); - - *seq = domain->sequence_number; - - return NT_STATUS_OK; -} - -/* enumerate trusted domains */ -static NTSTATUS trusted_domains(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_domains, - char ***names, - char ***alt_names, - DOM_SID **dom_sids) -{ - struct winbind_cache *cache = get_cache(domain); - - /* we don't cache this call */ - return cache->backend->trusted_domains(domain, mem_ctx, num_domains, - names, alt_names, dom_sids); -} - -/* find the domain sid */ -static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) -{ - struct winbind_cache *cache = get_cache(domain); - - /* we don't cache this call */ - return cache->backend->domain_sid(domain, sid); -} - -/* find the alternate names for the domain, if any */ -static NTSTATUS alternate_name(struct winbindd_domain *domain) -{ - struct winbind_cache *cache = get_cache(domain); - - /* we don't cache this call */ - return cache->backend->alternate_name(domain); -} - -/* the ADS backend methods are exposed via this structure */ -struct winbindd_methods cache_methods = { - True, - query_user_list, - enum_dom_groups, - enum_local_groups, - name_to_sid, - sid_to_name, - query_user, - lookup_usergroups, - lookup_groupmem, - sequence_number, - trusted_domains, - domain_sid, - alternate_name -}; diff --git a/source4/nsswitch/winbindd_cm.c b/source4/nsswitch/winbindd_cm.c deleted file mode 100644 index 0748a1c534..0000000000 --- a/source4/nsswitch/winbindd_cm.c +++ /dev/null @@ -1,954 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon connection manager - - Copyright (C) Tim Potter 2001 - Copyright (C) Andrew Bartlett 2002 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - We need to manage connections to domain controllers without having to - mess up the main winbindd code with other issues. The aim of the - connection manager is to: - - - make connections to domain controllers and cache them - - re-establish connections when networks or servers go down - - centralise the policy on connection timeouts, domain controller - selection etc - - manage re-entrancy for when winbindd becomes able to handle - multiple outstanding rpc requests - - Why not have connection management as part of the rpc layer like tng? - Good question. This code may morph into libsmb/rpc_cache.c or something - like that but at the moment it's simply staying as part of winbind. I - think the TNG architecture of forcing every user of the rpc layer to use - the connection caching system is a bad idea. It should be an optional - method of using the routines. - - The TNG design is quite good but I disagree with some aspects of the - implementation. -tpot - - */ - -/* - TODO: - - - I'm pretty annoyed by all the make_nmb_name() stuff. It should be - moved down into another function. - - - There needs to be a utility function in libsmb/namequery.c that does - cm_get_dc_name() - - - Take care when destroying cli_structs as they can be shared between - various sam handles. - - */ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Global list of connections. Initially a DLIST but can become a hash - table or whatever later. */ - -struct winbindd_cm_conn { - struct winbindd_cm_conn *prev, *next; - fstring domain; - fstring controller; - fstring pipe_name; - size_t mutex_ref_count; - struct cli_state *cli; - POLICY_HND pol; -}; - -static struct winbindd_cm_conn *cm_conns = NULL; - -/* Get a domain controller name. Cache positive and negative lookups so we - don't go to the network too often when something is badly broken. */ - -#define GET_DC_NAME_CACHE_TIMEOUT 30 /* Seconds between dc lookups */ - -struct get_dc_name_cache { - fstring domain_name; - fstring srv_name; - time_t lookup_time; - struct get_dc_name_cache *prev, *next; -}; - -/* - find the DC for a domain using methods appropriate for a ADS domain -*/ -static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name) -{ - ADS_STRUCT *ads; - const char *realm = domain; - - if (strcasecmp(realm, lp_workgroup()) == 0) - realm = lp_realm(); - - ads = ads_init(realm, domain, NULL); - if (!ads) - return False; - - /* we don't need to bind, just connect */ - ads->auth.flags |= ADS_AUTH_NO_BIND; - - DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain)); - -#ifdef HAVE_ADS - /* a full ads_connect() is actually overkill, as we don't srictly need - to do the SASL auth in order to get the info we need, but libads - doesn't offer a better way right now */ - ads_connect(ads); -#endif - - if (!ads->config.realm) - return False; - - fstrcpy(srv_name, ads->config.ldap_server_name); - strupper(srv_name); - *dc_ip = ads->ldap_ip; - ads_destroy(&ads); - - DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n", - srv_name, inet_ntoa(*dc_ip))); - - return True; -} - - - -static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out) -{ - static struct get_dc_name_cache *get_dc_name_cache; - struct get_dc_name_cache *dcc; - struct in_addr dc_ip; - BOOL ret; - - /* Check the cache for previous lookups */ - - for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) { - - if (!strequal(domain, dcc->domain_name)) - continue; /* Not our domain */ - - if ((time(NULL) - dcc->lookup_time) > - GET_DC_NAME_CACHE_TIMEOUT) { - - /* Cache entry has expired, delete it */ - - DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain)); - - DLIST_REMOVE(get_dc_name_cache, dcc); - SAFE_FREE(dcc); - - break; - } - - /* Return a positive or negative lookup for this domain */ - - if (dcc->srv_name[0]) { - DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain)); - fstrcpy(srv_name, dcc->srv_name); - return True; - } else { - DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain)); - return False; - } - } - - /* Add cache entry for this lookup. */ - - DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain)); - - if (!(dcc = (struct get_dc_name_cache *) - malloc(sizeof(struct get_dc_name_cache)))) - return False; - - ZERO_STRUCTP(dcc); - - fstrcpy(dcc->domain_name, domain); - dcc->lookup_time = time(NULL); - - DLIST_ADD(get_dc_name_cache, dcc); - - zero_ip(&dc_ip); - - ret = False; - if (lp_security() == SEC_ADS) - ret = cm_ads_find_dc(domain, &dc_ip, srv_name); - - if (!ret) { - /* fall back on rpc methods if the ADS methods fail */ - ret = rpc_find_dc(domain, srv_name, &dc_ip); - } - - if (!ret) - return False; - - /* We have a name so make the cache entry positive now */ - fstrcpy(dcc->srv_name, srv_name); - - DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name, - inet_ntoa(dc_ip), domain)); - - *ip_out = dc_ip; - - return True; -} - -/* Choose between anonymous or authenticated connections. We need to use - an authenticated connection if DCs have the RestrictAnonymous registry - entry set > 0, or the "Additional restrictions for anonymous - connections" set in the win2k Local Security Policy. - - Caller to free() result in domain, username, password -*/ - -static void cm_get_ipc_userpass(char **username, char **domain, char **password) -{ - *username = secrets_fetch(SECRETS_AUTH_USER, NULL); - *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL); - *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL); - - if (*username && **username) { - - if (!*domain || !**domain) - *domain = smb_xstrdup(lp_workgroup()); - - if (!*password || !**password) - *password = smb_xstrdup(""); - - DEBUG(3, ("IPC$ connections done by user %s\\%s\n", - *domain, *username)); - - } else { - DEBUG(3, ("IPC$ connections done anonymously\n")); - *username = smb_xstrdup(""); - *domain = smb_xstrdup(""); - *password = smb_xstrdup(""); - } -} - -/* Open a new smb pipe connection to a DC on a given domain. Cache - negative creation attempts so we don't try and connect to broken - machines too often. */ - -#define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */ - -struct failed_connection_cache { - fstring domain_name; - fstring controller; - time_t lookup_time; - NTSTATUS nt_status; - struct failed_connection_cache *prev, *next; -}; - -static struct failed_connection_cache *failed_connection_cache; - -/* Add an entry to the failed conneciton cache */ - -static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn, - NTSTATUS result) -{ - struct failed_connection_cache *fcc; - - SMB_ASSERT(!NT_STATUS_IS_OK(result)); - - /* Check we already aren't in the cache */ - - for (fcc = failed_connection_cache; fcc; fcc = fcc->next) { - if (strequal(fcc->domain_name, new_conn->domain)) { - DEBUG(10, ("domain %s already tried and failed\n", - fcc->domain_name)); - return; - } - } - - /* Create negative lookup cache entry for this domain and controller */ - - if (!(fcc = (struct failed_connection_cache *) - malloc(sizeof(struct failed_connection_cache)))) { - DEBUG(0, ("malloc failed in add_failed_connection_entry!\n")); - return; - } - - ZERO_STRUCTP(fcc); - - fstrcpy(fcc->domain_name, new_conn->domain); - fstrcpy(fcc->controller, new_conn->controller); - fcc->lookup_time = time(NULL); - fcc->nt_status = result; - - DLIST_ADD(failed_connection_cache, fcc); -} - -/* Open a connction to the remote server, cache failures for 30 seconds */ - -static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, - struct winbindd_cm_conn *new_conn, BOOL keep_mutex) -{ - struct failed_connection_cache *fcc; - NTSTATUS result; - char *ipc_username, *ipc_domain, *ipc_password; - struct in_addr dc_ip; - int i; - BOOL retry = True; - BOOL got_mutex = False; - - ZERO_STRUCT(dc_ip); - - fstrcpy(new_conn->domain, domain); - fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index)); - - /* Look for a domain controller for this domain. Negative results - are cached so don't bother applying the caching for this - function just yet. */ - - if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) { - result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - add_failed_connection_entry(new_conn, result); - return result; - } - - /* Return false if we have tried to look up this domain and netbios - name before and failed. */ - - for (fcc = failed_connection_cache; fcc; fcc = fcc->next) { - - if (!(strequal(domain, fcc->domain_name) && - strequal(new_conn->controller, fcc->controller))) - continue; /* Not our domain */ - - if ((time(NULL) - fcc->lookup_time) > - FAILED_CONNECTION_CACHE_TIMEOUT) { - - /* Cache entry has expired, delete it */ - - DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller)); - - DLIST_REMOVE(failed_connection_cache, fcc); - free(fcc); - - break; - } - - /* The timeout hasn't expired yet so return false */ - - DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller)); - - result = fcc->nt_status; - SMB_ASSERT(!NT_STATUS_IS_OK(result)); - return result; - } - - /* Initialise SMB connection */ - - cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); - - DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n", - new_conn->controller, lp_netbios_name(), ipc_domain, ipc_username)); - - for (i = 0; retry && (i < 3); i++) { - - if (!secrets_named_mutex(new_conn->controller, WINBIND_SERVER_MUTEX_WAIT_TIME, &new_conn->mutex_ref_count)) { - DEBUG(0,("cm_open_connection: mutex grab failed for %s\n", new_conn->controller)); - result = NT_STATUS_POSSIBLE_DEADLOCK; - continue; - } - - got_mutex = True; - - result = cli_full_connection(&new_conn->cli, lp_netbios_name(), new_conn->controller, - &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, - ipc_password, 0, &retry); - - if (NT_STATUS_IS_OK(result)) - break; - - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - got_mutex = False; - } - - SAFE_FREE(ipc_username); - SAFE_FREE(ipc_domain); - SAFE_FREE(ipc_password); - - if (!NT_STATUS_IS_OK(result)) { - if (got_mutex) - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - add_failed_connection_entry(new_conn, result); - return result; - } - - if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) { - result = NT_STATUS_PIPE_NOT_AVAILABLE; - /* - * only cache a failure if we are not trying to open the - * **win2k** specific lsarpc UUID. This could be an NT PDC - * and therefore a failure is normal. This should probably - * be abstracted to a check for 2k specific pipes and wondering - * if the PDC is an NT4 box. but since there is only one 2k - * specific UUID right now, i'm not going to bother. --jerry - */ - if (got_mutex) - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - if ( !is_win2k_pipe(pipe_index) ) - add_failed_connection_entry(new_conn, result); - cli_shutdown(new_conn->cli); - return result; - } - - if ((got_mutex) && !keep_mutex) - secrets_named_mutex_release(new_conn->controller, &new_conn->mutex_ref_count); - return NT_STATUS_OK; -} - -/* Return true if a connection is still alive */ - -static BOOL connection_ok(struct winbindd_cm_conn *conn) -{ - if (!conn) { - smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n"); - return False; - } - - if (!conn->cli) { - DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n", - conn->controller, conn->domain, conn->pipe_name)); - smb_panic("connection_ok: conn->cli was null!"); - return False; - } - - if (!conn->cli->initialised) { - DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n", - conn->controller, conn->domain, conn->pipe_name)); - smb_panic("connection_ok: conn->cli->initialised is False!"); - return False; - } - - if (conn->cli->fd == -1) { - DEBUG(3, ("Connection to %s for domain %s (pipe %s) has died or was never started (fd == -1)\n", - conn->controller, conn->domain, conn->pipe_name)); - return False; - } - - return True; -} - -/* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */ - -static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, - struct winbindd_cm_conn **conn_out, BOOL keep_mutex) -{ - struct winbindd_cm_conn *conn, conn_temp; - NTSTATUS result; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, pipe_name)) { - if (!connection_ok(conn)) { - if (conn->cli) - cli_shutdown(conn->cli); - ZERO_STRUCT(conn_temp); - conn_temp.next = conn->next; - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - conn = &conn_temp; /* Just to keep the loop moving */ - } else { - if (keep_mutex) { - if (!secrets_named_mutex(conn->controller, - WINBIND_SERVER_MUTEX_WAIT_TIME, &conn->mutex_ref_count)) - DEBUG(0,("get_connection_from_cache: mutex grab failed for %s\n", - conn->controller)); - } - break; - } - } - } - - if (!conn) { - if (!(conn = malloc(sizeof(*conn)))) - return NT_STATUS_NO_MEMORY; - - ZERO_STRUCTP(conn); - - if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn, keep_mutex))) { - DEBUG(3, ("Could not open a connection to %s for %s (%s)\n", - domain, pipe_name, nt_errstr(result))); - SAFE_FREE(conn); - return result; - } - DLIST_ADD(cm_conns, conn); - } - - *conn_out = conn; - return NT_STATUS_OK; -} - - -/********************************************************************************** -**********************************************************************************/ - -BOOL cm_check_for_native_mode_win2k( const char *domain ) -{ - NTSTATUS result; - struct winbindd_cm_conn conn; - DS_DOMINFO_CTR ctr; - BOOL ret = False; - - ZERO_STRUCT( conn ); - ZERO_STRUCT( ctr ); - - - if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn, False)) ) { - DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n", - domain, nt_errstr(result))); - return False; - } - - if ( conn.cli ) { - if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli, - conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) { - ret = False; - goto done; - } - } - - if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) - && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) ) - ret = True; - -done: - if ( conn.cli ) - cli_shutdown( conn.cli ); - - return ret; -} - - - -/* Return a LSA policy handle on a domain */ - -CLI_POLICY_HND *cm_get_lsa_handle(const char *domain) -{ - struct winbindd_cm_conn *conn; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - NTSTATUS result; - static CLI_POLICY_HND hnd; - - /* Look for existing connections */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn, False))) - return NULL; - - /* This *shitty* code needs scrapping ! JRA */ - if (policy_handle_is_valid(&conn->pol)) { - hnd.pol = conn->pol; - hnd.cli = conn->cli; - return &hnd; - } - - result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, - des_access, &conn->pol); - - if (!NT_STATUS_IS_OK(result)) { - /* Hit the cache code again. This cleans out the old connection and gets a new one */ - if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */ - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn, False))) - return NULL; - - result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, - des_access, &conn->pol); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return NULL; - } - } - - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain */ - -CLI_POLICY_HND *cm_get_sam_handle(char *domain) -{ - struct winbindd_cm_conn *conn; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - NTSTATUS result; - static CLI_POLICY_HND hnd; - - /* Look for existing connections */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn, False))) - return NULL; - - /* This *shitty* code needs scrapping ! JRA */ - if (policy_handle_is_valid(&conn->pol)) { - hnd.pol = conn->pol; - hnd.cli = conn->cli; - return &hnd; - } - result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, - des_access, &conn->pol); - - if (!NT_STATUS_IS_OK(result)) { - /* Hit the cache code again. This cleans out the old connection and gets a new one */ - if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */ - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn, False))) - return NULL; - - result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, - des_access, &conn->pol); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return NULL; - } - } - - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -#if 0 /* This code now *well* out of date */ - -/* Return a SAM domain policy handle on a domain */ - -CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a basic handle to open a domain handle from */ - - if (!cm_get_sam_handle(domain)) - return False; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_BASIC) - basic_conn = conn; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_DOM; - conn->cli = basic_conn->cli; - - result = cli_samr_open_domain(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, - domain_sid, &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain user */ - -CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, DOM_SID *domain_sid, - uint32 user_rid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_USER && - conn->pipe_data.samr.rid == user_rid) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a domain handle to open a user handle from */ - - if (!cm_get_sam_dom_handle(domain, domain_sid)) - return NULL; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) - basic_conn = conn; - } - - if (!basic_conn) { - DEBUG(0, ("No domain sam handle was created!\n")); - return NULL; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_USER; - conn->cli = basic_conn->cli; - conn->pipe_data.samr.rid = user_rid; - - result = cli_samr_open_user(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, user_rid, - &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain group */ - -CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid, - uint32 group_rid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_GROUP && - conn->pipe_data.samr.rid == group_rid) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a domain handle to open a user handle from */ - - if (!cm_get_sam_dom_handle(domain, domain_sid)) - return NULL; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) - basic_conn = conn; - } - - if (!basic_conn) { - DEBUG(0, ("No domain sam handle was created!\n")); - return NULL; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP; - conn->cli = basic_conn->cli; - conn->pipe_data.samr.rid = group_rid; - - result = cli_samr_open_group(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, group_rid, - &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -#endif - -/* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the - netlogon pipe as no handle is returned. */ - -NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_passwd, - struct cli_state **cli) -{ - NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - struct winbindd_cm_conn *conn; - uint32 neg_flags = 0x000001ff; - - if (!cli) - return NT_STATUS_INVALID_PARAMETER; - - /* Open an initial conection - keep the mutex. */ - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn, True))) - return result; - - result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2); - - if (conn->mutex_ref_count) - secrets_named_mutex_release(conn->controller, &conn->mutex_ref_count); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(0, ("error connecting to domain password server: %s\n", - nt_errstr(result))); - - /* Hit the cache code again. This cleans out the old connection and gets a new one */ - if (conn->cli->fd == -1) { - - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn, True))) - return result; - - /* Try again */ - result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2); - - if (conn->mutex_ref_count) - secrets_named_mutex_release(conn->controller, &conn->mutex_ref_count); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return result; - } - } - - *cli = conn->cli; - - return result; -} - -/* Dump the current connection status */ - -static void dump_conn_list(void) -{ - struct winbindd_cm_conn *con; - - DEBUG(0, ("\tDomain Controller Pipe\n")); - - for(con = cm_conns; con; con = con->next) { - char *msg; - - /* Display pipe info */ - - if (asprintf(&msg, "\t%-15s %-15s %-16s", con->domain, con->controller, con->pipe_name) < 0) { - DEBUG(0, ("Error: not enough memory!\n")); - } else { - DEBUG(0, ("%s\n", msg)); - SAFE_FREE(msg); - } - } -} - -void winbindd_cm_status(void) -{ - /* List open connections */ - - DEBUG(0, ("winbindd connection manager status:\n")); - - if (cm_conns) - dump_conn_list(); - else - DEBUG(0, ("\tNo active connections\n")); -} diff --git a/source4/nsswitch/winbindd_dual.c b/source4/nsswitch/winbindd_dual.c deleted file mode 100644 index 207757bcea..0000000000 --- a/source4/nsswitch/winbindd_dual.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind background daemon - - Copyright (C) Andrew Tridgell 2002 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - the idea of the optional dual daemon mode is ot prevent slow domain - responses from clagging up the rest of the system. When in dual - daemon mode winbindd always responds to requests from cache if the - request is in cache, and if the cached answer is stale then it asks - the "dual daemon" to update the cache for that request - - */ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -extern BOOL opt_dual_daemon; -BOOL background_process = False; -int dual_daemon_pipe = -1; - - -/* a list of requests ready to be sent to the dual daemon */ -struct dual_list { - struct dual_list *next; - char *data; - int length; - int offset; -}; - -static struct dual_list *dual_list; -static struct dual_list *dual_list_end; - -/* - setup a select() including the dual daemon pipe - */ -int dual_select_setup(fd_set *fds, int maxfd) -{ - if (dual_daemon_pipe == -1 || - !dual_list) { - return maxfd; - } - - FD_SET(dual_daemon_pipe, fds); - if (dual_daemon_pipe > maxfd) { - maxfd = dual_daemon_pipe; - } - return maxfd; -} - - -/* - a hook called from the main winbindd select() loop to handle writes - to the dual daemon pipe -*/ -void dual_select(fd_set *fds) -{ - int n; - - if (dual_daemon_pipe == -1 || - !dual_list || - !FD_ISSET(dual_daemon_pipe, fds)) { - return; - } - - n = sys_write(dual_daemon_pipe, - &dual_list->data[dual_list->offset], - dual_list->length - dual_list->offset); - - if (n <= 0) { - /* the pipe is dead! fall back to normal operation */ - dual_daemon_pipe = -1; - return; - } - - dual_list->offset += n; - - if (dual_list->offset == dual_list->length) { - struct dual_list *next; - next = dual_list->next; - free(dual_list->data); - free(dual_list); - dual_list = next; - if (!dual_list) { - dual_list_end = NULL; - } - } -} - -/* - send a request to the background daemon - this is called for stale cached entries -*/ -void dual_send_request(struct winbindd_cli_state *state) -{ - struct dual_list *list; - - if (!background_process) return; - - list = malloc(sizeof(*list)); - if (!list) return; - - list->next = NULL; - list->data = memdup(&state->request, sizeof(state->request)); - list->length = sizeof(state->request); - list->offset = 0; - - if (!dual_list_end) { - dual_list = list; - dual_list_end = list; - } else { - dual_list_end->next = list; - dual_list_end = list; - } - - background_process = False; -} - - -/* -the main dual daemon -*/ -void do_dual_daemon(void) -{ - int fdpair[2]; - struct winbindd_cli_state state; - - if (pipe(fdpair) != 0) { - return; - } - - ZERO_STRUCT(state); - state.pid = getpid(); - - dual_daemon_pipe = fdpair[1]; - state.sock = fdpair[0]; - - if (fork() != 0) { - close(fdpair[0]); - return; - } - close(fdpair[1]); - - if (!winbind_setup_common()) - _exit(0); - - dual_daemon_pipe = -1; - opt_dual_daemon = False; - - while (1) { - /* free up any talloc memory */ - lp_talloc_free(); - main_loop_talloc_free(); - - /* fetch a request from the main daemon */ - winbind_client_read(&state); - - if (state.finished) { - /* we lost contact with our parent */ - exit(0); - } - - /* process full rquests */ - if (state.read_buf_len == sizeof(state.request)) { - DEBUG(4,("dual daemon request %d\n", (int)state.request.cmd)); - - /* special handling for the stateful requests */ - switch (state.request.cmd) { - case WINBINDD_GETPWENT: - winbindd_setpwent(&state); - break; - - case WINBINDD_GETGRENT: - case WINBINDD_GETGRLST: - winbindd_setgrent(&state); - break; - default: - break; - } - - winbind_process_packet(&state); - SAFE_FREE(state.response.extra_data); - - free_getent_state(state.getpwent_state); - free_getent_state(state.getgrent_state); - state.getpwent_state = NULL; - state.getgrent_state = NULL; - } - } -} - diff --git a/source4/nsswitch/winbindd_group.c b/source4/nsswitch/winbindd_group.c deleted file mode 100644 index d06db5943c..0000000000 --- a/source4/nsswitch/winbindd_group.c +++ /dev/null @@ -1,896 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000 - Copyright (C) Jeremy Allison 2001. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/*************************************************************** - Empty static struct for negative caching. -****************************************************************/ - -/* Fill a grent structure from various other information */ - -static BOOL fill_grent(struct winbindd_gr *gr, const char *dom_name, - const char *gr_name, gid_t unix_gid) -{ - fstring full_group_name; - /* Fill in uid/gid */ - fill_domain_username(full_group_name, dom_name, gr_name); - - gr->gr_gid = unix_gid; - - /* Group name and password */ - - safe_strcpy(gr->gr_name, full_group_name, sizeof(gr->gr_name) - 1); - safe_strcpy(gr->gr_passwd, "x", sizeof(gr->gr_passwd) - 1); - - return True; -} - -/* Fill in the group membership field of a NT group given by group_sid */ - -static BOOL fill_grent_mem(struct winbindd_domain *domain, - DOM_SID *group_sid, - enum SID_NAME_USE group_name_type, - int *num_gr_mem, char **gr_mem, int *gr_mem_len) -{ - DOM_SID **sid_mem = NULL; - uint32 num_names = 0; - uint32 *name_types = NULL; - unsigned int buf_len, buf_ndx, i; - char **names = NULL, *buf; - BOOL result = False; - TALLOC_CTX *mem_ctx; - NTSTATUS status; - fstring sid_string; - - if (!(mem_ctx = talloc_init("fill_grent_mem(%s)", domain->name))) - return False; - - /* Initialise group membership information */ - - DEBUG(10, ("group SID %s\n", sid_to_string(sid_string, group_sid))); - - *num_gr_mem = 0; - - if (group_name_type != SID_NAME_DOM_GRP) { - DEBUG(1, ("SID %s in domain %s isn't a domain group\n", - sid_to_string(sid_string, group_sid), domain->name)); - goto done; - } - - /* Lookup group members */ - status = domain->methods->lookup_groupmem(domain, mem_ctx, group_sid, &num_names, - &sid_mem, &names, &name_types); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("could not lookup membership for group rid %s in domain %s (error: %s)\n", - sid_to_string(sid_string, group_sid), domain->name, nt_errstr(status))); - - goto done; - } - - DEBUG(10, ("looked up %d names\n", num_names)); - - if (DEBUGLEVEL >= 10) { - for (i = 0; i < num_names; i++) - DEBUG(10, ("\t%20s %s %d\n", names[i], sid_to_string(sid_string, sid_mem[i]), - name_types[i])); - } - - /* Add members to list */ - - buf = NULL; - buf_len = buf_ndx = 0; - - again: - - for (i = 0; i < num_names; i++) { - char *the_name; - fstring name; - int len; - - the_name = names[i]; - - DEBUG(10, ("processing name %s\n", the_name)); - - /* FIXME: need to cope with groups within groups. These - occur in Universal groups on a Windows 2000 native mode - server. */ - - if (name_types[i] != SID_NAME_USER) { - DEBUG(3, ("name %s isn't a domain user\n", the_name)); - continue; - } - - /* Don't bother with machine accounts */ - - if (the_name[strlen(the_name) - 1] == '$') { - DEBUG(10, ("%s is machine account\n", the_name)); - continue; - } - - /* Append domain name */ - - fill_domain_username(name, domain->name, the_name); - - len = strlen(name); - - /* Add to list or calculate buffer length */ - - if (!buf) { - buf_len += len + 1; /* List is comma separated */ - (*num_gr_mem)++; - DEBUG(10, ("buf_len + %d = %d\n", len + 1, buf_len)); - } else { - DEBUG(10, ("appending %s at ndx %d\n", name, len)); - safe_strcpy(&buf[buf_ndx], name, len); - buf_ndx += len; - buf[buf_ndx] = ','; - buf_ndx++; - } - } - - /* Allocate buffer */ - - if (!buf && buf_len != 0) { - if (!(buf = malloc(buf_len))) { - DEBUG(1, ("out of memory\n")); - result = False; - goto done; - } - memset(buf, 0, buf_len); - goto again; - } - - if (buf && buf_ndx > 0) { - buf[buf_ndx - 1] = '\0'; - } - - *gr_mem = buf; - *gr_mem_len = buf_len; - - DEBUG(10, ("num_mem = %d, len = %d, mem = %s\n", *num_gr_mem, - buf_len, *num_gr_mem ? buf : "NULL")); - result = True; - -done: - - talloc_destroy(mem_ctx); - - DEBUG(10, ("fill_grent_mem returning %d\n", result)); - - return result; -} - -/* Return a group structure from a group name */ - -enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) -{ - DOM_SID group_sid; - struct winbindd_domain *domain; - enum SID_NAME_USE name_type; - fstring name_domain, name_group; - char *tmp, *gr_mem; - gid_t gid; - int gr_mem_len; - - /* Ensure null termination */ - state->request.data.groupname[sizeof(state->request.data.groupname)-1]='\0'; - - DEBUG(3, ("[%5d]: getgrnam %s\n", state->pid, - state->request.data.groupname)); - - /* Parse domain and groupname */ - - memset(name_group, 0, sizeof(fstring)); - - tmp = state->request.data.groupname; - if (!parse_domain_user(tmp, name_domain, name_group)) - return WINBINDD_ERROR; - - /* Get info for the domain */ - - if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(0, ("could not get domain sid for domain %s\n", - name_domain)); - return WINBINDD_ERROR; - } - - /* Get rid and name type from name */ - - if (!winbindd_lookup_sid_by_name(domain, name_group, &group_sid, - &name_type)) { - DEBUG(1, ("group %s in domain %s does not exist\n", - name_group, name_domain)); - return WINBINDD_ERROR; - } - - if ((name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_DOM_GRP)) { - DEBUG(1, ("name '%s' is not a local or domain group: %d\n", - name_group, name_type)); - return WINBINDD_ERROR; - } - - if (!winbindd_idmap_get_gid_from_sid(&group_sid, &gid)) { - DEBUG(1, ("error converting unix gid to sid\n")); - return WINBINDD_ERROR; - } - - if (!fill_grent(&state->response.data.gr, name_domain, - name_group, gid) || - !fill_grent_mem(domain, &group_sid, name_type, - &state->response.data.gr.num_gr_mem, - &gr_mem, &gr_mem_len)) { - return WINBINDD_ERROR; - } - - /* Group membership lives at start of extra data */ - - state->response.data.gr.gr_mem_ofs = 0; - - state->response.length += gr_mem_len; - state->response.extra_data = gr_mem; - - return WINBINDD_OK; -} - -/* Return a group structure from a gid number */ - -enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - DOM_SID group_sid; - enum SID_NAME_USE name_type; - fstring dom_name; - fstring group_name; - int gr_mem_len; - char *gr_mem; - - DEBUG(3, ("[%5d]: getgrgid %d\n", state->pid, - state->request.data.gid)); - - /* Bug out if the gid isn't in the winbind range */ - - if ((state->request.data.gid < server_state.gid_low) || - (state->request.data.gid > server_state.gid_high)) - return WINBINDD_ERROR; - - /* Get rid from gid */ - - if (!winbindd_idmap_get_sid_from_gid(state->request.data.gid, &group_sid)) { - DEBUG(1, ("could not convert gid %d to rid\n", - state->request.data.gid)); - return WINBINDD_ERROR; - } - - /* Get name from sid */ - - if (!winbindd_lookup_name_by_sid(&group_sid, dom_name, group_name, &name_type)) { - DEBUG(1, ("could not lookup sid\n")); - return WINBINDD_ERROR; - } - - if (!((name_type == SID_NAME_ALIAS) || - (name_type == SID_NAME_DOM_GRP))) { - DEBUG(1, ("name '%s' is not a local or domain group: %d\n", - group_name, name_type)); - return WINBINDD_ERROR; - } - - /* Fill in group structure */ - - domain = find_domain_from_sid(&group_sid); - - if (!domain) { - DEBUG(1,("Can't find domain from sid\n")); - return WINBINDD_ERROR; - } - - if (!fill_grent(&state->response.data.gr, dom_name, group_name, - state->request.data.gid) || - !fill_grent_mem(domain, &group_sid, name_type, - &state->response.data.gr.num_gr_mem, - &gr_mem, &gr_mem_len)) - return WINBINDD_ERROR; - - /* Group membership lives at start of extra data */ - - state->response.data.gr.gr_mem_ofs = 0; - - state->response.length += gr_mem_len; - state->response.extra_data = gr_mem; - - return WINBINDD_OK; -} - -/* - * set/get/endgrent functions - */ - -/* "Rewind" file pointer for group database enumeration */ - -enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - - DEBUG(3, ("[%5d]: setgrent\n", state->pid)); - - /* Check user has enabled this */ - - if (!lp_winbind_enum_groups()) - return WINBINDD_ERROR; - - /* Free old static data if it exists */ - - if (state->getgrent_state != NULL) { - free_getent_state(state->getgrent_state); - state->getgrent_state = NULL; - } - - /* Create sam pipes for each domain we know about */ - - for (domain = domain_list(); domain != NULL; domain = domain->next) { - struct getent_state *domain_state; - - /* Create a state record for this domain */ - - if ((domain_state = (struct getent_state *) - malloc(sizeof(struct getent_state))) == NULL) { - DEBUG(1, ("winbindd_setgrent: malloc failed for domain_state!\n")); - return WINBINDD_ERROR; - } - - ZERO_STRUCTP(domain_state); - - fstrcpy(domain_state->domain_name, domain->name); - - /* Add to list of open domains */ - - DLIST_ADD(state->getgrent_state, domain_state); - } - - return WINBINDD_OK; -} - -/* Close file pointer to ntdom group database */ - -enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state) -{ - DEBUG(3, ("[%5d]: endgrent\n", state->pid)); - - free_getent_state(state->getgrent_state); - state->getgrent_state = NULL; - - return WINBINDD_OK; -} - -/* Get the list of domain groups and domain aliases for a domain. We fill in - the sam_entries and num_sam_entries fields with domain group information. - The dispinfo_ndx field is incremented to the index of the next group to - fetch. Return True if some groups were returned, False otherwise. */ - -#define MAX_FETCH_SAM_ENTRIES 100 - -static BOOL get_sam_group_entries(struct getent_state *ent) -{ - NTSTATUS status; - uint32 num_entries; - struct acct_info *name_list = NULL, *tmp_name_list = NULL; - TALLOC_CTX *mem_ctx; - BOOL result = False; - struct acct_info *sam_grp_entries = NULL; - struct winbindd_domain *domain; - - if (ent->got_sam_entries) - return False; - - if (!(mem_ctx = talloc_init("get_sam_group_entries(%s)", - ent->domain_name))) { - DEBUG(1, ("get_sam_group_entries: could not create talloc context!\n")); - return False; - } - - /* Free any existing group info */ - - SAFE_FREE(ent->sam_entries); - ent->num_sam_entries = 0; - ent->got_sam_entries = True; - - /* Enumerate domain groups */ - - num_entries = 0; - - if (!(domain = find_domain_from_name(ent->domain_name))) { - DEBUG(3, ("no such domain %s in get_sam_group_entries\n", ent->domain_name)); - goto done; - } - - /* always get the domain global groups */ - - status = domain->methods->enum_dom_groups(domain, mem_ctx, &num_entries, &sam_grp_entries); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("get_sam_group_entries: could not enumerate domain groups! Error: %s\n", nt_errstr(status))); - result = False; - goto done; - } - - /* Copy entries into return buffer */ - - if (num_entries) { - if ( !(name_list = malloc(sizeof(struct acct_info) * num_entries)) ) { - DEBUG(0,("get_sam_group_entries: Failed to malloc memory for %d domain groups!\n", - num_entries)); - result = False; - goto done; - } - memcpy( name_list, sam_grp_entries, num_entries * sizeof(struct acct_info) ); - } - - ent->num_sam_entries = num_entries; - - /* get the domain local groups if we are a member of - a native win2k domain */ - - if ( domain->native_mode && domain->methods->enum_local_groups ) - { - DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n")); - - status = domain->methods->enum_local_groups(domain, mem_ctx, &num_entries, &sam_grp_entries); - - if ( !NT_STATUS_IS_OK(status) ) { - DEBUG(3,("get_sam_group_entries: Failed to enumerate domain local groups!\n")); - num_entries = 0; - } - else - DEBUG(4,("get_sam_group_entries: Returned %d local groups\n", num_entries)); - - /* Copy entries into return buffer */ - - if ( num_entries ) { - if ( !(tmp_name_list = Realloc( name_list, sizeof(struct acct_info) * (ent->num_sam_entries+num_entries))) ) - { - DEBUG(0,("get_sam_group_entries: Failed to realloc more memory for %d local groups!\n", - num_entries)); - result = False; - SAFE_FREE( name_list ); - goto done; - } - - name_list = tmp_name_list; - - memcpy( &name_list[ent->num_sam_entries], sam_grp_entries, - num_entries * sizeof(struct acct_info) ); - } - - ent->num_sam_entries += num_entries; - } - - - /* Fill in remaining fields */ - - ent->sam_entries = name_list; - ent->sam_entry_index = 0; - - result = (ent->num_sam_entries > 0); - - done: - talloc_destroy(mem_ctx); - - return result; -} - -/* Fetch next group entry from ntdom database */ - -#define MAX_GETGRENT_GROUPS 500 - -enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) -{ - struct getent_state *ent; - struct winbindd_gr *group_list = NULL; - int num_groups, group_list_ndx = 0, i, gr_mem_list_len = 0; - char *new_extra_data, *gr_mem_list = NULL; - - DEBUG(3, ("[%5d]: getgrent\n", state->pid)); - - /* Check user has enabled this */ - - if (!lp_winbind_enum_groups()) - return WINBINDD_ERROR; - - num_groups = MIN(MAX_GETGRENT_GROUPS, state->request.data.num_entries); - - if ((state->response.extra_data = - malloc(num_groups * sizeof(struct winbindd_gr))) == NULL) - return WINBINDD_ERROR; - - state->response.data.num_entries = 0; - - group_list = (struct winbindd_gr *)state->response.extra_data; - - if (!(ent = state->getgrent_state)) - return WINBINDD_ERROR; - - /* Start sending back groups */ - - for (i = 0; i < num_groups; i++) { - struct acct_info *name_list = NULL; - fstring domain_group_name; - uint32 result; - gid_t group_gid; - int gr_mem_len; - char *gr_mem, *new_gr_mem_list; - DOM_SID group_sid; - struct winbindd_domain *domain; - - /* Do we need to fetch another chunk of groups? */ - - tryagain: - - DEBUG(10, ("entry_index = %d, num_entries = %d\n", - ent->sam_entry_index, ent->num_sam_entries)); - - if (ent->num_sam_entries == ent->sam_entry_index) { - - while(ent && !get_sam_group_entries(ent)) { - struct getent_state *next_ent; - - DEBUG(10, ("freeing state info for domain %s\n", ent->domain_name)); - - /* Free state information for this domain */ - - SAFE_FREE(ent->sam_entries); - - next_ent = ent->next; - DLIST_REMOVE(state->getgrent_state, ent); - - SAFE_FREE(ent); - ent = next_ent; - } - - /* No more domains */ - - if (!ent) - break; - } - - name_list = ent->sam_entries; - - if (!(domain = - find_domain_from_name(ent->domain_name))) { - DEBUG(3, ("No such domain %s in winbindd_getgrent\n", ent->domain_name)); - result = False; - goto done; - } - - /* Lookup group info */ - - sid_copy(&group_sid, &domain->sid); - sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid); - - if (!winbindd_idmap_get_gid_from_sid( - &group_sid, - &group_gid)) { - - DEBUG(1, ("could not look up gid for group %s\n", - name_list[ent->sam_entry_index].acct_name)); - - ent->sam_entry_index++; - goto tryagain; - } - - DEBUG(10, ("got gid %d for group %x\n", group_gid, - name_list[ent->sam_entry_index].rid)); - - /* Fill in group entry */ - - fill_domain_username(domain_group_name, ent->domain_name, - name_list[ent->sam_entry_index].acct_name); - - result = fill_grent(&group_list[group_list_ndx], - ent->domain_name, - name_list[ent->sam_entry_index].acct_name, - group_gid); - - /* Fill in group membership entry */ - - if (result) { - DOM_SID member_sid; - group_list[group_list_ndx].num_gr_mem = 0; - gr_mem = NULL; - gr_mem_len = 0; - - /* Get group membership */ - if (state->request.cmd == WINBINDD_GETGRLST) { - result = True; - } else { - sid_copy(&member_sid, &domain->sid); - sid_append_rid(&member_sid, name_list[ent->sam_entry_index].rid); - result = fill_grent_mem( - domain, - &member_sid, - SID_NAME_DOM_GRP, - &group_list[group_list_ndx].num_gr_mem, - &gr_mem, &gr_mem_len); - } - } - - if (result) { - /* Append to group membership list */ - new_gr_mem_list = Realloc( - gr_mem_list, - gr_mem_list_len + gr_mem_len); - - if (!new_gr_mem_list && (group_list[group_list_ndx].num_gr_mem != 0)) { - DEBUG(0, ("out of memory\n")); - SAFE_FREE(gr_mem_list); - gr_mem_list_len = 0; - break; - } - - DEBUG(10, ("list_len = %d, mem_len = %d\n", - gr_mem_list_len, gr_mem_len)); - - gr_mem_list = new_gr_mem_list; - - memcpy(&gr_mem_list[gr_mem_list_len], gr_mem, - gr_mem_len); - - SAFE_FREE(gr_mem); - - group_list[group_list_ndx].gr_mem_ofs = - gr_mem_list_len; - - gr_mem_list_len += gr_mem_len; - } - - ent->sam_entry_index++; - - /* Add group to return list */ - - if (result) { - - DEBUG(10, ("adding group num_entries = %d\n", - state->response.data.num_entries)); - - group_list_ndx++; - state->response.data.num_entries++; - - state->response.length += - sizeof(struct winbindd_gr); - - } else { - DEBUG(0, ("could not lookup domain group %s\n", - domain_group_name)); - } - } - - /* Copy the list of group memberships to the end of the extra data */ - - if (group_list_ndx == 0) - goto done; - - new_extra_data = Realloc( - state->response.extra_data, - group_list_ndx * sizeof(struct winbindd_gr) + gr_mem_list_len); - - if (!new_extra_data) { - DEBUG(0, ("out of memory\n")); - group_list_ndx = 0; - SAFE_FREE(state->response.extra_data); - SAFE_FREE(gr_mem_list); - - return WINBINDD_ERROR; - } - - state->response.extra_data = new_extra_data; - - memcpy(&((char *)state->response.extra_data) - [group_list_ndx * sizeof(struct winbindd_gr)], - gr_mem_list, gr_mem_list_len); - - SAFE_FREE(gr_mem_list); - - state->response.length += gr_mem_list_len; - - DEBUG(10, ("returning %d groups, length = %d\n", - group_list_ndx, gr_mem_list_len)); - - /* Out of domains */ - - done: - - return (group_list_ndx > 0) ? WINBINDD_OK : WINBINDD_ERROR; -} - -/* List domain groups without mapping to unix ids */ - -enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) -{ - uint32 total_entries = 0; - struct winbindd_domain *domain; - char *extra_data = NULL; - char *ted = NULL; - unsigned int extra_data_len = 0, i; - - DEBUG(3, ("[%5d]: list groups\n", state->pid)); - - /* Enumerate over trusted domains */ - - for (domain = domain_list(); domain; domain = domain->next) { - struct getent_state groups; - - ZERO_STRUCT(groups); - - /* Get list of sam groups */ - ZERO_STRUCT(groups); - fstrcpy(groups.domain_name, domain->name); - - get_sam_group_entries(&groups); - - if (groups.num_sam_entries == 0) { - /* this domain is empty or in an error state */ - continue; - } - - /* keep track the of the total number of groups seen so - far over all domains */ - total_entries += groups.num_sam_entries; - - /* Allocate some memory for extra data. Note that we limit - account names to sizeof(fstring) = 128 characters. */ - ted = Realloc(extra_data, sizeof(fstring) * total_entries); - - if (!ted) { - DEBUG(0,("failed to enlarge buffer!\n")); - SAFE_FREE(extra_data); - return WINBINDD_ERROR; - } else - extra_data = ted; - - /* Pack group list into extra data fields */ - for (i = 0; i < groups.num_sam_entries; i++) { - char *group_name = ((struct acct_info *) - groups.sam_entries)[i].acct_name; - fstring name; - - fill_domain_username(name, domain->name, group_name); - /* Append to extra data */ - memcpy(&extra_data[extra_data_len], name, - strlen(name)); - extra_data_len += strlen(name); - extra_data[extra_data_len++] = ','; - } - - free(groups.sam_entries); - } - - /* Assign extra_data fields in response structure */ - if (extra_data) { - extra_data[extra_data_len - 1] = '\0'; - state->response.extra_data = extra_data; - state->response.length += extra_data_len; - } - - /* No domains may have responded but that's still OK so don't - return an error. */ - - return WINBINDD_OK; -} - -/* Get user supplementary groups. This is much quicker than trying to - invert the groups database. */ - -enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) -{ - fstring name_domain, name_user; - DOM_SID user_sid; - enum SID_NAME_USE name_type; - uint32 num_groups, num_gids; - NTSTATUS status; - DOM_SID **user_gids; - struct winbindd_domain *domain; - enum winbindd_result result = WINBINDD_ERROR; - gid_t *gid_list; - unsigned int i; - TALLOC_CTX *mem_ctx; - - /* Ensure null termination */ - state->request.data.username[sizeof(state->request.data.username)-1]='\0'; - - DEBUG(3, ("[%5d]: getgroups %s\n", state->pid, - state->request.data.username)); - - if (!(mem_ctx = talloc_init("winbindd_getgroups(%s)", - state->request.data.username))) - return WINBINDD_ERROR; - - /* Parse domain and username */ - - if (!parse_domain_user(state->request.data.username, name_domain, - name_user)) - goto done; - - /* Get info for the domain */ - - if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(0, ("could not find domain entry for domain %s\n", - name_domain)); - goto done; - } - - /* Get rid and name type from name. The following costs 1 packet */ - - if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, - &name_type)) { - DEBUG(1, ("user '%s' does not exist\n", name_user)); - goto done; - } - - if (name_type != SID_NAME_USER) { - DEBUG(1, ("name '%s' is not a user name: %d\n", - name_user, name_type)); - goto done; - } - - status = domain->methods->lookup_usergroups(domain, mem_ctx, - &user_sid, &num_groups, - &user_gids); - if (!NT_STATUS_IS_OK(status)) goto done; - - /* Copy data back to client */ - - num_gids = 0; - gid_list = malloc(sizeof(gid_t) * num_groups); - - if (state->response.extra_data) - goto done; - - for (i = 0; i < num_groups; i++) { - if (!winbindd_idmap_get_gid_from_sid( - user_gids[i], - &gid_list[num_gids])) { - fstring sid_string; - - DEBUG(1, ("unable to convert group sid %s to gid\n", - sid_to_string(sid_string, user_gids[i]))); - continue; - } - - num_gids++; - } - - state->response.data.num_entries = num_gids; - state->response.extra_data = gid_list; - state->response.length += num_gids * sizeof(gid_t); - - result = WINBINDD_OK; - - done: - - talloc_destroy(mem_ctx); - - return result; -} diff --git a/source4/nsswitch/winbindd_idmap.c b/source4/nsswitch/winbindd_idmap.c deleted file mode 100644 index de547cde41..0000000000 --- a/source4/nsswitch/winbindd_idmap.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Winbind ID Mapping - Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori <aliguor@us.ibm.com> 2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -static struct { - const char *name; - /* Function to create a member of the idmap_methods list */ - BOOL (*reg_meth)(struct idmap_methods **methods); - struct idmap_methods *methods; -} builtin_idmap_functions[] = { - { "tdb", winbind_idmap_reg_tdb, NULL }, - /* { "ldap", winbind_idmap_reg_ldap, NULL },*/ - { NULL, NULL, NULL } -}; - -/* singleton pattern: uberlazy evaluation */ -static struct idmap_methods *impl; - -static struct idmap_methods *get_impl(const char *name) -{ - int i = 0; - struct idmap_methods *ret = NULL; - - while (builtin_idmap_functions[i].name && - strcmp(builtin_idmap_functions[i].name, name)) { - i++; - } - - if (builtin_idmap_functions[i].name) { - if (!builtin_idmap_functions[i].methods) { - builtin_idmap_functions[i].reg_meth(&builtin_idmap_functions[i].methods); - } - - ret = builtin_idmap_functions[i].methods; - } - - return ret; -} - -/* Initialize backend */ -BOOL winbindd_idmap_init(void) -{ - BOOL ret = False; - - DEBUG(3, ("winbindd_idmap_init: using '%s' as backend\n", - lp_idmap_backend())); - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - if (!impl) { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - } - - if (impl) { - ret = impl->init(); - } - - DEBUG(3, ("winbind_idmap_init: returning %s\n", ret ? "true" : "false")); - - return ret; -} - -/* Get UID from SID */ -BOOL winbindd_idmap_get_uid_from_sid(DOM_SID *sid, uid_t *uid) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - if (!impl) { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - } - - if (impl) { - ret = impl->get_uid_from_sid(sid, uid); - } - - return ret; -} - -/* Get GID from SID */ -BOOL winbindd_idmap_get_gid_from_sid(DOM_SID *sid, gid_t *gid) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - if (!impl) { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - } - - if (impl) { - ret = impl->get_gid_from_sid(sid, gid); - } - - return ret; -} - -/* Get SID from UID */ -BOOL winbindd_idmap_get_sid_from_uid(uid_t uid, DOM_SID *sid) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - if (!impl) { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - } - - if (impl) { - ret = impl->get_sid_from_uid(uid, sid); - } - - return ret; -} - -/* Get SID from GID */ -BOOL winbindd_idmap_get_sid_from_gid(gid_t gid, DOM_SID *sid) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - } - - if (impl) { - ret = impl->get_sid_from_gid(gid, sid); - } else { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - - return ret; -} - -/* Close backend */ -BOOL winbindd_idmap_close(void) -{ - BOOL ret = False; - - if (!impl) { - impl = get_impl(lp_idmap_backend()); - } - - if (impl) { - ret = impl->close(); - } else { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } - - return ret; -} - -/* Dump backend status */ -void winbindd_idmap_status(void) -{ - if (!impl) { - impl = get_impl(lp_idmap_backend()); - } - - if (impl) { - impl->status(); - } else { - DEBUG(0, ("winbindd_idmap_init: could not load backend '%s'\n", - lp_idmap_backend())); - } -} - diff --git a/source4/nsswitch/winbindd_idmap_tdb.c b/source4/nsswitch/winbindd_idmap_tdb.c deleted file mode 100644 index 911b3b41d2..0000000000 --- a/source4/nsswitch/winbindd_idmap_tdb.c +++ /dev/null @@ -1,441 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - user related function - - Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori 2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* High water mark keys */ -#define HWM_GROUP "GROUP HWM" -#define HWM_USER "USER HWM" - -/* idmap version determines auto-conversion */ -#define IDMAP_VERSION 2 - -/* Globals */ -static TDB_CONTEXT *idmap_tdb; - -/* convert one record to the new format */ -static int tdb_convert_fn(TDB_CONTEXT * tdb, TDB_DATA key, TDB_DATA data, - void *ignored) -{ - struct winbindd_domain *domain; - char *p; - DOM_SID sid; - uint32 rid; - fstring keystr; - fstring dom_name; - TDB_DATA key2; - - p = strchr(key.dptr, '/'); - if (!p) - return 0; - - *p = 0; - fstrcpy(dom_name, key.dptr); - *p++ = '/'; - - domain = find_domain_from_name(dom_name); - if (!domain) { - /* We must delete the old record. */ - DEBUG(0, - ("winbindd: tdb_convert_fn : Unable to find domain %s\n", - dom_name)); - DEBUG(0, - ("winbindd: tdb_convert_fn : deleting record %s\n", - key.dptr)); - tdb_delete(idmap_tdb, key); - return 0; - } - - rid = atoi(p); - - sid_copy(&sid, &domain->sid); - sid_append_rid(&sid, rid); - - sid_to_string(keystr, &sid); - key2.dptr = keystr; - key2.dsize = strlen(keystr) + 1; - - if (tdb_store(idmap_tdb, key2, data, TDB_INSERT) != 0) { - /* not good! */ - DEBUG(0, - ("winbindd: tdb_convert_fn : Unable to update record %s\n", - key2.dptr)); - DEBUG(0, - ("winbindd: tdb_convert_fn : conversion failed - idmap corrupt ?\n")); - return -1; - } - - if (tdb_store(idmap_tdb, data, key2, TDB_REPLACE) != 0) { - /* not good! */ - DEBUG(0, - ("winbindd: tdb_convert_fn : Unable to update record %s\n", - data.dptr)); - DEBUG(0, - ("winbindd: tdb_convert_fn : conversion failed - idmap corrupt ?\n")); - return -1; - } - - tdb_delete(idmap_tdb, key); - - return 0; -} - -/***************************************************************************** - Convert the idmap database from an older version. -*****************************************************************************/ -static BOOL tdb_idmap_convert(const char *idmap_name) -{ - int32 vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION"); - BOOL bigendianheader = - (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False; - - if (vers == IDMAP_VERSION) - return True; - - if (((vers == -1) && bigendianheader) - || (IREV(vers) == IDMAP_VERSION)) { - /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */ - /* - * high and low records were created on a - * big endian machine and will need byte-reversing. - */ - - int32 wm; - - wm = tdb_fetch_int32(idmap_tdb, HWM_USER); - - if (wm != -1) { - wm = IREV(wm); - } else - wm = server_state.uid_low; - - if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) { - DEBUG(0, - ("tdb_idmap_convert: Unable to byteswap user hwm in idmap database\n")); - return False; - } - - wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP); - if (wm != -1) { - wm = IREV(wm); - } else - wm = server_state.gid_low; - - if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) { - DEBUG(0, - ("tdb_idmap_convert: Unable to byteswap group hwm in idmap database\n")); - return False; - } - } - - /* the old format stored as DOMAIN/rid - now we store the SID direct */ - tdb_traverse(idmap_tdb, tdb_convert_fn, NULL); - - if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == - -1) { - DEBUG(0, - ("tdb_idmap_convert: Unable to byteswap group hwm in idmap database\n")); - return False; - } - - return True; -} - -/* Allocate either a user or group id from the pool */ -static BOOL tdb_allocate_id(uid_t * id, BOOL isgroup) -{ - int hwm; - - /* Get current high water mark */ - if ((hwm = tdb_fetch_int32(idmap_tdb, - isgroup ? HWM_GROUP : HWM_USER)) == - -1) { - return False; - } - - /* Return next available uid in list */ - if ((isgroup && (hwm > server_state.gid_high)) || - (!isgroup && (hwm > server_state.uid_high))) { - DEBUG(0, - ("winbind %sid range full!\n", isgroup ? "g" : "u")); - return False; - } - - if (id) { - *id = hwm; - } - - hwm++; - - /* Store new high water mark */ - tdb_store_int32(idmap_tdb, isgroup ? HWM_GROUP : HWM_USER, hwm); - - return True; -} - -/* Get a sid from an id */ -static BOOL tdb_get_sid_from_id(int id, DOM_SID * sid, BOOL isgroup) -{ - TDB_DATA key, data; - fstring keystr; - BOOL result = False; - - slprintf(keystr, sizeof(keystr), "%s %d", isgroup ? "GID" : "UID", - id); - - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - data = tdb_fetch(idmap_tdb, key); - - if (data.dptr) { - result = string_to_sid(sid, data.dptr); - SAFE_FREE(data.dptr); - } - - return result; -} - -/* Get an id from a sid */ -static BOOL tdb_get_id_from_sid(DOM_SID * sid, uid_t * id, BOOL isgroup) -{ - TDB_DATA data, key; - fstring keystr; - BOOL result = False; - - /* Check if sid is present in database */ - sid_to_string(keystr, sid); - - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - data = tdb_fetch(idmap_tdb, key); - - if (data.dptr) { - fstring scanstr; - int the_id; - - /* Parse and return existing uid */ - fstrcpy(scanstr, isgroup ? "GID" : "UID"); - fstrcat(scanstr, " %d"); - - if (sscanf(data.dptr, scanstr, &the_id) == 1) { - /* Store uid */ - if (id) { - *id = the_id; - } - - result = True; - } - - SAFE_FREE(data.dptr); - } else { - - /* Allocate a new id for this sid */ - if (id && tdb_allocate_id(id, isgroup)) { - fstring keystr2; - - /* Store new id */ - slprintf(keystr2, sizeof(keystr2), "%s %d", - isgroup ? "GID" : "UID", *id); - - data.dptr = keystr2; - data.dsize = strlen(keystr2) + 1; - - tdb_store(idmap_tdb, key, data, TDB_REPLACE); - tdb_store(idmap_tdb, data, key, TDB_REPLACE); - - result = True; - } - } - - return result; -} - -/***************************************************************************** - Initialise idmap database. -*****************************************************************************/ -static BOOL tdb_idmap_init(void) -{ - /* Open tdb cache */ - if (!(idmap_tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0, - TDB_DEFAULT, O_RDWR | O_CREAT, - 0600))) { - DEBUG(0, - ("winbindd_idmap_init: Unable to open idmap database\n")); - return False; - } - - /* possibly convert from an earlier version */ - if (!tdb_idmap_convert(lock_path("winbindd_idmap.tdb"))) { - DEBUG(0, - ("winbindd_idmap_init: Unable to open idmap database\n")); - return False; - } - - /* Create high water marks for group and user id */ - if (tdb_fetch_int32(idmap_tdb, HWM_USER) == -1) { - if (tdb_store_int32 - (idmap_tdb, HWM_USER, server_state.uid_low) == -1) { - DEBUG(0, - ("winbindd_idmap_init: Unable to initialise user hwm in idmap database\n")); - return False; - } - } - - if (tdb_fetch_int32(idmap_tdb, HWM_GROUP) == -1) { - if (tdb_store_int32 - (idmap_tdb, HWM_GROUP, server_state.gid_low) == -1) { - DEBUG(0, - ("winbindd_idmap_init: Unable to initialise group hwm in idmap database\n")); - return False; - } - } - - return True; -} - -/* Get a sid from a uid */ -static BOOL tdb_get_sid_from_uid(uid_t uid, DOM_SID * sid) -{ - return tdb_get_sid_from_id((int) uid, sid, False); -} - -/* Get a sid from a gid */ -static BOOL tdb_get_sid_from_gid(gid_t gid, DOM_SID * sid) -{ - return tdb_get_sid_from_id((int) gid, sid, True); -} - -/* Get a uid from a sid */ -static BOOL tdb_get_uid_from_sid(DOM_SID * sid, uid_t * uid) -{ - return tdb_get_id_from_sid(sid, uid, False); -} - -/* Get a gid from a group sid */ -static BOOL tdb_get_gid_from_sid(DOM_SID * sid, gid_t * gid) -{ - return tdb_get_id_from_sid(sid, gid, True); -} - -/* Close the tdb */ -static BOOL tdb_idmap_close(void) -{ - if (idmap_tdb) - return (tdb_close(idmap_tdb) == 0); - return True; -} - - -/* Dump status information to log file. Display different stuff based on - the debug level: - - Debug Level Information Displayed - ================================================================= - 0 Percentage of [ug]id range allocated - 0 High water marks (next allocated ids) -*/ - -#define DUMP_INFO 0 - -static void tdb_idmap_status(void) -{ - int user_hwm, group_hwm; - - DEBUG(0, ("winbindd idmap status:\n")); - - /* Get current high water marks */ - - if ((user_hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) { - DEBUG(DUMP_INFO, - ("\tCould not get userid high water mark!\n")); - } - - if ((group_hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) { - DEBUG(DUMP_INFO, - ("\tCould not get groupid high water mark!\n")); - } - - /* Display next ids to allocate */ - - if (user_hwm != -1) { - DEBUG(DUMP_INFO, - ("\tNext userid to allocate is %d\n", user_hwm)); - } - - if (group_hwm != -1) { - DEBUG(DUMP_INFO, - ("\tNext groupid to allocate is %d\n", group_hwm)); - } - - /* Display percentage of id range already allocated. */ - - if (user_hwm != -1) { - int num_users = user_hwm - server_state.uid_low; - int total_users = - server_state.uid_high - server_state.uid_low; - - DEBUG(DUMP_INFO, - ("\tUser id range is %d%% full (%d of %d)\n", - num_users * 100 / total_users, num_users, - total_users)); - } - - if (group_hwm != -1) { - int num_groups = group_hwm - server_state.gid_low; - int total_groups = - server_state.gid_high - server_state.gid_low; - - DEBUG(DUMP_INFO, - ("\tGroup id range is %d%% full (%d of %d)\n", - num_groups * 100 / total_groups, num_groups, - total_groups)); - } - - /* Display complete mapping of users and groups to rids */ -} - -struct idmap_methods tdb_idmap_methods = { - tdb_idmap_init, - - tdb_get_sid_from_uid, - tdb_get_sid_from_gid, - - tdb_get_uid_from_sid, - tdb_get_gid_from_sid, - - tdb_idmap_close, - - tdb_idmap_status -}; - -BOOL winbind_idmap_reg_tdb(struct idmap_methods **meth) -{ - *meth = &tdb_idmap_methods; - - return True; -} diff --git a/source4/nsswitch/winbindd_misc.c b/source4/nsswitch/winbindd_misc.c deleted file mode 100644 index b85cd0570d..0000000000 --- a/source4/nsswitch/winbindd_misc.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - miscellaneous other functions - - Copyright (C) Tim Potter 2000 - Copyright (C) Andrew Bartlett 2002 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Check the machine account password is valid */ - -enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *state) -{ - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uchar trust_passwd[16]; - int num_retries = 0; - struct cli_state *cli; - DEBUG(3, ("[%5d]: check machine account\n", state->pid)); - - /* Get trust account password */ - - again: - if (!secrets_fetch_trust_account_password( - lp_workgroup(), trust_passwd, NULL)) { - result = NT_STATUS_INTERNAL_ERROR; - goto done; - } - - /* This call does a cli_nt_setup_creds() which implicitly checks - the trust account password. */ - - /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, &cli); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(3, ("could not open handle to NETLOGON pipe\n")); - goto done; - } - - /* There is a race condition between fetching the trust account - password and the periodic machine password change. So it's - possible that the trust account password has been changed on us. - We are returned NT_STATUS_ACCESS_DENIED if this happens. */ - -#define MAX_RETRIES 8 - - if ((num_retries < MAX_RETRIES) && - NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) { - num_retries++; - goto again; - } - - /* Pass back result code - zero for success, other values for - specific failures. */ - - DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(result) ? - "good" : "bad")); - - done: - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - fstrcpy(state->response.data.auth.error_string, nt_errstr(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); - - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n", - state->response.data.auth.nt_status_string)); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state - *state) -{ - struct winbindd_domain *domain; - int total_entries = 0, extra_data_len = 0; - char *ted, *extra_data = NULL; - - DEBUG(3, ("[%5d]: list trusted domains\n", state->pid)); - - /* We need to refresh the trusted domain list as the domains may - have changed since we last looked. There may be a sequence - number or something we should use but I haven't found it yet. */ - - if (!init_domain_list()) { - DEBUG(1, ("winbindd_list_trusted_domains: could not " - "refresh trusted domain list\n")); - return WINBINDD_ERROR; - } - - for(domain = domain_list(); domain; domain = domain->next) { - - /* Skip own domain */ - - if (strequal(domain->name, lp_workgroup())) continue; - - /* Add domain to list */ - - total_entries++; - ted = Realloc(extra_data, sizeof(fstring) * - total_entries); - - if (!ted) { - DEBUG(0,("winbindd_list_trusted_domains: failed to enlarge buffer!\n")); - SAFE_FREE(extra_data); - return WINBINDD_ERROR; - } else - extra_data = ted; - - memcpy(&extra_data[extra_data_len], domain->name, - strlen(domain->name)); - - extra_data_len += strlen(domain->name); - extra_data[extra_data_len++] = ','; - } - - if (extra_data) { - if (extra_data_len > 1) - extra_data[extra_data_len - 1] = '\0'; - state->response.extra_data = extra_data; - state->response.length += extra_data_len; - } - - return WINBINDD_OK; -} - - -enum winbindd_result winbindd_show_sequence(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - char *extra_data = NULL; - - DEBUG(3, ("[%5d]: show sequence\n", state->pid)); - - extra_data = strdup(""); - - /* this makes for a very simple data format, and is easily parsable as well - if that is ever needed */ - for (domain = domain_list(); domain; domain = domain->next) { - char *s; - - domain->methods->sequence_number(domain, &domain->sequence_number); - - if (DOM_SEQUENCE_NONE == (unsigned)domain->sequence_number) { - asprintf(&s,"%s%s : DISCONNECTED\n", extra_data, - domain->name); - } else { - asprintf(&s,"%s%s : %u\n", extra_data, - domain->name, (unsigned)domain->sequence_number); - } - free(extra_data); - extra_data = s; - } - - state->response.extra_data = extra_data; - /* must add one to length to copy the 0 for string termination */ - state->response.length += strlen(extra_data) + 1; - - return WINBINDD_OK; -} - -enum winbindd_result winbindd_ping(struct winbindd_cli_state - *state) -{ - DEBUG(3, ("[%5d]: ping\n", state->pid)); - - return WINBINDD_OK; -} - -/* List various tidbits of information */ - -enum winbindd_result winbindd_info(struct winbindd_cli_state *state) -{ - - DEBUG(3, ("[%5d]: request misc info\n", state->pid)); - - state->response.data.info.winbind_separator = *lp_winbind_separator(); - fstrcpy(state->response.data.info.samba_version, VERSION); - - return WINBINDD_OK; -} - -/* Tell the client the current interface version */ - -enum winbindd_result winbindd_interface_version(struct winbindd_cli_state *state) -{ - - DEBUG(3, ("[%5d]: request interface version\n", state->pid)); - - state->response.data.interface_version = WINBIND_INTERFACE_VERSION; - - return WINBINDD_OK; -} - -/* What domain are we a member of? */ - -enum winbindd_result winbindd_domain_name(struct winbindd_cli_state *state) -{ - - DEBUG(3, ("[%5d]: request domain name\n", state->pid)); - - fstrcpy(state->response.data.domain_name, lp_workgroup()); - - return WINBINDD_OK; -} - -/* What's my name again? */ - -enum winbindd_result winbindd_netbios_name(struct winbindd_cli_state *state) -{ - - DEBUG(3, ("[%5d]: request netbios name\n", state->pid)); - - fstrcpy(state->response.data.netbios_name, lp_netbios_name()); - - return WINBINDD_OK; -} diff --git a/source4/nsswitch/winbindd_nss.h b/source4/nsswitch/winbindd_nss.h deleted file mode 100644 index 2c87a77100..0000000000 --- a/source4/nsswitch/winbindd_nss.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - 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 7 - -/* 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 */ - - /* WINS commands */ - - WINBINDD_WINS_BYIP, - WINBINDD_WINS_BYNAME, - - /* this is like GETGRENT but gives an empty group list */ - WINBINDD_GETGRLST, - - WINBINDD_NETBIOS_NAME, /* The netbios name of the server */ - /* Placeholder for end of cmd list */ - - WINBINDD_NUM_CMDS -}; - -#define WINBIND_PAM_INFO3_NDR 0x0001 -#define WINBIND_PAM_INFO3_TEXT 0x0002 -#define WINBIND_PAM_NTKEY 0x0004 -#define WINBIND_PAM_LMKEY 0x0008 -#define WINBIND_PAM_CONTACT_TRUSTDOM 0x0010 - -/* 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 winsreq; /* WINS request */ - fstring username; /* getpwnam */ - fstring groupname; /* getgrnam */ - uid_t uid; /* getpwuid, uid_to_sid */ - gid_t gid; /* getgrgid, gid_to_sid */ - struct { - /* We deliberatedly don't split into domain/user to - avoid having the client know what the separator - character is. */ - 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; - fstring workstation; - uint32 flags; - } 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; - char null_term; -}; - -/* 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... */ - - fstring winsresp; /* WINS response */ - - /* 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; - fstring netbios_name; - - struct auth_reply { - uint32 nt_status; - fstring nt_status_string; - fstring error_string; - int pam_error; - char nt_session_key[16]; - char first_8_lm_hash[8]; - } auth; - } data; - - /* Variable length return data */ - - void *extra_data; /* getgrnam, getgrgid, getgrent */ -}; - -#endif diff --git a/source4/nsswitch/winbindd_pam.c b/source4/nsswitch/winbindd_pam.c deleted file mode 100644 index 8a0326b42c..0000000000 --- a/source4/nsswitch/winbindd_pam.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - pam auth funcions - - Copyright (C) Andrew Tridgell 2000 - Copyright (C) Tim Potter 2001 - Copyright (C) Andrew Bartlett 2001-2002 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - - -static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, - struct winbindd_cli_state *state, - NET_USER_INFO_3 *info3) -{ - prs_struct ps; - uint32 size; - if (!prs_init(&ps, 256 /* Random, non-zero number */, mem_ctx, MARSHALL)) { - return NT_STATUS_NO_MEMORY; - } - if (!net_io_user_info3("", info3, &ps, 1, 3)) { - prs_mem_free(&ps); - return NT_STATUS_UNSUCCESSFUL; - } - - size = prs_data_size(&ps); - state->response.extra_data = malloc(size); - if (!state->response.extra_data) { - prs_mem_free(&ps); - return NT_STATUS_NO_MEMORY; - } - prs_copy_all_data_out(state->response.extra_data, &ps); - state->response.length += size; - prs_mem_free(&ps); - return NT_STATUS_OK; -} - -/* Return a password structure from a username. */ - -enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) -{ - NTSTATUS result; - fstring name_domain, name_user; - unsigned char trust_passwd[16]; - time_t last_change_time; - uint32 smb_uid_low; - NET_USER_INFO_3 info3; - struct cli_state *cli = NULL; - uchar chal[8]; - TALLOC_CTX *mem_ctx = NULL; - DATA_BLOB lm_resp; - DATA_BLOB nt_resp; - - /* Ensure null termination */ - state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; - - /* Ensure null termination */ - state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0'; - - DEBUG(3, ("[%5d]: pam auth %s\n", state->pid, - state->request.data.auth.user)); - - if (!(mem_ctx = talloc_init("winbind pam auth for %s", state->request.data.auth.user))) { - DEBUG(0, ("winbindd_pam_auth: could not talloc_init()!\n")); - result = NT_STATUS_NO_MEMORY; - goto done; - } - - /* Parse domain and username */ - - if (!parse_domain_user(state->request.data.auth.user, name_domain, - name_user)) { - DEBUG(5,("no domain separator (%s) in username (%s) - failing auth\n", lp_winbind_separator(), state->request.data.auth.user)); - result = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - { - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - - generate_random_buffer(chal, 8, False); - SMBencrypt(state->request.data.auth.pass, chal, local_lm_response); - - SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response); - - lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response)); - nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response)); - } - - /* - * Get the machine account password for our primary domain - */ - - if (!secrets_fetch_trust_account_password( - lp_workgroup(), trust_passwd, &last_change_time)) { - DEBUG(0, ("winbindd_pam_auth: could not fetch trust account " - "password for domain %s\n", lp_workgroup())); - result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - goto done; - } - - /* We really don't care what LUID we give the user. */ - - generate_random_buffer( (unsigned char *)&smb_uid_low, 4, False); - - ZERO_STRUCT(info3); - - /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, &cli); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(3, ("could not open handle to NETLOGON pipe\n")); - goto done; - } - - result = cli_netlogon_sam_network_logon(cli, mem_ctx, - name_user, name_domain, - lp_netbios_name(), chal, - lm_resp, nt_resp, - &info3); - - uni_group_cache_store_netlogon(mem_ctx, &info3); -done: - - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); - - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", - state->request.data.auth.user, - state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); - - if (mem_ctx) - talloc_destroy(mem_ctx); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -/* Challenge Response Authentication Protocol */ - -enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) -{ - NTSTATUS result; - unsigned char trust_passwd[16]; - time_t last_change_time; - NET_USER_INFO_3 info3; - struct cli_state *cli = NULL; - TALLOC_CTX *mem_ctx = NULL; - char *user = NULL; - const char *domain = NULL; - const char *contact_domain; - const char *workstation; - - DATA_BLOB lm_resp, nt_resp; - - /* Ensure null termination */ - state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]='\0'; - - /* Ensure null termination */ - state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]='\0'; - - if (!(mem_ctx = talloc_init("winbind pam auth crap for (utf8) %s", state->request.data.auth_crap.user))) { - DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n")); - result = NT_STATUS_NO_MEMORY; - goto done; - } - - if (pull_utf8_talloc(mem_ctx, &user, state->request.data.auth_crap.user) == (size_t)-1) { - DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); - } - - if (*state->request.data.auth_crap.domain) { - char *dom = NULL; - if (pull_utf8_talloc(mem_ctx, &dom, state->request.data.auth_crap.domain) == (size_t)-1) { - DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); - } - domain = dom; - } else if (lp_winbind_use_default_domain()) { - domain = lp_workgroup(); - } else { - DEBUG(5,("no domain specified with username (%s) - failing auth\n", - user)); - result = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state->pid, - domain, user)); - - if (lp_allow_trusted_domains() && (state->request.data.auth_crap.flags & WINBIND_PAM_CONTACT_TRUSTDOM)) { - contact_domain = domain; - } else { - contact_domain = lp_workgroup(); - } - - if (*state->request.data.auth_crap.workstation) { - char *wrk = NULL; - if (pull_utf8_talloc(mem_ctx, &wrk, state->request.data.auth_crap.workstation) == (size_t)-1) { - DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); - } - workstation = wrk; - } else { - workstation = lp_netbios_name(); - } - - if (state->request.data.auth_crap.lm_resp_len > sizeof(state->request.data.auth_crap.lm_resp) - || state->request.data.auth_crap.nt_resp_len > sizeof(state->request.data.auth_crap.nt_resp)) { - DEBUG(0, ("winbindd_pam_auth_crap: invalid password length %u/%u\n", - state->request.data.auth_crap.lm_resp_len, - state->request.data.auth_crap.nt_resp_len)); - result = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - lm_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len); - nt_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len); - - /* - * Get the machine account password for the domain to contact. - * This is either our own domain for a workstation, or possibly - * any domain for a PDC with trusted domains. - */ - - if (!secrets_fetch_trust_account_password ( - contact_domain, trust_passwd, &last_change_time)) { - DEBUG(0, ("winbindd_pam_auth: could not fetch trust account " - "password for domain %s\n", contact_domain)); - result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - goto done; - } - - ZERO_STRUCT(info3); - - /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(contact_domain, trust_passwd, &cli); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", nt_errstr(result))); - goto done; - } - - result = cli_netlogon_sam_network_logon(cli, mem_ctx, - user, domain, - workstation, state->request.data.auth_crap.chal, - lm_resp, nt_resp, - &info3); - - if (NT_STATUS_IS_OK(result)) { - uni_group_cache_store_netlogon(mem_ctx, &info3); - if (state->request.data.auth_crap.flags & WINBIND_PAM_INFO3_NDR) { - result = append_info3_as_ndr(mem_ctx, state, &info3); - } - -#if 0 - /* we don't currently do this stuff right */ - /* Doing an assert in a daemon is going to be a pretty bad - idea. - tpot */ - if (state->request.data.auth_crap.flags & WINBIND_PAM_NTKEY) { - SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) == sizeof(info3.user_sess_key)); - memcpy(state->response.data.auth.nt_session_key, info3.user_sess_key, sizeof(state->response.data.auth.nt_session_key) /* 16 */); - } - if (state->request.data.auth_crap.flags & WINBIND_PAM_LMKEY) { - SMB_ASSERT(sizeof(state->response.data.auth.nt_session_key) <= sizeof(info3.user_sess_key)); - memcpy(state->response.data.auth.first_8_lm_hash, info3.padding, sizeof(state->response.data.auth.nt_session_key) /* 16 */); - } -#endif - } - -done: - - state->response.data.auth.nt_status = NT_STATUS_V(result); - push_utf8_fstring(state->response.data.auth.nt_status_string, nt_errstr(result)); - push_utf8_fstring(state->response.data.auth.error_string, nt_errstr(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); - - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, - ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", - domain, - user, - state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); - - if (mem_ctx) - talloc_destroy(mem_ctx); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} - -/* Change a user password */ - -enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state) -{ - NTSTATUS result; - char *oldpass, *newpass; - fstring domain, user; - CLI_POLICY_HND *hnd; - - DEBUG(3, ("[%5d]: pam chauthtok %s\n", state->pid, - state->request.data.chauthtok.user)); - - /* Setup crap */ - - if (state == NULL) - return WINBINDD_ERROR; - - if (!parse_domain_user(state->request.data.chauthtok.user, domain, - user)) { - result = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - /* Change password */ - - oldpass = state->request.data.chauthtok.oldpass; - newpass = state->request.data.chauthtok.newpass; - - /* Get sam handle */ - - if (!(hnd = cm_get_sam_handle(domain))) { - DEBUG(1, ("could not get SAM handle on DC for %s\n", domain)); - result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - goto done; - } - - if (!cli_oem_change_password(hnd->cli, user, newpass, oldpass)) { - DEBUG(1, ("password change failed for user %s/%s\n", domain, - user)); - result = NT_STATUS_WRONG_PASSWORD; - } else { - result = NT_STATUS_OK; - } - -done: - state->response.data.auth.nt_status = NT_STATUS_V(result); - fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - fstrcpy(state->response.data.auth.error_string, nt_errstr(result)); - state->response.data.auth.pam_error = nt_status_to_pam(result); - - DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, - ("Password change for user [%s]\\[%s] returned %s (PAM: %d)\n", - domain, - user, - state->response.data.auth.nt_status_string, - state->response.data.auth.pam_error)); - - return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; -} diff --git a/source4/nsswitch/winbindd_rpc.c b/source4/nsswitch/winbindd_rpc.c deleted file mode 100644 index 9989f27109..0000000000 --- a/source4/nsswitch/winbindd_rpc.c +++ /dev/null @@ -1,776 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind rpc backend functions - - Copyright (C) Tim Potter 2000-2001,2003 - Copyright (C) Andrew Tridgell 2001 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - - -/* Query display info for a domain. This returns enough information plus a - bit extra to give an overview of domain users for the User Manager - application. */ -static NTSTATUS query_user_list(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - WINBIND_USERINFO **info) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - POLICY_HND dom_pol; - BOOL got_dom_pol = False; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - unsigned int i, start_idx, retry; - - DEBUG(3,("rpc: query_user_list\n")); - - *num_entries = 0; - *info = NULL; - - retry = 0; - do { - /* Get sam handle */ - - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - i = start_idx = 0; - do { - TALLOC_CTX *ctx2; - char **dom_users; - uint32 num_dom_users, *dom_rids, j, size = 0xffff; - uint16 acb_mask = ACB_NORMAL; - - if (!(ctx2 = talloc_init("winbindd enum_users"))) { - result = NT_STATUS_NO_MEMORY; - goto done; - } - - result = cli_samr_enum_dom_users( - hnd->cli, ctx2, &dom_pol, &start_idx, acb_mask, - size, &dom_users, &dom_rids, &num_dom_users); - - *num_entries += num_dom_users; - - *info = talloc_realloc( - mem_ctx, *info, - (*num_entries) * sizeof(WINBIND_USERINFO)); - - if (!(*info)) { - result = NT_STATUS_NO_MEMORY; - talloc_destroy(ctx2); - goto done; - } - - for (j = 0; j < num_dom_users; i++, j++) { - (*info)[i].acct_name = - talloc_strdup(mem_ctx, dom_users[j]); - (*info)[i].full_name = talloc_strdup(mem_ctx, ""); - (*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, dom_rids[j]); - /* For the moment we set the primary group for - every user to be the Domain Users group. - There are serious problems with determining - the actual primary group for large domains. - This should really be made into a 'winbind - force group' smb.conf parameter or - something like that. */ - (*info)[i].group_sid - = rid_to_talloced_sid(domain, - mem_ctx, - DOMAIN_GROUP_RID_USERS); - } - - talloc_destroy(ctx2); - - } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); - - done: - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return result; -} - -/* list all domain groups */ -static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - CLI_POLICY_HND *hnd; - POLICY_HND dom_pol; - NTSTATUS status; - uint32 start = 0; - int retry; - - *num_entries = 0; - *info = NULL; - - DEBUG(3,("rpc: enum_dom_groups\n")); - - retry = 0; - do { - if (!(hnd = cm_get_sam_handle(domain->name))) - return NT_STATUS_UNSUCCESSFUL; - - status = cli_samr_open_domain(hnd->cli, mem_ctx, - &hnd->pol, des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(status)) - return status; - - do { - struct acct_info *info2 = NULL; - uint32 count = 0; - TALLOC_CTX *mem_ctx2; - - mem_ctx2 = talloc_init("enum_dom_groups[rpc]"); - - /* start is updated by this call. */ - status = cli_samr_enum_dom_groups(hnd->cli, mem_ctx2, &dom_pol, - &start, - 0xFFFF, /* buffer size? */ - &info2, &count); - - if (!NT_STATUS_IS_OK(status) && - !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { - talloc_destroy(mem_ctx2); - break; - } - - (*info) = talloc_realloc(mem_ctx, *info, - sizeof(**info) * ((*num_entries) + count)); - if (! *info) { - talloc_destroy(mem_ctx2); - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - return NT_STATUS_NO_MEMORY; - } - - memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2)); - (*num_entries) += count; - talloc_destroy(mem_ctx2); - } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)); - - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return status; -} - -/* List all domain groups */ - -static NTSTATUS enum_local_groups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_entries, - struct acct_info **info) -{ - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - CLI_POLICY_HND *hnd; - POLICY_HND dom_pol; - NTSTATUS result; - int retry; - - *num_entries = 0; - *info = NULL; - - retry = 0; - do { - if ( !(hnd = cm_get_sam_handle(domain->name)) ) - return NT_STATUS_UNSUCCESSFUL; - - result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if ( !NT_STATUS_IS_OK(result)) - return result; - - do { - struct acct_info *info2 = NULL; - uint32 count = 0, start = *num_entries; - TALLOC_CTX *mem_ctx2; - - mem_ctx2 = talloc_init("enum_dom_local_groups[rpc]"); - - result = cli_samr_enum_als_groups( hnd->cli, mem_ctx2, &dom_pol, - &start, 0xFFFF, &info2, &count); - - if ( !NT_STATUS_IS_OK(result) - && !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES) ) - { - talloc_destroy(mem_ctx2); - break; - } - - (*info) = talloc_realloc(mem_ctx, *info, - sizeof(**info) * ((*num_entries) + count)); - if (! *info) { - talloc_destroy(mem_ctx2); - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - return NT_STATUS_NO_MEMORY; - } - - memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2)); - (*num_entries) += count; - talloc_destroy(mem_ctx2); - } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); - - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return result; -} - -/* convert a single name to a sid in a domain */ -static NTSTATUS name_to_sid(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - const char *name, - DOM_SID *sid, - enum SID_NAME_USE *type) -{ - CLI_POLICY_HND *hnd; - NTSTATUS status; - DOM_SID *sids = NULL; - uint32 *types = NULL; - const char *full_name; - int retry; - - DEBUG(3,("rpc: name_to_sid name=%s\n", name)); - - full_name = talloc_asprintf(mem_ctx, "%s\\%s", domain->name, name); - - if (!full_name) { - DEBUG(0, ("talloc_asprintf failed!\n")); - return NT_STATUS_NO_MEMORY; - } - - retry = 0; - do { - if (!(hnd = cm_get_lsa_handle(domain->name))) { - return NT_STATUS_UNSUCCESSFUL; - } - - status = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1, - &full_name, &sids, &types); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - /* Return rid and type if lookup successful */ - - if (NT_STATUS_IS_OK(status)) { - sid_copy(sid, &sids[0]); - *type = types[0]; - } - - return status; -} - -/* - convert a domain SID to a user or group name -*/ -static NTSTATUS sid_to_name(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, - char **name, - enum SID_NAME_USE *type) -{ - CLI_POLICY_HND *hnd; - char **domains; - char **names; - uint32 *types; - NTSTATUS status; - int retry; - - DEBUG(3,("rpc: sid_to_name\n")); - - retry = 0; - do { - if (!(hnd = cm_get_lsa_handle(domain->name))) - return NT_STATUS_UNSUCCESSFUL; - - status = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol, - 1, sid, &domains, &names, &types); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (NT_STATUS_IS_OK(status)) { - *type = types[0]; - *name = names[0]; - DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name)); - - /* Paranoia */ - if (strcasecmp(domain->name, domains[0]) != 0) { - DEBUG(1, ("domain name from domain param and PDC lookup return differ! (%s vs %s)\n", domain->name, domains[0])); - return NT_STATUS_UNSUCCESSFUL; - } - } - return status; -} - -/* Lookup user information from a rid or username. */ -static NTSTATUS query_user(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - WINBIND_USERINFO *user_info) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - POLICY_HND dom_pol, user_pol; - BOOL got_dom_pol = False, got_user_pol = False; - SAM_USERINFO_CTR *ctr; - int retry; - fstring sid_string; - uint32 user_rid; - - DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid))); - if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) { - goto done; - } - - retry = 0; - do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - SEC_RIGHTS_MAXIMUM_ALLOWED, - &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - /* Get user handle */ - result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol, - SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_user_pol = True; - - /* Get user info */ - result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol, - 0x15, &ctr); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - cli_samr_close(hnd->cli, mem_ctx, &user_pol); - got_user_pol = False; - - user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid); - user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid); - user_info->acct_name = unistr2_tdup(mem_ctx, - &ctr->info.id21->uni_user_name); - user_info->full_name = unistr2_tdup(mem_ctx, - &ctr->info.id21->uni_full_name); - - done: - /* Clean up policy handles */ - if (got_user_pol) - cli_samr_close(hnd->cli, mem_ctx, &user_pol); - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return result; -} - -/* Lookup groups a user is a member of. I wish Unix had a call like this! */ -static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *user_sid, - uint32 *num_groups, DOM_SID ***user_gids) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - POLICY_HND dom_pol, user_pol; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - BOOL got_dom_pol = False, got_user_pol = False; - DOM_GID *user_groups; - unsigned int i; - unsigned int retry; - fstring sid_string; - uint32 user_rid; - - DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid))); - - *num_groups = 0; - - /* First try cached universal groups from logon */ - *user_gids = uni_group_cache_fetch(&domain->sid, user_sid, mem_ctx, num_groups); - if((*num_groups > 0) && *user_gids) { - return NT_STATUS_OK; - } else { - *user_gids = NULL; - *num_groups = 0; - } - - retry = 0; - do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - - if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) { - goto done; - } - - /* Get user handle */ - result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol, - des_access, user_rid, &user_pol); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_user_pol = True; - - /* Query user rids */ - result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol, - num_groups, &user_groups); - - if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0) - goto done; - - (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups)); - if (!(*user_gids)) { - result = NT_STATUS_NO_MEMORY; - goto done; - } - - for (i=0;i<(*num_groups);i++) { - (*user_gids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid); - } - - done: - /* Clean up policy handles */ - if (got_user_pol) - cli_samr_close(hnd->cli, mem_ctx, &user_pol); - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return result; -} - - -/* Lookup group membership given a rid. */ -static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - DOM_SID *group_sid, uint32 *num_names, - DOM_SID ***sid_mem, char ***names, - uint32 **name_types) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uint32 i, total_names = 0; - POLICY_HND dom_pol, group_pol; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - BOOL got_dom_pol = False, got_group_pol = False; - uint32 *rid_mem = NULL; - uint32 group_rid; - int retry; - unsigned int j; - fstring sid_string; - - DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid))); - - if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) { - goto done; - } - - *num_names = 0; - - retry = 0; - do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - /* Get group handle */ - - result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol, - des_access, group_rid, &group_pol); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_group_pol = True; - - /* Step #1: Get a list of user rids that are the members of the - group. */ - - result = cli_samr_query_groupmem(hnd->cli, mem_ctx, - &group_pol, num_names, &rid_mem, - name_types); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - /* Step #2: Convert list of rids into list of usernames. Do this - in bunches of ~1000 to avoid crashing NT4. It looks like there - is a buffer overflow or something like that lurking around - somewhere. */ - -#define MAX_LOOKUP_RIDS 900 - - *names = talloc_zero(mem_ctx, *num_names * sizeof(char *)); - *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32)); - *sid_mem = talloc_zero(mem_ctx, *num_names * sizeof(DOM_SID *)); - - for (j=0;j<(*num_names);j++) { - (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]); - } - - if (!*names || !*name_types) { - result = NT_STATUS_NO_MEMORY; - goto done; - } - - for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { - int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); - uint32 tmp_num_names = 0; - char **tmp_names = NULL; - uint32 *tmp_types = NULL; - - /* Lookup a chunk of rids */ - - result = cli_samr_lookup_rids(hnd->cli, mem_ctx, - &dom_pol, 1000, /* flags */ - num_lookup_rids, - &rid_mem[i], - &tmp_num_names, - &tmp_names, &tmp_types); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - /* Copy result into array. The talloc system will take - care of freeing the temporary arrays later on. */ - - memcpy(&(*names)[i], tmp_names, sizeof(char *) * - tmp_num_names); - - memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * - tmp_num_names); - - total_names += tmp_num_names; - } - - *num_names = total_names; - - done: - if (got_group_pol) - cli_samr_close(hnd->cli, mem_ctx, &group_pol); - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - return result; -} - -/* find the sequence number for a domain */ -static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) -{ - TALLOC_CTX *mem_ctx; - CLI_POLICY_HND *hnd; - SAM_UNK_CTR ctr; - uint16 switch_value = 2; - NTSTATUS result; - uint32 seqnum = DOM_SEQUENCE_NONE; - POLICY_HND dom_pol; - BOOL got_dom_pol = False; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - int retry; - - DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name)); - - *seq = DOM_SEQUENCE_NONE; - - if (!(mem_ctx = talloc_init("sequence_number[rpc]"))) - return NT_STATUS_NO_MEMORY; - - retry = 0; - do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; - - /* Get domain handle */ - result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, - des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - got_dom_pol = True; - - /* Query domain info */ - - result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol, - switch_value, &ctr); - - if (NT_STATUS_IS_OK(result)) { - seqnum = ctr.info.inf2.seq_num; - DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)seqnum )); - } else { - DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n", - (unsigned)seqnum, domain->name )); - } - - done: - - if (got_dom_pol) - cli_samr_close(hnd->cli, mem_ctx, &dom_pol); - - talloc_destroy(mem_ctx); - - *seq = seqnum; - - return result; -} - -/* get a list of trusted domains */ -static NTSTATUS trusted_domains(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 *num_domains, - char ***names, - char ***alt_names, - DOM_SID **dom_sids) -{ - CLI_POLICY_HND *hnd; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uint32 enum_ctx = 0; - int retry; - - DEBUG(3,("rpc: trusted_domains\n")); - - *num_domains = 0; - *alt_names = NULL; - - retry = 0; - do { - if (!(hnd = cm_get_lsa_handle(lp_workgroup()))) - goto done; - - result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx, - &hnd->pol, &enum_ctx, - num_domains, names, dom_sids); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - -done: - return result; -} - -/* find the domain sid for a domain */ -static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) -{ - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - TALLOC_CTX *mem_ctx; - CLI_POLICY_HND *hnd; - fstring level5_dom; - int retry; - - DEBUG(3,("rpc: domain_sid\n")); - - if (!(mem_ctx = talloc_init("domain_sid[rpc]"))) - return NT_STATUS_NO_MEMORY; - - retry = 0; - do { - /* Get sam handle */ - if (!(hnd = cm_get_lsa_handle(domain->name))) - goto done; - - status = cli_lsa_query_info_policy(hnd->cli, mem_ctx, - &hnd->pol, 0x05, level5_dom, sid); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); - -done: - talloc_destroy(mem_ctx); - return status; -} - -/* find alternate names list for the domain - none for rpc */ -static NTSTATUS alternate_name(struct winbindd_domain *domain) -{ - return NT_STATUS_OK; -} - - -/* the rpc backend methods are exposed via this structure */ -struct winbindd_methods msrpc_methods = { - False, - query_user_list, - enum_dom_groups, - enum_local_groups, - name_to_sid, - sid_to_name, - query_user, - lookup_usergroups, - lookup_groupmem, - sequence_number, - trusted_domains, - domain_sid, - alternate_name -}; diff --git a/source4/nsswitch/winbindd_sid.c b/source4/nsswitch/winbindd_sid.c deleted file mode 100644 index 6ab2eaa646..0000000000 --- a/source4/nsswitch/winbindd_sid.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - sid related functions - - Copyright (C) Tim Potter 2000 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Convert a string */ - -enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state) -{ - extern DOM_SID global_sid_Builtin; - enum SID_NAME_USE type; - DOM_SID sid, tmp_sid; - uint32 rid; - fstring name; - fstring dom_name; - - /* Ensure null termination */ - state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; - - DEBUG(3, ("[%5d]: lookupsid %s\n", state->pid, - state->request.data.sid)); - - /* Lookup sid from PDC using lsa_lookup_sids() */ - - if (!string_to_sid(&sid, state->request.data.sid)) { - DEBUG(5, ("%s not a SID\n", state->request.data.sid)); - return WINBINDD_ERROR; - } - - /* Don't look up BUILTIN sids */ - - sid_copy(&tmp_sid, &sid); - sid_split_rid(&tmp_sid, &rid); - - if (sid_equal(&tmp_sid, &global_sid_Builtin)) { - return WINBINDD_ERROR; - } - - /* Lookup the sid */ - - if (!winbindd_lookup_name_by_sid(&sid, dom_name, name, &type)) { - return WINBINDD_ERROR; - } - - fstrcpy(state->response.data.name.dom_name, dom_name); - fstrcpy(state->response.data.name.name, name); - - state->response.data.name.type = type; - - return WINBINDD_OK; -} - - -/** - * Look up the SID for a qualified name. - **/ -enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state) -{ - enum SID_NAME_USE type; - fstring sid_str; - char *name_domain, *name_user; - DOM_SID sid; - struct winbindd_domain *domain; - - /* Ensure null termination */ - state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0'; - - /* Ensure null termination */ - state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0'; - - DEBUG(3, ("[%5d]: lookupname %s%s%s\n", state->pid, - state->request.data.name.dom_name, - lp_winbind_separator(), - state->request.data.name.name)); - - name_domain = state->request.data.name.dom_name; - name_user = state->request.data.name.name; - - if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(0, ("could not find domain entry for domain %s\n", - name_domain)); - return WINBINDD_ERROR; - } - - /* Lookup name from PDC using lsa_lookup_names() */ - if (!winbindd_lookup_sid_by_name(domain, name_user, &sid, &type)) { - return WINBINDD_ERROR; - } - - sid_to_string(sid_str, &sid); - fstrcpy(state->response.data.sid.sid, sid_str); - state->response.data.sid.type = type; - - return WINBINDD_OK; -} - -/* Convert a sid to a uid. We assume we only have one rid attached to the - sid. */ - -enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) -{ - DOM_SID sid; - - /* Ensure null termination */ - state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; - - DEBUG(3, ("[%5d]: sid to uid %s\n", state->pid, - state->request.data.sid)); - - /* Split sid into domain sid and user rid */ - if (!string_to_sid(&sid, state->request.data.sid)) { - DEBUG(1, ("Could not get convert sid %s from string\n", - state->request.data.sid)); - return WINBINDD_ERROR; - } - - /* Find uid for this sid and return it */ - if (!winbindd_idmap_get_uid_from_sid(&sid, &state->response.data.uid)) { - DEBUG(1, ("Could not get uid for sid %s\n", - state->request.data.sid)); - return WINBINDD_ERROR; - } - - return WINBINDD_OK; -} - -/* Convert a sid to a gid. We assume we only have one rid attached to the - sid.*/ - -enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) -{ - DOM_SID sid; - - /* Ensure null termination */ - state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; - - DEBUG(3, ("[%5d]: sid to gid %s\n", state->pid, - state->request.data.sid)); - - if (!string_to_sid(&sid, state->request.data.sid)) { - DEBUG(1, ("Could not cvt string to sid %s\n", - state->request.data.sid)); - return WINBINDD_ERROR; - } - - /* Find gid for this sid and return it */ - if (!winbindd_idmap_get_gid_from_sid(&sid, &state->response.data.gid)) { - DEBUG(1, ("Could not get gid for sid %s\n", - state->request.data.sid)); - return WINBINDD_ERROR; - } - - return WINBINDD_OK; -} - -/* Convert a uid to a sid */ - -enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state) -{ - DOM_SID sid; - - /* Bug out if the uid isn't in the winbind range */ - - if ((state->request.data.uid < server_state.uid_low ) || - (state->request.data.uid > server_state.uid_high)) { - return WINBINDD_ERROR; - } - - DEBUG(3, ("[%5d]: uid to sid %d\n", state->pid, - state->request.data.uid)); - - /* Lookup rid for this uid */ - if (!winbindd_idmap_get_sid_from_uid(state->request.data.uid, &sid)) { - DEBUG(1, ("Could not convert uid %d to rid\n", - state->request.data.uid)); - return WINBINDD_ERROR; - } - - sid_to_string(state->response.data.sid.sid, &sid); - state->response.data.sid.type = SID_NAME_USER; - - return WINBINDD_OK; -} - -/* Convert a gid to a sid */ - -enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state) -{ - DOM_SID sid; - - /* Bug out if the gid isn't in the winbind range */ - - if ((state->request.data.gid < server_state.gid_low) || - (state->request.data.gid > server_state.gid_high)) { - return WINBINDD_ERROR; - } - - DEBUG(3, ("[%5d]: gid to sid %d\n", state->pid, - state->request.data.gid)); - - /* Lookup sid for this uid */ - if (!winbindd_idmap_get_sid_from_gid(state->request.data.gid, &sid)) { - DEBUG(1, ("Could not convert gid %d to sid\n", - state->request.data.gid)); - return WINBINDD_ERROR; - } - - /* Construct sid and return it */ - sid_to_string(state->response.data.sid.sid, &sid); - state->response.data.sid.type = SID_NAME_DOM_GRP; - - return WINBINDD_OK; -} diff --git a/source4/nsswitch/winbindd_user.c b/source4/nsswitch/winbindd_user.c deleted file mode 100644 index ee05543d30..0000000000 --- a/source4/nsswitch/winbindd_user.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - user related functions - - Copyright (C) Tim Potter 2000 - Copyright (C) Jeremy Allison 2001. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Fill a pwent structure with information we have obtained */ - -static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, - DOM_SID *user_sid, DOM_SID *group_sid, - char *full_name, struct winbindd_pw *pw) -{ - extern userdom_struct current_user_info; - fstring output_username; - pstring homedir; - fstring sid_string; - - if (!pw || !dom_name || !user_name) - return False; - - /* Resolve the uid number */ - - if (!winbindd_idmap_get_uid_from_sid(user_sid, - &pw->pw_uid)) { - DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid))); - return False; - } - - /* Resolve the gid number */ - - if (!winbindd_idmap_get_gid_from_sid(group_sid, - &pw->pw_gid)) { - DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid))); - return False; - } - - /* Username */ - - fill_domain_username(output_username, dom_name, user_name); - - safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1); - - /* Full name (gecos) */ - - safe_strcpy(pw->pw_gecos, full_name, sizeof(pw->pw_gecos) - 1); - - /* Home directory and shell - use template config parameters. The - defaults are /tmp for the home directory and /bin/false for - shell. */ - - /* The substitution of %U and %D in the 'template homedir' is done - by lp_string() calling standard_sub_basic(). */ - - fstrcpy(current_user_info.smb_name, user_name); - sub_set_smb_name(user_name); - fstrcpy(current_user_info.domain, dom_name); - - pstrcpy(homedir, lp_template_homedir()); - - safe_strcpy(pw->pw_dir, homedir, sizeof(pw->pw_dir) - 1); - - safe_strcpy(pw->pw_shell, lp_template_shell(), - sizeof(pw->pw_shell) - 1); - - /* Password - set to "x" as we can't generate anything useful here. - Authentication can be done using the pam_winbind module. */ - - safe_strcpy(pw->pw_passwd, "x", sizeof(pw->pw_passwd) - 1); - - return True; -} - -/* Return a password structure from a username. */ - -enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) -{ - WINBIND_USERINFO user_info; - DOM_SID user_sid; - NTSTATUS status; - fstring name_domain, name_user; - enum SID_NAME_USE name_type; - struct winbindd_domain *domain; - TALLOC_CTX *mem_ctx; - - /* Ensure null termination */ - state->request.data.username[sizeof(state->request.data.username)-1]='\0'; - - DEBUG(3, ("[%5d]: getpwnam %s\n", state->pid, - state->request.data.username)); - - /* Parse domain and username */ - - if (!parse_domain_user(state->request.data.username, name_domain, - name_user)) - return WINBINDD_ERROR; - - if ((domain = find_domain_from_name(name_domain)) == NULL) { - DEBUG(5, ("no such domain: %s\n", name_domain)); - return WINBINDD_ERROR; - } - - /* Get rid and name type from name */ - - if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, &name_type)) { - DEBUG(1, ("user '%s' does not exist\n", name_user)); - return WINBINDD_ERROR; - } - - if (name_type != SID_NAME_USER) { - DEBUG(1, ("name '%s' is not a user name: %d\n", name_user, - name_type)); - return WINBINDD_ERROR; - } - - /* Get some user info. Split the user rid from the sid obtained - from the winbind_lookup_by_name() call and use it in a - winbind_lookup_userinfo() */ - - if (!(mem_ctx = talloc_init("winbindd_getpwnam([%s]\\[%s])", - name_domain, name_user))) { - DEBUG(1, ("out of memory\n")); - return WINBINDD_ERROR; - } - - status = domain->methods->query_user(domain, mem_ctx, &user_sid, - &user_info); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("error getting user info for user '[%s]\\[%s]'\n", - name_domain, name_user)); - talloc_destroy(mem_ctx); - return WINBINDD_ERROR; - } - - /* Now take all this information and fill in a passwd structure */ - if (!winbindd_fill_pwent(name_domain, name_user, - user_info.user_sid, user_info.group_sid, - user_info.full_name, - &state->response.data.pw)) { - talloc_destroy(mem_ctx); - return WINBINDD_ERROR; - } - - talloc_destroy(mem_ctx); - - return WINBINDD_OK; -} - -/* Return a password structure given a uid number */ - -enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) -{ - DOM_SID user_sid; - struct winbindd_domain *domain; - fstring dom_name; - fstring user_name; - enum SID_NAME_USE name_type; - WINBIND_USERINFO user_info; - gid_t gid; - TALLOC_CTX *mem_ctx; - NTSTATUS status; - - /* Bug out if the uid isn't in the winbind range */ - - if ((state->request.data.uid < server_state.uid_low ) || - (state->request.data.uid > server_state.uid_high)) - return WINBINDD_ERROR; - - DEBUG(3, ("[%5d]: getpwuid %d\n", state->pid, - state->request.data.uid)); - - /* Get rid from uid */ - - if (!winbindd_idmap_get_sid_from_uid(state->request.data.uid, - &user_sid)) { - DEBUG(1, ("could not convert uid %d to SID\n", - state->request.data.uid)); - return WINBINDD_ERROR; - } - - /* Get name and name type from rid */ - - if (!winbindd_lookup_name_by_sid(&user_sid, dom_name, user_name, &name_type)) { - fstring temp; - - sid_to_string(temp, &user_sid); - DEBUG(1, ("could not lookup sid %s\n", temp)); - return WINBINDD_ERROR; - } - - domain = find_domain_from_sid(&user_sid); - - if (!domain) { - DEBUG(1,("Can't find domain from sid\n")); - return WINBINDD_ERROR; - } - - /* Get some user info */ - - if (!(mem_ctx = talloc_init("winbind_getpwuid(%d)", - state->request.data.uid))) { - - DEBUG(1, ("out of memory\n")); - return WINBINDD_ERROR; - } - - status = domain->methods->query_user(domain, mem_ctx, &user_sid, - &user_info); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(1, ("error getting user info for user '%s'\n", - user_name)); - talloc_destroy(mem_ctx); - return WINBINDD_ERROR; - } - - /* Resolve gid number */ - - if (!winbindd_idmap_get_gid_from_sid(user_info.group_sid, &gid)) { - DEBUG(1, ("error getting group id for user %s\n", user_name)); - talloc_destroy(mem_ctx); - return WINBINDD_ERROR; - } - - /* Fill in password structure */ - - if (!winbindd_fill_pwent(domain->name, user_name, user_info.user_sid, - user_info.group_sid, - user_info.full_name, &state->response.data.pw)) { - talloc_destroy(mem_ctx); - return WINBINDD_ERROR; - } - - talloc_destroy(mem_ctx); - - return WINBINDD_OK; -} - -/* - * set/get/endpwent functions - */ - -/* Rewind file pointer for ntdom passwd database */ - -enum winbindd_result winbindd_setpwent(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - - DEBUG(3, ("[%5d]: setpwent\n", state->pid)); - - /* Check user has enabled this */ - - if (!lp_winbind_enum_users()) - return WINBINDD_ERROR; - - /* Free old static data if it exists */ - - if (state->getpwent_state != NULL) { - free_getent_state(state->getpwent_state); - state->getpwent_state = NULL; - } - - /* Create sam pipes for each domain we know about */ - - for(domain = domain_list(); domain != NULL; domain = domain->next) { - struct getent_state *domain_state; - - /* Create a state record for this domain */ - - if ((domain_state = (struct getent_state *) - malloc(sizeof(struct getent_state))) == NULL) - return WINBINDD_ERROR; - - ZERO_STRUCTP(domain_state); - - fstrcpy(domain_state->domain_name, domain->name); - - /* Add to list of open domains */ - - DLIST_ADD(state->getpwent_state, domain_state); - } - - return WINBINDD_OK; -} - -/* Close file pointer to ntdom passwd database */ - -enum winbindd_result winbindd_endpwent(struct winbindd_cli_state *state) -{ - DEBUG(3, ("[%5d]: endpwent\n", state->pid)); - - free_getent_state(state->getpwent_state); - state->getpwent_state = NULL; - - return WINBINDD_OK; -} - -/* Get partial list of domain users for a domain. We fill in the sam_entries, - and num_sam_entries fields with domain user information. The dispinfo_ndx - field is incremented to the index of the next user to fetch. Return True if - some users were returned, False otherwise. */ - -#define MAX_FETCH_SAM_ENTRIES 100 - -static BOOL get_sam_user_entries(struct getent_state *ent) -{ - NTSTATUS status; - uint32 num_entries; - WINBIND_USERINFO *info; - struct getpwent_user *name_list = NULL; - BOOL result = False; - TALLOC_CTX *mem_ctx; - struct winbindd_domain *domain; - struct winbindd_methods *methods; - unsigned int i; - - if (ent->num_sam_entries) - return False; - - if (!(mem_ctx = talloc_init("get_sam_user_entries(%s)", - ent->domain_name))) - return False; - - if (!(domain = find_domain_from_name(ent->domain_name))) { - DEBUG(3, ("no such domain %s in get_sam_user_entries\n", - ent->domain_name)); - return False; - } - - methods = domain->methods; - - /* Free any existing user info */ - - SAFE_FREE(ent->sam_entries); - ent->num_sam_entries = 0; - - /* Call query_user_list to get a list of usernames and user rids */ - - num_entries = 0; - - status = methods->query_user_list(domain, mem_ctx, &num_entries, - &info); - - if (num_entries) { - struct getpwent_user *tnl; - - tnl = (struct getpwent_user *)Realloc(name_list, - sizeof(struct getpwent_user) * - (ent->num_sam_entries + - num_entries)); - - if (!tnl) { - DEBUG(0,("get_sam_user_entries realloc failed.\n")); - SAFE_FREE(name_list); - goto done; - } else - name_list = tnl; - } - - for (i = 0; i < num_entries; i++) { - /* Store account name and gecos */ - if (!info[i].acct_name) { - fstrcpy(name_list[ent->num_sam_entries + i].name, ""); - } else { - fstrcpy(name_list[ent->num_sam_entries + i].name, - info[i].acct_name); - } - if (!info[i].full_name) { - fstrcpy(name_list[ent->num_sam_entries + i].gecos, ""); - } else { - fstrcpy(name_list[ent->num_sam_entries + i].gecos, - info[i].full_name); - } - - /* User and group ids */ - sid_copy(&name_list[ent->num_sam_entries+i].user_sid, info[i].user_sid); - sid_copy(&name_list[ent->num_sam_entries+i].group_sid, info[i].group_sid); - } - - ent->num_sam_entries += num_entries; - - /* Fill in remaining fields */ - - ent->sam_entries = name_list; - ent->sam_entry_index = 0; - result = ent->num_sam_entries > 0; - - done: - - talloc_destroy(mem_ctx); - - return result; -} - -/* Fetch next passwd entry from ntdom database */ - -#define MAX_GETPWENT_USERS 500 - -enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state) -{ - struct getent_state *ent; - struct winbindd_pw *user_list; - int num_users, user_list_ndx = 0, i; - - DEBUG(3, ("[%5d]: getpwent\n", state->pid)); - - /* Check user has enabled this */ - - if (!lp_winbind_enum_users()) - return WINBINDD_ERROR; - - /* Allocate space for returning a chunk of users */ - - num_users = MIN(MAX_GETPWENT_USERS, state->request.data.num_entries); - - if ((state->response.extra_data = - malloc(num_users * sizeof(struct winbindd_pw))) == NULL) - return WINBINDD_ERROR; - - memset(state->response.extra_data, 0, num_users * - sizeof(struct winbindd_pw)); - - user_list = (struct winbindd_pw *)state->response.extra_data; - - if (!(ent = state->getpwent_state)) - return WINBINDD_ERROR; - - /* Start sending back users */ - - for (i = 0; i < num_users; i++) { - struct getpwent_user *name_list = NULL; - fstring domain_user_name; - uint32 result; - - /* Do we need to fetch another chunk of users? */ - - if (ent->num_sam_entries == ent->sam_entry_index) { - - while(ent && !get_sam_user_entries(ent)) { - struct getent_state *next_ent; - - /* Free state information for this domain */ - - SAFE_FREE(ent->sam_entries); - - next_ent = ent->next; - DLIST_REMOVE(state->getpwent_state, ent); - - SAFE_FREE(ent); - ent = next_ent; - } - - /* No more domains */ - - if (!ent) - break; - } - - name_list = ent->sam_entries; - - /* Skip machine accounts */ - - if (name_list[ent->sam_entry_index]. - name[strlen(name_list[ent->sam_entry_index].name) - 1] - == '$') { - ent->sam_entry_index++; - continue; - } - - /* Lookup user info */ - - result = winbindd_fill_pwent( - ent->domain_name, - name_list[ent->sam_entry_index].name, - &name_list[ent->sam_entry_index].user_sid, - &name_list[ent->sam_entry_index].group_sid, - name_list[ent->sam_entry_index].gecos, - &user_list[user_list_ndx]); - - ent->sam_entry_index++; - - /* Add user to return list */ - - if (result) { - - user_list_ndx++; - state->response.data.num_entries++; - state->response.length += - sizeof(struct winbindd_pw); - - } else - DEBUG(1, ("could not lookup domain user %s\n", - domain_user_name)); - } - - /* Out of domains */ - - return (user_list_ndx > 0) ? WINBINDD_OK : WINBINDD_ERROR; -} - -/* List domain users without mapping to unix ids */ - -enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - WINBIND_USERINFO *info; - uint32 num_entries = 0, total_entries = 0; - char *ted, *extra_data = NULL; - int extra_data_len = 0; - TALLOC_CTX *mem_ctx; - enum winbindd_result rv = WINBINDD_ERROR; - - DEBUG(3, ("[%5d]: list users\n", state->pid)); - - if (!(mem_ctx = talloc_init("winbindd_list_users"))) - return WINBINDD_ERROR; - - /* Enumerate over trusted domains */ - - for (domain = domain_list(); domain; domain = domain->next) { - NTSTATUS status; - struct winbindd_methods *methods; - unsigned int i; - - methods = domain->methods; - - /* Query display info */ - status = methods->query_user_list(domain, mem_ctx, - &num_entries, &info); - - if (num_entries == 0) - continue; - - /* Allocate some memory for extra data */ - total_entries += num_entries; - - ted = Realloc(extra_data, sizeof(fstring) * total_entries); - - if (!ted) { - DEBUG(0,("failed to enlarge buffer!\n")); - SAFE_FREE(extra_data); - goto done; - } else - extra_data = ted; - - /* Pack user list into extra data fields */ - - for (i = 0; i < num_entries; i++) { - fstring acct_name, name; - - if (!info[i].acct_name) { - fstrcpy(acct_name, ""); - } else { - fstrcpy(acct_name, info[i].acct_name); - } - - fill_domain_username(name, domain->name, acct_name); - - /* Append to extra data */ - memcpy(&extra_data[extra_data_len], name, - strlen(name)); - extra_data_len += strlen(name); - extra_data[extra_data_len++] = ','; - } - } - - /* Assign extra_data fields in response structure */ - - if (extra_data) { - extra_data[extra_data_len - 1] = '\0'; - state->response.extra_data = extra_data; - state->response.length += extra_data_len; - } - - /* No domains responded but that's still OK so don't return an - error. */ - - rv = WINBINDD_OK; - - done: - - talloc_destroy(mem_ctx); - - return rv; -} diff --git a/source4/nsswitch/winbindd_util.c b/source4/nsswitch/winbindd_util.c deleted file mode 100644 index 7ccf032041..0000000000 --- a/source4/nsswitch/winbindd_util.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon for ntdom nss module - - Copyright (C) Tim Potter 2000-2001 - Copyright (C) 2001 by Martin Pool <mbp@samba.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/** - * @file winbindd_util.c - * - * Winbind daemon for NT domain authentication nss module. - **/ - - -/** - * Used to clobber name fields that have an undefined value. - * - * Correct code should never look at a field that has this value. - **/ - -static const fstring name_deadbeef = "<deadbeef>"; - -/* The list of trusted domains. Note that the list can be deleted and - recreated using the init_domain_list() function so pointers to - individual winbindd_domain structures cannot be made. Keep a copy of - the domain name instead. */ - -static struct winbindd_domain *_domain_list; - -struct winbindd_domain *domain_list(void) -{ - /* Initialise list */ - - if (!_domain_list) - init_domain_list(); - - return _domain_list; -} - -/* Free all entries in the trusted domain list */ - -void free_domain_list(void) -{ - struct winbindd_domain *domain = _domain_list; - - while(domain) { - struct winbindd_domain *next = domain->next; - - DLIST_REMOVE(_domain_list, domain); - SAFE_FREE(domain); - domain = next; - } -} - - -/* Add a trusted domain to our list of domains */ -static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name, - struct winbindd_methods *methods, - DOM_SID *sid) -{ - struct winbindd_domain *domain; - - /* We can't call domain_list() as this function is called from - init_domain_list() and we'll get stuck in a loop. */ - for (domain = _domain_list; domain; domain = domain->next) { - if (strcasecmp(domain_name, domain->name) == 0 || - strcasecmp(domain_name, domain->alt_name) == 0) { - return domain; - } - if (alt_name && *alt_name) { - if (strcasecmp(alt_name, domain->name) == 0 || - strcasecmp(alt_name, domain->alt_name) == 0) { - return domain; - } - } - } - - /* Create new domain entry */ - - if ((domain = (struct winbindd_domain *) - malloc(sizeof(*domain))) == NULL) - return NULL; - - /* Fill in fields */ - - ZERO_STRUCTP(domain); - - /* prioritise the short name */ - if (strchr_m(domain_name, '.') && alt_name && *alt_name) { - fstrcpy(domain->name, alt_name); - fstrcpy(domain->alt_name, domain_name); - } else { - fstrcpy(domain->name, domain_name); - if (alt_name) { - fstrcpy(domain->alt_name, alt_name); - } - } - - domain->methods = methods; - domain->sequence_number = DOM_SEQUENCE_NONE; - domain->last_seq_check = 0; - if (sid) { - sid_copy(&domain->sid, sid); - } - - /* see if this is a native mode win2k domain, but only for our own domain */ - - if ( strequal( lp_workgroup(), domain_name) ) { - domain->native_mode = cm_check_for_native_mode_win2k( domain_name ); - DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain_name, - domain->native_mode ? "native" : "mixed" )); - } - - /* Link to domain list */ - DLIST_ADD(_domain_list, domain); - - DEBUG(1,("Added domain %s %s %s\n", - domain->name, domain->alt_name, - sid?sid_string_static(&domain->sid):"")); - - return domain; -} - - -/* - rescan our domains looking for new trusted domains - */ -void rescan_trusted_domains(BOOL force) -{ - struct winbindd_domain *domain; - TALLOC_CTX *mem_ctx; - static time_t last_scan; - time_t t = time(NULL); - - /* trusted domains might be disabled */ - if (!lp_allow_trusted_domains()) { - return; - } - - /* Only rescan every few minutes but force if necessary */ - - if (((unsigned)(t - last_scan) < WINBINDD_RESCAN_FREQ) && !force) - return; - - last_scan = t; - - DEBUG(1, ("scanning trusted domain list\n")); - - if (!(mem_ctx = talloc_init("init_domain_list"))) - return; - - for (domain = _domain_list; domain; domain = domain->next) { - NTSTATUS result; - char **names; - char **alt_names; - int num_domains = 0; - DOM_SID *dom_sids; - int i; - - result = domain->methods->trusted_domains(domain, mem_ctx, &num_domains, - &names, &alt_names, &dom_sids); - if (!NT_STATUS_IS_OK(result)) { - continue; - } - - /* Add each domain to the trusted domain list. Each domain inherits - the access methods of its parent */ - for(i = 0; i < num_domains; i++) { - DEBUG(10,("Found domain %s\n", names[i])); - add_trusted_domain(names[i], alt_names?alt_names[i]:NULL, - domain->methods, &dom_sids[i]); - - /* store trusted domain in the cache */ - trustdom_cache_store(mem_ctx, names[i], alt_names ? alt_names[i] : NULL, - &dom_sids[i], t + WINBINDD_RESCAN_FREQ); - } - } - - talloc_destroy(mem_ctx); -} - -/* Look up global info for the winbind daemon */ -BOOL init_domain_list(void) -{ - extern struct winbindd_methods cache_methods; - struct winbindd_domain *domain; - - /* Free existing list */ - free_domain_list(); - - /* Add ourselves as the first entry */ - domain = add_trusted_domain(lp_workgroup(), NULL, &cache_methods, NULL); - if (!secrets_fetch_domain_sid(domain->name, &domain->sid)) { - DEBUG(1, ("Could not fetch sid for our domain %s\n", - domain->name)); - return False; - } - - /* get any alternate name for the primary domain */ - cache_methods.alternate_name(domain); - - /* do an initial scan for trusted domains */ - rescan_trusted_domains(True); - - return True; -} - -/* Given a domain name, return the struct winbindd domain info for it - if it is actually working. */ - -struct winbindd_domain *find_domain_from_name(const char *domain_name) -{ - struct winbindd_domain *domain; - - /* Search through list */ - - for (domain = domain_list(); domain != NULL; domain = domain->next) { - if (strequal(domain_name, domain->name) || - (domain->alt_name[0] && strequal(domain_name, domain->alt_name))) - return domain; - } - - /* Not found */ - - return NULL; -} - -/* Given a domain sid, return the struct winbindd domain info for it */ - -struct winbindd_domain *find_domain_from_sid(DOM_SID *sid) -{ - struct winbindd_domain *domain; - - /* Search through list */ - - for (domain = domain_list(); domain != NULL; domain = domain->next) { - if (sid_compare_domain(sid, &domain->sid) == 0) - return domain; - } - - /* Not found */ - - return NULL; -} - -/* Lookup a sid in a domain from a name */ - -BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, - const char *name, DOM_SID *sid, - enum SID_NAME_USE *type) -{ - NTSTATUS result; - TALLOC_CTX *mem_ctx; - /* Don't bother with machine accounts */ - - if (name[strlen(name) - 1] == '$') - return False; - - mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name); - if (!mem_ctx) - return False; - - /* Lookup name */ - result = domain->methods->name_to_sid(domain, mem_ctx, name, sid, type); - - talloc_destroy(mem_ctx); - - /* Return rid and type if lookup successful */ - if (!NT_STATUS_IS_OK(result)) { - *type = SID_NAME_UNKNOWN; - } - - return NT_STATUS_IS_OK(result); -} - -/** - * @brief Lookup a name in a domain from a sid. - * - * @param sid Security ID you want to look up. - * - * @param name On success, set to the name corresponding to @p sid. - * - * @param dom_name On success, set to the 'domain name' corresponding to @p sid. - * - * @param type On success, contains the type of name: alias, group or - * user. - * - * @retval True if the name exists, in which case @p name and @p type - * are set, otherwise False. - **/ -BOOL winbindd_lookup_name_by_sid(DOM_SID *sid, - fstring dom_name, - fstring name, - enum SID_NAME_USE *type) -{ - char *names; - NTSTATUS result; - TALLOC_CTX *mem_ctx; - BOOL rv = False; - struct winbindd_domain *domain; - - domain = find_domain_from_sid(sid); - - if (!domain) { - DEBUG(1,("Can't find domain from sid\n")); - return False; - } - - /* Lookup name */ - - if (!(mem_ctx = talloc_init("winbindd_lookup_name_by_sid"))) - return False; - - result = domain->methods->sid_to_name(domain, mem_ctx, sid, &names, type); - - /* Return name and type if successful */ - - if ((rv = NT_STATUS_IS_OK(result))) { - fstrcpy(dom_name, domain->name); - fstrcpy(name, names); - } else { - *type = SID_NAME_UNKNOWN; - fstrcpy(name, name_deadbeef); - } - - talloc_destroy(mem_ctx); - - return rv; -} - - -/* Free state information held for {set,get,end}{pw,gr}ent() functions */ - -void free_getent_state(struct getent_state *state) -{ - struct getent_state *temp; - - /* Iterate over state list */ - - temp = state; - - while(temp != NULL) { - struct getent_state *next; - - /* Free sam entries then list entry */ - - SAFE_FREE(state->sam_entries); - DLIST_REMOVE(state, state); - next = temp->next; - - SAFE_FREE(temp); - temp = next; - } -} - -/* Parse winbindd related parameters */ - -BOOL winbindd_param_init(void) -{ - /* Parse winbind uid and winbind_gid parameters */ - - if (!lp_winbind_uid(&server_state.uid_low, &server_state.uid_high)) { - DEBUG(0, ("winbind uid range missing or invalid\n")); - return False; - } - - if (!lp_winbind_gid(&server_state.gid_low, &server_state.gid_high)) { - DEBUG(0, ("winbind gid range missing or invalid\n")); - return False; - } - - return True; -} - -/* Check if a domain is present in a comma-separated list of domains */ - -BOOL check_domain_env(char *domain_env, char *domain) -{ - fstring name; - const char *tmp = domain_env; - - while(next_token(&tmp, name, ",", sizeof(fstring))) { - if (strequal(name, domain)) - return True; - } - - return False; -} - -/* Parse a string of the form DOMAIN/user into a domain and a user */ - -BOOL parse_domain_user(const char *domuser, fstring domain, fstring user) -{ - char *p = strchr(domuser,*lp_winbind_separator()); - - if (!(p || lp_winbind_use_default_domain())) - return False; - - if(!p && lp_winbind_use_default_domain()) { - fstrcpy(user, domuser); - fstrcpy(domain, lp_workgroup()); - } else { - fstrcpy(user, p+1); - fstrcpy(domain, domuser); - domain[PTR_DIFF(p, domuser)] = 0; - } - strupper(domain); - return True; -} - -/* - Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and - 'winbind separator' options. - This means: - - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is - lp_workgroup - -*/ -void fill_domain_username(fstring name, const char *domain, const char *user) -{ - if(lp_winbind_use_default_domain() && - !strcmp(lp_workgroup(), domain)) { - strlcpy(name, user, sizeof(fstring)); - } else { - slprintf(name, sizeof(fstring) - 1, "%s%s%s", - domain, lp_winbind_separator(), - user); - } -} - -/* - * Winbindd socket accessor functions - */ - -/* Open the winbindd socket */ - -static int _winbindd_socket = -1; - -int open_winbindd_socket(void) -{ - if (_winbindd_socket == -1) { - _winbindd_socket = create_pipe_sock( - WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME, 0755); - DEBUG(10, ("open_winbindd_socket: opened socket fd %d\n", - _winbindd_socket)); - } - - return _winbindd_socket; -} - -/* Close the winbindd socket */ - -void close_winbindd_socket(void) -{ - if (_winbindd_socket != -1) { - DEBUG(10, ("close_winbindd_socket: closing socket fd %d\n", - _winbindd_socket)); - close(_winbindd_socket); - _winbindd_socket = -1; - } -} - -/* - * Client list accessor functions - */ - -static struct winbindd_cli_state *_client_list; -static int _num_clients; - -/* Return list of all connected clients */ - -struct winbindd_cli_state *winbindd_client_list(void) -{ - return _client_list; -} - -/* Add a connection to the list */ - -void winbindd_add_client(struct winbindd_cli_state *cli) -{ - DLIST_ADD(_client_list, cli); - _num_clients++; -} - -/* Remove a client from the list */ - -void winbindd_remove_client(struct winbindd_cli_state *cli) -{ - DLIST_REMOVE(_client_list, cli); - _num_clients--; -} - -/* Close all open clients */ - -void winbindd_kill_all_clients(void) -{ - struct winbindd_cli_state *cl = winbindd_client_list(); - - DEBUG(10, ("winbindd_kill_all_clients: going postal\n")); - - while (cl) { - struct winbindd_cli_state *next; - - next = cl->next; - winbindd_remove_client(cl); - cl = next; - } -} - -/* Return number of open clients */ - -int winbindd_num_clients(void) -{ - return _num_clients; -} - -/* Help with RID -> SID conversion */ - -DOM_SID *rid_to_talloced_sid(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - uint32 rid) -{ - DOM_SID *sid; - sid = talloc(mem_ctx, sizeof(*sid)); - if (!sid) { - smb_panic("rid_to_to_talloced_sid: talloc for DOM_SID failed!\n"); - } - sid_copy(sid, &domain->sid); - sid_append_rid(sid, rid); - return sid; -} - diff --git a/source4/nsswitch/winbindd_wins.c b/source4/nsswitch/winbindd_wins.c deleted file mode 100644 index 8ddd5dc10d..0000000000 --- a/source4/nsswitch/winbindd_wins.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Winbind daemon - WINS related functions - - Copyright (C) Andrew Tridgell 1999 - Copyright (C) Herb Lewis 2002 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "winbindd.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_WINBIND - -/* Use our own create socket code so we don't recurse.... */ - -static int wins_lookup_open_socket_in(void) -{ - struct sockaddr_in sock; - int val=1; - int res; - - memset((char *)&sock,'\0',sizeof(sock)); - -#ifdef HAVE_SOCK_SIN_LEN - sock.sin_len = sizeof(sock); -#endif - sock.sin_port = 0; - sock.sin_family = AF_INET; - sock.sin_addr.s_addr = interpret_addr("0.0.0.0"); - res = socket(AF_INET, SOCK_DGRAM, 0); - if (res == -1) - return -1; - - setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); -#ifdef SO_REUSEPORT - setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)); -#endif /* SO_REUSEPORT */ - - /* now we've got a socket - we need to bind it */ - - if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) { - close(res); - return(-1); - } - - set_socket_options(res,"SO_BROADCAST"); - - return res; -} - - -static struct node_status *lookup_byaddr_backend(char *addr, int *count) -{ - int fd; - struct in_addr ip; - struct nmb_name nname; - struct node_status *status; - - fd = wins_lookup_open_socket_in(); - if (fd == -1) - return NULL; - - make_nmb_name(&nname, "*", 0); - ip = *interpret_addr2(addr); - status = node_status_query(fd,&nname,ip, count); - - close(fd); - return status; -} - -static struct in_addr *lookup_byname_backend(const char *name, int *count) -{ - int fd; - struct in_addr *ret = NULL; - int j, flags = 0; - - *count = 0; - - /* always try with wins first */ - if (resolve_wins(name,0x20,&ret,count)) { - return ret; - } - - fd = wins_lookup_open_socket_in(); - if (fd == -1) { - return NULL; - } - - /* uggh, we have to broadcast to each interface in turn */ - for (j=iface_count() - 1; - j >= 0; - j--) { - struct in_addr *bcast = iface_n_bcast(j); - ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); - if (ret) break; - } - - close(fd); - return ret; -} - -/* Get hostname from IP */ - -enum winbindd_result winbindd_wins_byip(struct winbindd_cli_state *state) -{ - fstring response; - int i, count, maxlen, size; - struct node_status *status; - - /* Ensure null termination */ - state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0'; - - DEBUG(3, ("[%5d]: wins_byip %s\n", state->pid, - state->request.data.winsreq)); - - *response = '\0'; - maxlen = sizeof(response) - 1; - - if ((status = lookup_byaddr_backend(state->request.data.winsreq, &count))){ - size = strlen(state->request.data.winsreq); - if (size > maxlen) { - SAFE_FREE(status); - return WINBINDD_ERROR; - } - safe_strcat(response,state->request.data.winsreq,maxlen); - safe_strcat(response,"\t",maxlen); - for (i = 0; i < count; i++) { - /* ignore group names */ - if (status[i].flags & 0x80) continue; - if (status[i].type == 0x20) { - size = sizeof(status[i].name) + strlen(response); - if (size > maxlen) { - SAFE_FREE(status); - return WINBINDD_ERROR; - } - safe_strcat(response, status[i].name, maxlen); - safe_strcat(response, " ", maxlen); - } - } - /* make last character a newline */ - response[strlen(response)-1] = '\n'; - SAFE_FREE(status); - } - fstrcpy(state->response.data.winsresp,response); - return WINBINDD_OK; -} - -/* Get IP from hostname */ - -enum winbindd_result winbindd_wins_byname(struct winbindd_cli_state *state) -{ - struct in_addr *ip_list; - int i, count, maxlen, size; - fstring response; - char * addr; - - /* Ensure null termination */ - state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0'; - - DEBUG(3, ("[%5d]: wins_byname %s\n", state->pid, - state->request.data.winsreq)); - - *response = '\0'; - maxlen = sizeof(response) - 1; - - if ((ip_list = lookup_byname_backend(state->request.data.winsreq,&count))){ - for (i = count; i ; i--) { - addr = inet_ntoa(ip_list[i-1]); - size = strlen(addr); - if (size > maxlen) { - SAFE_FREE(ip_list); - return WINBINDD_ERROR; - } - if (i != 0) { - /* Clear out the newline character */ - response[strlen(response)-1] = ' '; - } - safe_strcat(response,addr,maxlen); - safe_strcat(response,"\t",maxlen); - } - size = strlen(state->request.data.winsreq) + strlen(response); - if (size > maxlen) { - SAFE_FREE(ip_list); - return WINBINDD_ERROR; - } - safe_strcat(response,state->request.data.winsreq,maxlen); - safe_strcat(response,"\n",maxlen); - SAFE_FREE(ip_list); - } else - return WINBINDD_ERROR; - - fstrcpy(state->response.data.winsresp,response); - - return WINBINDD_OK; -} diff --git a/source4/nsswitch/wins.c b/source4/nsswitch/wins.c deleted file mode 100644 index d5791d7af5..0000000000 --- a/source4/nsswitch/wins.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - Unix SMB/CIFS implementation. - a WINS nsswitch module - Copyright (C) Andrew Tridgell 1999 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "includes.h" -#ifdef HAVE_NS_API_H -#undef VOLATILE - -#include <ns_daemon.h> -#endif - -#ifndef INADDRSZ -#define INADDRSZ 4 -#endif - -static int initialised; - -extern BOOL AllowDebugChange; - -/* Use our own create socket code so we don't recurse.... */ - -static int wins_lookup_open_socket_in(void) -{ - struct sockaddr_in sock; - int val=1; - int res; - - memset((char *)&sock,'\0',sizeof(sock)); - -#ifdef HAVE_SOCK_SIN_LEN - sock.sin_len = sizeof(sock); -#endif - sock.sin_port = 0; - sock.sin_family = AF_INET; - sock.sin_addr.s_addr = interpret_addr("0.0.0.0"); - res = socket(AF_INET, SOCK_DGRAM, 0); - if (res == -1) - return -1; - - setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&val,sizeof(val)); -#ifdef SO_REUSEPORT - setsockopt(res,SOL_SOCKET,SO_REUSEPORT,(char *)&val,sizeof(val)); -#endif /* SO_REUSEPORT */ - - /* now we've got a socket - we need to bind it */ - - if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) { - close(res); - return(-1); - } - - set_socket_options(res,"SO_BROADCAST"); - - return res; -} - - -static void nss_wins_init(void) -{ - initialised = 1; - DEBUGLEVEL = 0; - AllowDebugChange = False; - - TimeInit(); - setup_logging("nss_wins",DEBUG_FILE); - lp_load(dyn_CONFIGFILE,True,False,False); - load_interfaces(); -} - -static struct node_status *lookup_byaddr_backend(char *addr, int *count) -{ - int fd; - struct in_addr ip; - struct nmb_name nname; - struct node_status *status; - - if (!initialised) { - nss_wins_init(); - } - - fd = wins_lookup_open_socket_in(); - if (fd == -1) - return NULL; - - make_nmb_name(&nname, "*", 0); - ip = *interpret_addr2(addr); - status = node_status_query(fd,&nname,ip, count); - - close(fd); - return status; -} - -static struct in_addr *lookup_byname_backend(const char *name, int *count) -{ - int fd = -1; - struct in_addr *ret = NULL; - struct in_addr p; - int j, flags = 0; - - if (!initialised) { - nss_wins_init(); - } - - *count = 0; - - /* always try with wins first */ - if (resolve_wins(name,0x20,&ret,count)) { - return ret; - } - - fd = wins_lookup_open_socket_in(); - if (fd == -1) { - return NULL; - } - - /* uggh, we have to broadcast to each interface in turn */ - for (j=iface_count() - 1;j >= 0;j--) { - struct in_addr *bcast = iface_n_bcast(j); - ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); - if (ret) break; - } - -out: - close(fd); - return ret; -} - - -#ifdef HAVE_NS_API_H -/* IRIX version */ - -int init(void) -{ - nsd_logprintf(NSD_LOG_MIN, "entering init (wins)\n"); - nss_wins_init(); - return NSD_OK; -} - -int lookup(nsd_file_t *rq) -{ - char *map; - char *key; - char *addr; - struct in_addr *ip_list; - struct node_status *status; - int i, count, len, size; - char response[1024]; - BOOL found = False; - - nsd_logprintf(NSD_LOG_MIN, "entering lookup (wins)\n"); - if (! rq) - return NSD_ERROR; - - map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0); - if (! map) { - rq->f_status = NS_FATAL; - return NSD_ERROR; - } - - key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0); - if (! key || ! *key) { - rq->f_status = NS_FATAL; - return NSD_ERROR; - } - - response[0] = '\0'; - len = sizeof(response) - 2; - - /* - * response needs to be a string of the following format - * ip_address[ ip_address]*\tname[ alias]* - */ - if (strcasecmp(map,"hosts.byaddr") == 0) { - if ( status = lookup_byaddr_backend(key, &count)) { - size = strlen(key) + 1; - if (size > len) { - free(status); - return NSD_ERROR; - } - len -= size; - strncat(response,key,size); - strncat(response,"\t",1); - for (i = 0; i < count; i++) { - /* ignore group names */ - if (status[i].flags & 0x80) continue; - if (status[i].type == 0x20) { - size = sizeof(status[i].name) + 1; - if (size > len) { - free(status); - return NSD_ERROR; - } - len -= size; - strncat(response, status[i].name, size); - strncat(response, " ", 1); - found = True; - } - } - response[strlen(response)-1] = '\n'; - free(status); - } - } else if (strcasecmp(map,"hosts.byname") == 0) { - if (ip_list = lookup_byname_backend(key, &count)) { - for (i = count; i ; i--) { - addr = inet_ntoa(ip_list[i-1]); - size = strlen(addr) + 1; - if (size > len) { - free(ip_list); - return NSD_ERROR; - } - len -= size; - if (i != 0) - response[strlen(response)-1] = ' '; - strncat(response,addr,size); - strncat(response,"\t",1); - } - size = strlen(key) + 1; - if (size > len) { - free(ip_list); - return NSD_ERROR; - } - strncat(response,key,size); - strncat(response,"\n",1); - found = True; - free(ip_list); - } - } - - if (found) { - nsd_logprintf(NSD_LOG_LOW, "lookup (wins %s) %s\n",map,response); - nsd_set_result(rq,NS_SUCCESS,response,strlen(response),VOLATILE); - return NSD_OK; - } - nsd_logprintf(NSD_LOG_LOW, "lookup (wins) not found\n"); - rq->f_status = NS_NOTFOUND; - return NSD_NEXT; -} - -#else -/**************************************************************************** -gethostbyname() - we ignore any domain portion of the name and only -handle names that are at most 15 characters long - **************************************************************************/ -NSS_STATUS -_nss_wins_gethostbyname_r(const char *name, struct hostent *he, - char *buffer, size_t buflen, int *errnop, - int *h_errnop) -{ - char **host_addresses; - struct in_addr *ip_list; - int i, count; - size_t namelen = strlen(name) + 1; - - memset(he, '\0', sizeof(*he)); - - ip_list = lookup_byname_backend(name, &count); - if (!ip_list) { - return NSS_STATUS_NOTFOUND; - } - - if (buflen < namelen + (2*count+1)*INADDRSZ) { - /* no ENOMEM error type?! */ - return NSS_STATUS_NOTFOUND; - } - - - host_addresses = (char **)buffer; - he->h_addr_list = host_addresses; - host_addresses[count] = NULL; - buffer += (count + 1) * INADDRSZ; - buflen += (count + 1) * INADDRSZ; - he->h_addrtype = AF_INET; - he->h_length = INADDRSZ; - - for (i=0;i<count;i++) { - memcpy(buffer, &ip_list[i].s_addr, INADDRSZ); - *host_addresses = buffer; - buffer += INADDRSZ; - buflen -= INADDRSZ; - host_addresses++; - } - - if (ip_list) - free(ip_list); - - memcpy(buffer, name, namelen); - he->h_name = buffer; - - return NSS_STATUS_SUCCESS; -} - - -NSS_STATUS -_nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he, - char *buffer, size_t buflen, int *errnop, - int *h_errnop) -{ - if(af!=AF_INET) { - *h_errnop = NO_DATA; - *errnop = EAFNOSUPPORT; - return NSS_STATUS_UNAVAIL; - } - - return _nss_wins_gethostbyname_r(name,he,buffer,buflen,errnop,h_errnop); -} -#endif |