summaryrefslogtreecommitdiff
path: root/nsswitch
diff options
context:
space:
mode:
authorbubulle <bubulle@alioth.debian.org>2010-04-04 16:44:16 +0000
committerbubulle <bubulle@alioth.debian.org>2010-04-04 16:44:16 +0000
commit9e2f5a6ab663f7a111832217c527508c75ddae8a (patch)
tree2e74616febbb3fb658ce2dcc5f9cff00ad4fdb4a /nsswitch
parentb5556af8f75a4f74db404dd43ee7abafa2be6ca4 (diff)
downloadsamba-9e2f5a6ab663f7a111832217c527508c75ddae8a.tar.gz
Merge 3.5.1 from experimental
git-svn-id: svn://svn.debian.org/svn/pkg-samba/trunk/samba@3414 fc4039ab-9d04-0410-8cac-899223bdd6b0
Diffstat (limited to 'nsswitch')
-rw-r--r--nsswitch/config.mk11
-rw-r--r--nsswitch/libwbclient/config.mk15
-rw-r--r--nsswitch/libwbclient/libwbclient.h1
-rw-r--r--nsswitch/libwbclient/tests/wbclient.c326
-rw-r--r--nsswitch/libwbclient/wb_reqtrans.c446
-rw-r--r--nsswitch/libwbclient/wbc_async.c774
-rw-r--r--nsswitch/libwbclient/wbc_async.h95
-rw-r--r--nsswitch/libwbclient/wbc_guid.c1
-rw-r--r--nsswitch/libwbclient/wbc_idmap.c1
-rw-r--r--nsswitch/libwbclient/wbc_pam.c238
-rw-r--r--nsswitch/libwbclient/wbc_pwd.c1
-rw-r--r--nsswitch/libwbclient/wbc_sid.c18
-rw-r--r--nsswitch/libwbclient/wbc_util.c8
-rw-r--r--nsswitch/libwbclient/wbclient.c3
-rw-r--r--nsswitch/libwbclient/wbclient.h50
-rw-r--r--nsswitch/libwbclient/wbclient_internal.h1
-rw-r--r--nsswitch/nsstest.h20
-rw-r--r--nsswitch/pam_winbind.c159
-rwxr-xr-xnsswitch/tests/test_wbinfo.sh10
-rw-r--r--nsswitch/wbinfo.c727
-rw-r--r--nsswitch/wbinfo4.c1331
-rw-r--r--nsswitch/winbind_nss_netbsd.c5
-rw-r--r--nsswitch/winbind_struct_protocol.h22
23 files changed, 2604 insertions, 1659 deletions
diff --git a/nsswitch/config.mk b/nsswitch/config.mk
index 3a4f054d1f..9ad873bed1 100644
--- a/nsswitch/config.mk
+++ b/nsswitch/config.mk
@@ -2,6 +2,7 @@
PRIVATE_DEPENDENCIES = SOCKET_WRAPPER
LIBWINBIND-CLIENT_OBJ_FILES = $(nsswitchsrcdir)/wb_common.o
+$(LIBWINBIND-CLIENT_OBJ_FILES): CFLAGS+=-DWINBINDD_SOCKET_DIR=\"$(winbindd_socket_dir)\"
#################################
# Start BINARY nsstest
@@ -26,9 +27,15 @@ PRIVATE_DEPENDENCIES = \
LIBCLI_AUTH \
LIBPOPT \
POPT_SAMBA \
- LIBWINBIND-CLIENT
+ LIBWINBIND-CLIENT \
+ LIBWBCLIENT \
+ LIBTEVENT \
+ UTIL_TEVENT \
+ LIBASYNC_REQ \
+ UID_WRAPPER
# End BINARY nsstest
#################################
wbinfo_OBJ_FILES = \
- $(nsswitchsrcdir)/wbinfo4.o
+ $(nsswitchsrcdir)/wbinfo.o
+$(wbinfo_OBJ_FILES): CFLAGS+=-DWINBINDD_SOCKET_DIR=\"$(winbindd_socket_dir)\"
diff --git a/nsswitch/libwbclient/config.mk b/nsswitch/libwbclient/config.mk
new file mode 100644
index 0000000000..ffdab159f8
--- /dev/null
+++ b/nsswitch/libwbclient/config.mk
@@ -0,0 +1,15 @@
+[SUBSYSTEM::LIBWBCLIENT]
+PUBLIC_DEPENDENCIES = LIBASYNC_REQ \
+ LIBTEVENT \
+ LIBTALLOC \
+ UTIL_TEVENT
+
+LIBWBCLIENT_OBJ_FILES = $(addprefix $(libwbclientsrcdir)/, wbc_async.o \
+ wbc_guid.o \
+ wbc_idmap.o \
+ wbclient.o \
+ wbc_pam.o \
+ wbc_pwd.o \
+ wbc_sid.o \
+ wbc_util.o \
+ wb_reqtrans.o )
diff --git a/nsswitch/libwbclient/libwbclient.h b/nsswitch/libwbclient/libwbclient.h
index 74cba7e796..5a25cf462c 100644
--- a/nsswitch/libwbclient/libwbclient.h
+++ b/nsswitch/libwbclient/libwbclient.h
@@ -36,6 +36,7 @@
/* Public headers */
#include "wbclient.h"
+#include "wbc_async.h"
/* Private headers */
diff --git a/nsswitch/libwbclient/tests/wbclient.c b/nsswitch/libwbclient/tests/wbclient.c
new file mode 100644
index 0000000000..23fad63025
--- /dev/null
+++ b/nsswitch/libwbclient/tests/wbclient.c
@@ -0,0 +1,326 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB torture tester
+ Copyright (C) Guenther Deschner 2009
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "nsswitch/libwbclient/wbclient.h"
+#include "torture/smbtorture.h"
+#include "torture/winbind/proto.h"
+
+#define WBC_ERROR_EQUAL(x,y) (x == y)
+
+#define torture_assert_wbc_equal(torture_ctx, got, expected, cmt) \
+ do { wbcErr __got = got, __expected = expected; \
+ if (!WBC_ERROR_EQUAL(__got, __expected)) { \
+ torture_result(torture_ctx, TORTURE_FAIL, __location__": "#got" was %s, expected %s: %s", wbcErrorString(__got), wbcErrorString(__expected), cmt); \
+ return false; \
+ } \
+ } while (0)
+
+#define torture_assert_wbc_ok(torture_ctx,expr,cmt) \
+ torture_assert_wbc_equal(torture_ctx,expr,WBC_ERR_SUCCESS,cmt)
+
+static bool test_wbc_ping(struct torture_context *tctx)
+{
+ torture_assert_wbc_ok(tctx, wbcPing(),
+ "wbcPing failed");
+
+ return true;
+}
+
+static bool test_wbc_library_details(struct torture_context *tctx)
+{
+ struct wbcLibraryDetails *details;
+
+ torture_assert_wbc_ok(tctx, wbcLibraryDetails(&details),
+ "wbcLibraryDetails failed");
+ torture_assert(tctx, details,
+ "wbcLibraryDetails returned NULL pointer");
+
+ wbcFreeMemory(details);
+
+ return true;
+}
+
+static bool test_wbc_interface_details(struct torture_context *tctx)
+{
+ struct wbcInterfaceDetails *details;
+
+ torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
+ "wbcInterfaceDetails failed");
+ torture_assert(tctx, details,
+ "wbcInterfaceDetails returned NULL pointer");
+
+ wbcFreeMemory(details);
+
+ return true;
+}
+
+static bool test_wbc_sidtypestring(struct torture_context *tctx)
+{
+ torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_USE_NONE),
+ "SID_NONE", "SID_NONE failed");
+ torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_USER),
+ "SID_USER", "SID_USER failed");
+ torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_DOM_GRP),
+ "SID_DOM_GROUP", "SID_DOM_GROUP failed");
+ torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_DOMAIN),
+ "SID_DOMAIN", "SID_DOMAIN failed");
+ torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_ALIAS),
+ "SID_ALIAS", "SID_ALIAS failed");
+ torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_WKN_GRP),
+ "SID_WKN_GROUP", "SID_WKN_GROUP failed");
+ torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_DELETED),
+ "SID_DELETED", "SID_DELETED failed");
+ torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_INVALID),
+ "SID_INVALID", "SID_INVALID failed");
+ torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_UNKNOWN),
+ "SID_UNKNOWN", "SID_UNKNOWN failed");
+ torture_assert_str_equal(tctx, wbcSidTypeString(WBC_SID_NAME_COMPUTER),
+ "SID_COMPUTER", "SID_COMPUTER failed");
+ return true;
+}
+
+static bool test_wbc_sidtostring(struct torture_context *tctx)
+{
+ struct wbcDomainSid sid;
+ const char *sid_string = "S-1-5-32";
+ char *sid_string2;
+
+ torture_assert_wbc_ok(tctx, wbcStringToSid(sid_string, &sid),
+ "wbcStringToSid failed");
+ torture_assert_wbc_ok(tctx, wbcSidToString(&sid, &sid_string2),
+ "wbcSidToString failed");
+ torture_assert_str_equal(tctx, sid_string, sid_string2,
+ "sid strings differ");
+
+ return true;
+}
+
+static bool test_wbc_guidtostring(struct torture_context *tctx)
+{
+ struct wbcGuid guid;
+ const char *guid_string = "f7cf07b4-1487-45c7-824d-8b18cc580811";
+ char *guid_string2;
+
+ torture_assert_wbc_ok(tctx, wbcStringToGuid(guid_string, &guid),
+ "wbcStringToGuid failed");
+ torture_assert_wbc_ok(tctx, wbcGuidToString(&guid, &guid_string2),
+ "wbcGuidToString failed");
+ torture_assert_str_equal(tctx, guid_string, guid_string2,
+ "guid strings differ");
+
+ return true;
+}
+
+static bool test_wbc_domain_info(struct torture_context *tctx)
+{
+ const char *domain_name = NULL;
+ struct wbcDomainInfo *info;
+ struct wbcInterfaceDetails *details;
+
+ torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
+ "wbcInterfaceDetails failed");
+
+ domain_name = talloc_strdup(tctx, details->netbios_domain);
+ wbcFreeMemory(details);
+
+ torture_assert_wbc_ok(tctx, wbcDomainInfo(domain_name, &info),
+ "wbcDomainInfo failed");
+ torture_assert(tctx, info,
+ "wbcDomainInfo returned NULL pointer");
+
+ return true;
+}
+
+static bool test_wbc_users(struct torture_context *tctx)
+{
+ const char *domain_name = NULL;
+ uint32_t num_users;
+ const char **users;
+ int i;
+ struct wbcInterfaceDetails *details;
+
+ torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
+ "wbcInterfaceDetails failed");
+
+ domain_name = talloc_strdup(tctx, details->netbios_domain);
+ wbcFreeMemory(details);
+
+ torture_assert_wbc_ok(tctx, wbcListUsers(domain_name, &num_users, &users),
+ "wbcListUsers failed");
+ torture_assert(tctx, !(num_users > 0 && !users),
+ "wbcListUsers returned invalid results");
+
+ for (i=0; i < MIN(num_users,100); i++) {
+
+ struct wbcDomainSid sid, *sids;
+ enum wbcSidType name_type;
+ char *domain;
+ char *name;
+ uint32_t num_sids;
+
+ torture_assert_wbc_ok(tctx, wbcLookupName(domain_name, users[i], &sid, &name_type),
+ "wbcLookupName failed");
+ torture_assert_int_equal(tctx, name_type, WBC_SID_NAME_USER,
+ "wbcLookupName expected WBC_SID_NAME_USER");
+ torture_assert_wbc_ok(tctx, wbcLookupSid(&sid, &domain, &name, &name_type),
+ "wbcLookupSid failed");
+ torture_assert_int_equal(tctx, name_type, WBC_SID_NAME_USER,
+ "wbcLookupSid expected WBC_SID_NAME_USER");
+ torture_assert(tctx, name,
+ "wbcLookupSid returned no name");
+ torture_assert_wbc_ok(tctx, wbcLookupUserSids(&sid, true, &num_sids, &sids),
+ "wbcLookupUserSids failed");
+ }
+
+ return true;
+}
+
+static bool test_wbc_groups(struct torture_context *tctx)
+{
+ const char *domain_name = NULL;
+ uint32_t num_groups;
+ const char **groups;
+ int i;
+ struct wbcInterfaceDetails *details;
+
+ torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
+ "wbcInterfaceDetails failed");
+
+ domain_name = talloc_strdup(tctx, details->netbios_domain);
+ wbcFreeMemory(details);
+
+ torture_assert_wbc_ok(tctx, wbcListGroups(domain_name, &num_groups, &groups),
+ "wbcListGroups failed");
+ torture_assert(tctx, !(num_groups > 0 && !groups),
+ "wbcListGroups returned invalid results");
+
+ for (i=0; i < MIN(num_groups,100); i++) {
+
+ struct wbcDomainSid sid;
+ enum wbcSidType name_type;
+ char *domain;
+ char *name;
+
+ torture_assert_wbc_ok(tctx, wbcLookupName(domain_name, groups[i], &sid, &name_type),
+ "wbcLookupName failed");
+ torture_assert_wbc_ok(tctx, wbcLookupSid(&sid, &domain, &name, &name_type),
+ "wbcLookupSid failed");
+ torture_assert(tctx, name,
+ "wbcLookupSid returned no name");
+ }
+
+ return true;
+}
+
+static bool test_wbc_trusts(struct torture_context *tctx)
+{
+ struct wbcDomainInfo *domains;
+ size_t num_domains;
+ int i;
+
+ torture_assert_wbc_ok(tctx, wbcListTrusts(&domains, &num_domains),
+ "wbcListTrusts failed");
+ torture_assert(tctx, !(num_domains > 0 && !domains),
+ "wbcListTrusts returned invalid results");
+
+ for (i=0; i < MIN(num_domains,100); i++) {
+
+ struct wbcAuthErrorInfo *error;
+ /*
+ struct wbcDomainSid sid;
+ enum wbcSidType name_type;
+ char *domain;
+ char *name;
+ */
+ torture_assert_wbc_ok(tctx, wbcCheckTrustCredentials(domains[i].short_name, &error),
+ "wbcCheckTrustCredentials failed");
+ /*
+ torture_assert_wbc_ok(tctx, wbcLookupName(domains[i].short_name, NULL, &sid, &name_type),
+ "wbcLookupName failed");
+ torture_assert_int_equal(tctx, name_type, WBC_SID_NAME_DOMAIN,
+ "wbcLookupName expected WBC_SID_NAME_DOMAIN");
+ torture_assert_wbc_ok(tctx, wbcLookupSid(&sid, &domain, &name, &name_type),
+ "wbcLookupSid failed");
+ torture_assert_int_equal(tctx, name_type, WBC_SID_NAME_DOMAIN,
+ "wbcLookupSid expected WBC_SID_NAME_DOMAIN");
+ torture_assert(tctx, name,
+ "wbcLookupSid returned no name");
+ */
+ }
+
+ return true;
+}
+
+static bool test_wbc_lookupdc(struct torture_context *tctx)
+{
+ const char *domain_name = NULL;
+ struct wbcInterfaceDetails *details;
+ struct wbcDomainControllerInfo *dc_info;
+
+ torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
+ "wbcInterfaceDetails failed");
+
+ domain_name = talloc_strdup(tctx, details->netbios_domain);
+ wbcFreeMemory(details);
+
+ torture_assert_wbc_ok(tctx, wbcLookupDomainController(domain_name, 0, &dc_info),
+ "wbcLookupDomainController failed");
+
+ return true;
+}
+
+static bool test_wbc_lookupdcex(struct torture_context *tctx)
+{
+ const char *domain_name = NULL;
+ struct wbcInterfaceDetails *details;
+ struct wbcDomainControllerInfoEx *dc_info;
+
+ torture_assert_wbc_ok(tctx, wbcInterfaceDetails(&details),
+ "wbcInterfaceDetails failed");
+
+ domain_name = talloc_strdup(tctx, details->netbios_domain);
+ wbcFreeMemory(details);
+
+ torture_assert_wbc_ok(tctx, wbcLookupDomainControllerEx(domain_name, NULL, NULL, 0, &dc_info),
+ "wbcLookupDomainControllerEx failed");
+
+ return true;
+}
+
+
+struct torture_suite *torture_wbclient(void)
+{
+ struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "WBCLIENT");
+
+ torture_suite_add_simple_test(suite, "wbcPing", test_wbc_ping);
+ torture_suite_add_simple_test(suite, "wbcLibraryDetails", test_wbc_library_details);
+ torture_suite_add_simple_test(suite, "wbcInterfaceDetails", test_wbc_interface_details);
+ torture_suite_add_simple_test(suite, "wbcSidTypeString", test_wbc_sidtypestring);
+ torture_suite_add_simple_test(suite, "wbcSidToString", test_wbc_sidtostring);
+ torture_suite_add_simple_test(suite, "wbcGuidToString", test_wbc_guidtostring);
+ torture_suite_add_simple_test(suite, "wbcDomainInfo", test_wbc_domain_info);
+ torture_suite_add_simple_test(suite, "wbcListUsers", test_wbc_users);
+ torture_suite_add_simple_test(suite, "wbcListGroups", test_wbc_groups);
+ torture_suite_add_simple_test(suite, "wbcListTrusts", test_wbc_trusts);
+ torture_suite_add_simple_test(suite, "wbcLookupDomainController", test_wbc_lookupdc);
+ torture_suite_add_simple_test(suite, "wbcLookupDomainControllerEx", test_wbc_lookupdcex);
+
+ return suite;
+}
diff --git a/nsswitch/libwbclient/wb_reqtrans.c b/nsswitch/libwbclient/wb_reqtrans.c
new file mode 100644
index 0000000000..6dc429bb7d
--- /dev/null
+++ b/nsswitch/libwbclient/wb_reqtrans.c
@@ -0,0 +1,446 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Async transfer of winbindd_request and _response structs
+
+ Copyright (C) Volker Lendecke 2008
+
+ ** NOTE! The following LGPL license applies to the wbclient
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 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 Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/network.h"
+#include <talloc.h>
+#include <tevent.h>
+#include "lib/async_req/async_sock.h"
+#include "lib/util/tevent_unix.h"
+#include "nsswitch/winbind_struct_protocol.h"
+#include "nsswitch/libwbclient/wbclient.h"
+#include "nsswitch/libwbclient/wbc_async.h"
+
+/* can't use DEBUG here... */
+#define DEBUG(a,b)
+
+struct req_read_state {
+ struct winbindd_request *wb_req;
+ size_t max_extra_data;
+ ssize_t ret;
+};
+
+static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data);
+static void wb_req_read_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, size_t max_extra_data)
+{
+ struct tevent_req *req, *subreq;
+ struct req_read_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct req_read_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->max_extra_data = max_extra_data;
+
+ subreq = read_packet_send(state, ev, fd, 4, wb_req_more, state);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_req_read_done, req);
+ return req;
+}
+
+static ssize_t wb_req_more(uint8_t *buf, size_t buflen, void *private_data)
+{
+ struct req_read_state *state = talloc_get_type_abort(
+ private_data, struct req_read_state);
+ struct winbindd_request *req = (struct winbindd_request *)buf;
+
+ if (buflen == 4) {
+ if (req->length != sizeof(struct winbindd_request)) {
+ DEBUG(0, ("wb_req_read_len: Invalid request size "
+ "received: %d (expected %d)\n",
+ (int)req->length,
+ (int)sizeof(struct winbindd_request)));
+ return -1;
+ }
+ return sizeof(struct winbindd_request) - 4;
+ }
+
+ if (buflen > sizeof(struct winbindd_request)) {
+ /* We've been here, we're done */
+ return 0;
+ }
+
+ if ((state->max_extra_data != 0)
+ && (req->extra_len > state->max_extra_data)) {
+ DEBUG(3, ("Got request with %d bytes extra data on "
+ "unprivileged socket\n", (int)req->extra_len));
+ return -1;
+ }
+
+ return req->extra_len;
+}
+
+static void wb_req_read_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct req_read_state *state = tevent_req_data(
+ req, struct req_read_state);
+ int err;
+ uint8_t *buf;
+
+ state->ret = read_packet_recv(subreq, state, &buf, &err);
+ TALLOC_FREE(subreq);
+ if (state->ret == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+
+ state->wb_req = (struct winbindd_request *)buf;
+
+ if (state->wb_req->extra_len != 0) {
+ state->wb_req->extra_data.data =
+ (char *)buf + sizeof(struct winbindd_request);
+ } else {
+ state->wb_req->extra_data.data = NULL;
+ }
+ tevent_req_done(req);
+}
+
+ssize_t wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_request **preq, int *err)
+{
+ struct req_read_state *state = tevent_req_data(
+ req, struct req_read_state);
+
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
+ }
+ *preq = talloc_move(mem_ctx, &state->wb_req);
+ return state->ret;
+}
+
+struct req_write_state {
+ struct iovec iov[2];
+ ssize_t ret;
+};
+
+static void wb_req_write_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tevent_queue *queue, int fd,
+ struct winbindd_request *wb_req)
+{
+ struct tevent_req *req, *subreq;
+ struct req_write_state *state;
+ int count = 1;
+
+ req = tevent_req_create(mem_ctx, &state, struct req_write_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ state->iov[0].iov_base = (void *)wb_req;
+ state->iov[0].iov_len = sizeof(struct winbindd_request);
+
+ if (wb_req->extra_len != 0) {
+ state->iov[1].iov_base = (void *)wb_req->extra_data.data;
+ state->iov[1].iov_len = wb_req->extra_len;
+ count = 2;
+ }
+
+ subreq = writev_send(state, ev, queue, fd, true, state->iov, count);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_req_write_done, req);
+ return req;
+}
+
+static void wb_req_write_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct req_write_state *state = tevent_req_data(
+ req, struct req_write_state);
+ int err;
+
+ state->ret = writev_recv(subreq, &err);
+ TALLOC_FREE(subreq);
+ if (state->ret < 0) {
+ tevent_req_error(req, err);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+ssize_t wb_req_write_recv(struct tevent_req *req, int *err)
+{
+ struct req_write_state *state = tevent_req_data(
+ req, struct req_write_state);
+
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
+ }
+ return state->ret;
+}
+
+struct resp_read_state {
+ struct winbindd_response *wb_resp;
+ ssize_t ret;
+};
+
+static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data);
+static void wb_resp_read_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev, int fd)
+{
+ struct tevent_req *req, *subreq;
+ struct resp_read_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct resp_read_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ subreq = read_packet_send(state, ev, fd, 4, wb_resp_more, state);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_resp_read_done, req);
+ return req;
+}
+
+static ssize_t wb_resp_more(uint8_t *buf, size_t buflen, void *private_data)
+{
+ struct winbindd_response *resp = (struct winbindd_response *)buf;
+
+ if (buflen == 4) {
+ if (resp->length < sizeof(struct winbindd_response)) {
+ DEBUG(0, ("wb_resp_read_len: Invalid response size "
+ "received: %d (expected at least%d)\n",
+ (int)resp->length,
+ (int)sizeof(struct winbindd_response)));
+ return -1;
+ }
+ }
+ return resp->length - buflen;
+}
+
+static void wb_resp_read_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct resp_read_state *state = tevent_req_data(
+ req, struct resp_read_state);
+ uint8_t *buf;
+ int err;
+
+ state->ret = read_packet_recv(subreq, state, &buf, &err);
+ TALLOC_FREE(subreq);
+ if (state->ret == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+
+ state->wb_resp = (struct winbindd_response *)buf;
+
+ if (state->wb_resp->length > sizeof(struct winbindd_response)) {
+ state->wb_resp->extra_data.data =
+ (char *)buf + sizeof(struct winbindd_response);
+ } else {
+ state->wb_resp->extra_data.data = NULL;
+ }
+ tevent_req_done(req);
+}
+
+ssize_t wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_response **presp, int *err)
+{
+ struct resp_read_state *state = tevent_req_data(
+ req, struct resp_read_state);
+
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
+ }
+ *presp = talloc_move(mem_ctx, &state->wb_resp);
+ return state->ret;
+}
+
+struct resp_write_state {
+ struct iovec iov[2];
+ ssize_t ret;
+};
+
+static void wb_resp_write_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tevent_queue *queue, int fd,
+ struct winbindd_response *wb_resp)
+{
+ struct tevent_req *req, *subreq;
+ struct resp_write_state *state;
+ int count = 1;
+
+ req = tevent_req_create(mem_ctx, &state, struct resp_write_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ state->iov[0].iov_base = (void *)wb_resp;
+ state->iov[0].iov_len = sizeof(struct winbindd_response);
+
+ if (wb_resp->length > sizeof(struct winbindd_response)) {
+ state->iov[1].iov_base = (void *)wb_resp->extra_data.data;
+ state->iov[1].iov_len =
+ wb_resp->length - sizeof(struct winbindd_response);
+ count = 2;
+ }
+
+ subreq = writev_send(state, ev, queue, fd, true, state->iov, count);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_resp_write_done, req);
+ return req;
+}
+
+static void wb_resp_write_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct resp_write_state *state = tevent_req_data(
+ req, struct resp_write_state);
+ int err;
+
+ state->ret = writev_recv(subreq, &err);
+ TALLOC_FREE(subreq);
+ if (state->ret < 0) {
+ tevent_req_error(req, err);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+ssize_t wb_resp_write_recv(struct tevent_req *req, int *err)
+{
+ struct resp_write_state *state = tevent_req_data(
+ req, struct resp_write_state);
+
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
+ }
+ return state->ret;
+}
+
+struct wb_simple_trans_state {
+ struct tevent_context *ev;
+ int fd;
+ struct winbindd_response *wb_resp;
+};
+
+static void wb_simple_trans_write_done(struct tevent_req *subreq);
+static void wb_simple_trans_read_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_simple_trans_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tevent_queue *queue, int fd,
+ struct winbindd_request *wb_req)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_simple_trans_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_simple_trans_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ wb_req->length = sizeof(struct winbindd_request);
+
+ state->ev = ev;
+ state->fd = fd;
+
+ subreq = wb_req_write_send(state, ev, queue, fd, wb_req);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_simple_trans_write_done, req);
+
+ return req;
+}
+
+static void wb_simple_trans_write_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_simple_trans_state *state = tevent_req_data(
+ req, struct wb_simple_trans_state);
+ ssize_t ret;
+ int err;
+
+ ret = wb_req_write_recv(subreq, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+ subreq = wb_resp_read_send(state, state->ev, state->fd);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_simple_trans_read_done, req);
+}
+
+static void wb_simple_trans_read_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_simple_trans_state *state = tevent_req_data(
+ req, struct wb_simple_trans_state);
+ ssize_t ret;
+ int err;
+
+ ret = wb_resp_read_recv(subreq, state, &state->wb_resp, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ tevent_req_error(req, err);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int wb_simple_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_response **presponse, int *err)
+{
+ struct wb_simple_trans_state *state = tevent_req_data(
+ req, struct wb_simple_trans_state);
+
+ if (tevent_req_is_unix_error(req, err)) {
+ return -1;
+ }
+ *presponse = talloc_move(mem_ctx, &state->wb_resp);
+ return 0;
+}
diff --git a/nsswitch/libwbclient/wbc_async.c b/nsswitch/libwbclient/wbc_async.c
new file mode 100644
index 0000000000..181d5463e9
--- /dev/null
+++ b/nsswitch/libwbclient/wbc_async.c
@@ -0,0 +1,774 @@
+/*
+ Unix SMB/CIFS implementation.
+ Infrastructure for async winbind requests
+ Copyright (C) Volker Lendecke 2008
+
+ ** NOTE! The following LGPL license applies to the wbclient
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 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 Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/network.h"
+#include <talloc.h>
+#include <tevent.h>
+#include "lib/async_req/async_sock.h"
+#include "nsswitch/winbind_struct_protocol.h"
+#include "nsswitch/libwbclient/wbclient.h"
+#include "nsswitch/libwbclient/wbc_async.h"
+
+wbcErr map_wbc_err_from_errno(int error)
+{
+ switch(error) {
+ case EPERM:
+ case EACCES:
+ return WBC_ERR_AUTH_ERROR;
+ case ENOMEM:
+ return WBC_ERR_NO_MEMORY;
+ case EIO:
+ default:
+ return WBC_ERR_UNKNOWN_FAILURE;
+ }
+}
+
+bool tevent_req_is_wbcerr(struct tevent_req *req, wbcErr *pwbc_err)
+{
+ enum tevent_req_state state;
+ uint64_t error;
+ if (!tevent_req_is_error(req, &state, &error)) {
+ *pwbc_err = WBC_ERR_SUCCESS;
+ return false;
+ }
+
+ switch (state) {
+ case TEVENT_REQ_USER_ERROR:
+ *pwbc_err = error;
+ break;
+ case TEVENT_REQ_TIMED_OUT:
+ *pwbc_err = WBC_ERR_UNKNOWN_FAILURE;
+ break;
+ case TEVENT_REQ_NO_MEMORY:
+ *pwbc_err = WBC_ERR_NO_MEMORY;
+ break;
+ default:
+ *pwbc_err = WBC_ERR_UNKNOWN_FAILURE;
+ break;
+ }
+ return true;
+}
+
+wbcErr tevent_req_simple_recv_wbcerr(struct tevent_req *req)
+{
+ wbcErr wbc_err;
+
+ if (tevent_req_is_wbcerr(req, &wbc_err)) {
+ return wbc_err;
+ }
+
+ return WBC_ERR_SUCCESS;
+}
+
+struct wbc_debug_ops {
+ void (*debug)(void *context, enum wbcDebugLevel level,
+ const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
+ void *context;
+};
+
+struct wb_context {
+ struct tevent_queue *queue;
+ int fd;
+ bool is_priv;
+ const char *dir;
+ struct wbc_debug_ops debug_ops;
+};
+
+static int make_nonstd_fd(int fd)
+{
+ int i;
+ int sys_errno = 0;
+ int fds[3];
+ int num_fds = 0;
+
+ if (fd == -1) {
+ return -1;
+ }
+ while (fd < 3) {
+ fds[num_fds++] = fd;
+ fd = dup(fd);
+ if (fd == -1) {
+ sys_errno = errno;
+ break;
+ }
+ }
+ for (i=0; i<num_fds; i++) {
+ close(fds[i]);
+ }
+ if (fd == -1) {
+ errno = sys_errno;
+ }
+ return fd;
+}
+
+/****************************************************************************
+ Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
+ else
+ if SYSV use O_NDELAY
+ if BSD use FNDELAY
+ Set close on exec also.
+****************************************************************************/
+
+static int make_safe_fd(int fd)
+{
+ int result, flags;
+ int new_fd = make_nonstd_fd(fd);
+
+ if (new_fd == -1) {
+ goto fail;
+ }
+
+ /* Socket should be nonblocking. */
+
+#ifdef O_NONBLOCK
+#define FLAG_TO_SET O_NONBLOCK
+#else
+#ifdef SYSV
+#define FLAG_TO_SET O_NDELAY
+#else /* BSD */
+#define FLAG_TO_SET FNDELAY
+#endif
+#endif
+
+ if ((flags = fcntl(new_fd, F_GETFL)) == -1) {
+ goto fail;
+ }
+
+ flags |= FLAG_TO_SET;
+ if (fcntl(new_fd, F_SETFL, flags) == -1) {
+ goto fail;
+ }
+
+#undef FLAG_TO_SET
+
+ /* 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) {
+ goto fail;
+ }
+#endif
+ return new_fd;
+
+ fail:
+ if (new_fd != -1) {
+ int sys_errno = errno;
+ close(new_fd);
+ errno = sys_errno;
+ }
+ return -1;
+}
+
+/* Just put a prototype to avoid moving the whole function around */
+static const char *winbindd_socket_dir(void);
+
+struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx, const char* dir)
+{
+ struct wb_context *result;
+
+ result = talloc(mem_ctx, struct wb_context);
+ if (result == NULL) {
+ return NULL;
+ }
+ result->queue = tevent_queue_create(result, "wb_trans");
+ if (result->queue == NULL) {
+ TALLOC_FREE(result);
+ return NULL;
+ }
+ result->fd = -1;
+ result->is_priv = false;
+
+ if (dir != NULL) {
+ result->dir = talloc_strdup(result, dir);
+ } else {
+ result->dir = winbindd_socket_dir();
+ }
+ if (result->dir == NULL) {
+ TALLOC_FREE(result);
+ return NULL;
+ }
+ return result;
+}
+
+struct wb_connect_state {
+ int dummy;
+};
+
+static void wbc_connect_connected(struct tevent_req *subreq);
+
+static struct tevent_req *wb_connect_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct wb_context *wb_ctx,
+ const char *dir)
+{
+ struct tevent_req *result, *subreq;
+ struct wb_connect_state *state;
+ struct sockaddr_un sunaddr;
+ struct stat st;
+ char *path = NULL;
+ wbcErr wbc_err;
+
+ result = tevent_req_create(mem_ctx, &state, struct wb_connect_state);
+ if (result == NULL) {
+ return NULL;
+ }
+
+ if (wb_ctx->fd != -1) {
+ close(wb_ctx->fd);
+ wb_ctx->fd = -1;
+ }
+
+ /* Check permissions on unix socket directory */
+
+ if (lstat(dir, &st) == -1) {
+ wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE;
+ goto post_status;
+ }
+
+ if (!S_ISDIR(st.st_mode) ||
+ (st.st_uid != 0 && st.st_uid != geteuid())) {
+ wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE;
+ goto post_status;
+ }
+
+ /* Connect to socket */
+
+ path = talloc_asprintf(mem_ctx, "%s/%s", dir,
+ WINBINDD_SOCKET_NAME);
+ if (path == NULL) {
+ goto nomem;
+ }
+
+ sunaddr.sun_family = AF_UNIX;
+ strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path));
+ TALLOC_FREE(path);
+
+ /* 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(sunaddr.sun_path, &st) == -1)
+ || !S_ISSOCK(st.st_mode)
+ || (st.st_uid != 0 && st.st_uid != geteuid())) {
+ wbc_err = WBC_ERR_WINBIND_NOT_AVAILABLE;
+ goto post_status;
+ }
+
+ wb_ctx->fd = make_safe_fd(socket(AF_UNIX, SOCK_STREAM, 0));
+ if (wb_ctx->fd == -1) {
+ wbc_err = map_wbc_err_from_errno(errno);
+ goto post_status;
+ }
+
+ subreq = async_connect_send(mem_ctx, ev, wb_ctx->fd,
+ (struct sockaddr *)(void *)&sunaddr,
+ sizeof(sunaddr));
+ if (subreq == NULL) {
+ goto nomem;
+ }
+ tevent_req_set_callback(subreq, wbc_connect_connected, result);
+ return result;
+
+ post_status:
+ tevent_req_error(result, wbc_err);
+ return tevent_req_post(result, ev);
+ nomem:
+ TALLOC_FREE(result);
+ return NULL;
+}
+
+static void wbc_connect_connected(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ int res, err;
+
+ res = async_connect_recv(subreq, &err);
+ TALLOC_FREE(subreq);
+ if (res == -1) {
+ tevent_req_error(req, map_wbc_err_from_errno(err));
+ return;
+ }
+ tevent_req_done(req);
+}
+
+static wbcErr wb_connect_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_wbcerr(req);
+}
+
+static const char *winbindd_socket_dir(void)
+{
+#ifdef SOCKET_WRAPPER
+ const char *env_dir;
+
+ env_dir = getenv(WINBINDD_SOCKET_DIR_ENVVAR);
+ if (env_dir) {
+ return env_dir;
+ }
+#endif
+
+ return WINBINDD_SOCKET_DIR;
+}
+
+struct wb_open_pipe_state {
+ struct wb_context *wb_ctx;
+ struct tevent_context *ev;
+ bool need_priv;
+ struct winbindd_request wb_req;
+};
+
+static void wb_open_pipe_connect_nonpriv_done(struct tevent_req *subreq);
+static void wb_open_pipe_ping_done(struct tevent_req *subreq);
+static void wb_open_pipe_getpriv_done(struct tevent_req *subreq);
+static void wb_open_pipe_connect_priv_done(struct tevent_req *subreq);
+
+static struct tevent_req *wb_open_pipe_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct wb_context *wb_ctx,
+ bool need_priv)
+{
+ struct tevent_req *result, *subreq;
+ struct wb_open_pipe_state *state;
+
+ result = tevent_req_create(mem_ctx, &state, struct wb_open_pipe_state);
+ if (result == NULL) {
+ return NULL;
+ }
+ state->wb_ctx = wb_ctx;
+ state->ev = ev;
+ state->need_priv = need_priv;
+
+ if (wb_ctx->fd != -1) {
+ close(wb_ctx->fd);
+ wb_ctx->fd = -1;
+ }
+
+ subreq = wb_connect_send(state, ev, wb_ctx, wb_ctx->dir);
+ if (subreq == NULL) {
+ goto fail;
+ }
+ tevent_req_set_callback(subreq, wb_open_pipe_connect_nonpriv_done,
+ result);
+ return result;
+
+ fail:
+ TALLOC_FREE(result);
+ return NULL;
+}
+
+static void wb_open_pipe_connect_nonpriv_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_open_pipe_state *state = tevent_req_data(
+ req, struct wb_open_pipe_state);
+ wbcErr wbc_err;
+
+ wbc_err = wb_connect_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!WBC_ERROR_IS_OK(wbc_err)) {
+ state->wb_ctx->is_priv = true;
+ tevent_req_error(req, wbc_err);
+ return;
+ }
+
+ ZERO_STRUCT(state->wb_req);
+ state->wb_req.cmd = WINBINDD_INTERFACE_VERSION;
+ state->wb_req.pid = getpid();
+
+ subreq = wb_simple_trans_send(state, state->ev, NULL,
+ state->wb_ctx->fd, &state->wb_req);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_open_pipe_ping_done, req);
+}
+
+static void wb_open_pipe_ping_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_open_pipe_state *state = tevent_req_data(
+ req, struct wb_open_pipe_state);
+ struct winbindd_response *wb_resp;
+ int ret, err;
+
+ ret = wb_simple_trans_recv(subreq, state, &wb_resp, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ tevent_req_error(req, map_wbc_err_from_errno(err));
+ return;
+ }
+
+ if (!state->need_priv) {
+ tevent_req_done(req);
+ return;
+ }
+
+ state->wb_req.cmd = WINBINDD_PRIV_PIPE_DIR;
+ state->wb_req.pid = getpid();
+
+ subreq = wb_simple_trans_send(state, state->ev, NULL,
+ state->wb_ctx->fd, &state->wb_req);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_open_pipe_getpriv_done, req);
+}
+
+static void wb_open_pipe_getpriv_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_open_pipe_state *state = tevent_req_data(
+ req, struct wb_open_pipe_state);
+ struct winbindd_response *wb_resp = NULL;
+ int ret, err;
+
+ ret = wb_simple_trans_recv(subreq, state, &wb_resp, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ tevent_req_error(req, map_wbc_err_from_errno(err));
+ return;
+ }
+
+ close(state->wb_ctx->fd);
+ state->wb_ctx->fd = -1;
+
+ subreq = wb_connect_send(state, state->ev, state->wb_ctx,
+ (char *)wb_resp->extra_data.data);
+ TALLOC_FREE(wb_resp);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_open_pipe_connect_priv_done, req);
+}
+
+static void wb_open_pipe_connect_priv_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_open_pipe_state *state = tevent_req_data(
+ req, struct wb_open_pipe_state);
+ wbcErr wbc_err;
+
+ wbc_err = wb_connect_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!WBC_ERROR_IS_OK(wbc_err)) {
+ tevent_req_error(req, wbc_err);
+ return;
+ }
+ state->wb_ctx->is_priv = true;
+ tevent_req_done(req);
+}
+
+static wbcErr wb_open_pipe_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_wbcerr(req);
+}
+
+struct wb_trans_state {
+ struct wb_trans_state *prev, *next;
+ struct wb_context *wb_ctx;
+ struct tevent_context *ev;
+ struct winbindd_request *wb_req;
+ struct winbindd_response *wb_resp;
+ bool need_priv;
+};
+
+static bool closed_fd(int fd)
+{
+ struct timeval tv;
+ fd_set r_fds;
+ int selret;
+
+ if (fd == -1) {
+ return true;
+ }
+
+ FD_ZERO(&r_fds);
+ FD_SET(fd, &r_fds);
+ ZERO_STRUCT(tv);
+
+ selret = select(fd+1, &r_fds, NULL, NULL, &tv);
+ if (selret == -1) {
+ return true;
+ }
+ if (selret == 0) {
+ return false;
+ }
+ return (FD_ISSET(fd, &r_fds));
+}
+
+static void wb_trans_trigger(struct tevent_req *req, void *private_data);
+static void wb_trans_connect_done(struct tevent_req *subreq);
+static void wb_trans_done(struct tevent_req *subreq);
+static void wb_trans_retry_wait_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_trans_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct wb_context *wb_ctx, bool need_priv,
+ struct winbindd_request *wb_req)
+{
+ struct tevent_req *req;
+ struct wb_trans_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_trans_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->wb_ctx = wb_ctx;
+ state->ev = ev;
+ state->wb_req = wb_req;
+ state->need_priv = need_priv;
+
+ if (!tevent_queue_add(wb_ctx->queue, ev, req, wb_trans_trigger,
+ NULL)) {
+ tevent_req_nomem(NULL, req);
+ return tevent_req_post(req, ev);
+ }
+ return req;
+}
+
+static void wb_trans_trigger(struct tevent_req *req, void *private_data)
+{
+ struct wb_trans_state *state = tevent_req_data(
+ req, struct wb_trans_state);
+ struct tevent_req *subreq;
+
+ if ((state->wb_ctx->fd != -1) && closed_fd(state->wb_ctx->fd)) {
+ close(state->wb_ctx->fd);
+ state->wb_ctx->fd = -1;
+ }
+
+ if ((state->wb_ctx->fd == -1)
+ || (state->need_priv && !state->wb_ctx->is_priv)) {
+ subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx,
+ state->need_priv);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_trans_connect_done, req);
+ return;
+ }
+
+ state->wb_req->pid = getpid();
+
+ subreq = wb_simple_trans_send(state, state->ev, NULL,
+ state->wb_ctx->fd, state->wb_req);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_trans_done, req);
+}
+
+static bool wb_trans_retry(struct tevent_req *req,
+ struct wb_trans_state *state,
+ wbcErr wbc_err)
+{
+ struct tevent_req *subreq;
+
+ if (WBC_ERROR_IS_OK(wbc_err)) {
+ return false;
+ }
+
+ if (wbc_err == WBC_ERR_WINBIND_NOT_AVAILABLE) {
+ /*
+ * Winbind not around or we can't connect to the pipe. Fail
+ * immediately.
+ */
+ tevent_req_error(req, wbc_err);
+ return true;
+ }
+
+ /*
+ * The transfer as such failed, retry after one second
+ */
+
+ if (state->wb_ctx->fd != -1) {
+ close(state->wb_ctx->fd);
+ state->wb_ctx->fd = -1;
+ }
+
+ subreq = tevent_wakeup_send(state, state->ev,
+ tevent_timeval_current_ofs(1, 0));
+ if (tevent_req_nomem(subreq, req)) {
+ return true;
+ }
+ tevent_req_set_callback(subreq, wb_trans_retry_wait_done, req);
+ return true;
+}
+
+static void wb_trans_retry_wait_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_trans_state *state = tevent_req_data(
+ req, struct wb_trans_state);
+ bool ret;
+
+ ret = tevent_wakeup_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!ret) {
+ tevent_req_error(req, WBC_ERR_UNKNOWN_FAILURE);
+ return;
+ }
+
+ subreq = wb_open_pipe_send(state, state->ev, state->wb_ctx,
+ state->need_priv);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_trans_connect_done, req);
+}
+
+static void wb_trans_connect_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_trans_state *state = tevent_req_data(
+ req, struct wb_trans_state);
+ wbcErr wbc_err;
+
+ wbc_err = wb_open_pipe_recv(subreq);
+ TALLOC_FREE(subreq);
+
+ if (wb_trans_retry(req, state, wbc_err)) {
+ return;
+ }
+
+ subreq = wb_simple_trans_send(state, state->ev, NULL,
+ state->wb_ctx->fd, state->wb_req);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_trans_done, req);
+}
+
+static void wb_trans_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_trans_state *state = tevent_req_data(
+ req, struct wb_trans_state);
+ int ret, err;
+
+ ret = wb_simple_trans_recv(subreq, state, &state->wb_resp, &err);
+ TALLOC_FREE(subreq);
+ if ((ret == -1)
+ && wb_trans_retry(req, state, map_wbc_err_from_errno(err))) {
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+wbcErr wb_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_response **presponse)
+{
+ struct wb_trans_state *state = tevent_req_data(
+ req, struct wb_trans_state);
+ wbcErr wbc_err;
+
+ if (tevent_req_is_wbcerr(req, &wbc_err)) {
+ return wbc_err;
+ }
+
+ *presponse = talloc_move(mem_ctx, &state->wb_resp);
+ return WBC_ERR_SUCCESS;
+}
+
+/********************************************************************
+ * Debug wrapper functions, modeled (with lot's of code copied as is)
+ * after the tevent debug wrapper functions
+ ********************************************************************/
+
+/*
+ this allows the user to choose their own debug function
+*/
+int wbcSetDebug(struct wb_context *wb_ctx,
+ void (*debug)(void *context,
+ enum wbcDebugLevel level,
+ const char *fmt,
+ va_list ap) PRINTF_ATTRIBUTE(3,0),
+ void *context)
+{
+ wb_ctx->debug_ops.debug = debug;
+ wb_ctx->debug_ops.context = context;
+ return 0;
+}
+
+/*
+ debug function for wbcSetDebugStderr
+*/
+static void wbcDebugStderr(void *private_data,
+ enum wbcDebugLevel level,
+ const char *fmt,
+ va_list ap) PRINTF_ATTRIBUTE(3,0);
+static void wbcDebugStderr(void *private_data,
+ enum wbcDebugLevel level,
+ const char *fmt, va_list ap)
+{
+ if (level <= WBC_DEBUG_WARNING) {
+ vfprintf(stderr, fmt, ap);
+ }
+}
+
+/*
+ convenience function to setup debug messages on stderr
+ messages of level WBC_DEBUG_WARNING and higher are printed
+*/
+int wbcSetDebugStderr(struct wb_context *wb_ctx)
+{
+ return wbcSetDebug(wb_ctx, wbcDebugStderr, wb_ctx);
+}
+
+/*
+ * log a message
+ *
+ * The default debug action is to ignore debugging messages.
+ * This is the most appropriate action for a library.
+ * Applications using the library must decide where to
+ * redirect debugging messages
+*/
+void wbcDebug(struct wb_context *wb_ctx, enum wbcDebugLevel level,
+ const char *fmt, ...)
+{
+ va_list ap;
+ if (!wb_ctx) {
+ return;
+ }
+ if (wb_ctx->debug_ops.debug == NULL) {
+ return;
+ }
+ va_start(ap, fmt);
+ wb_ctx->debug_ops.debug(wb_ctx->debug_ops.context, level, fmt, ap);
+ va_end(ap);
+}
diff --git a/nsswitch/libwbclient/wbc_async.h b/nsswitch/libwbclient/wbc_async.h
new file mode 100644
index 0000000000..76e02cadf2
--- /dev/null
+++ b/nsswitch/libwbclient/wbc_async.h
@@ -0,0 +1,95 @@
+/*
+ Unix SMB/CIFS implementation.
+ Headers for the async winbind client library
+ Copyright (C) Volker Lendecke 2008
+
+ ** NOTE! The following LGPL license applies to the wbclient
+ ** library. This does NOT imply that all of Samba is released
+ ** under the LGPL
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 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 Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _WBC_ASYNC_H_
+#define _WBC_ASYNC_H_
+
+#include <talloc.h>
+#include <tevent.h>
+#include "nsswitch/libwbclient/wbclient.h"
+
+struct wb_context;
+struct winbindd_request;
+struct winbindd_response;
+
+enum wbcDebugLevel {
+ WBC_DEBUG_FATAL,
+ WBC_DEBUG_ERROR,
+ WBC_DEBUG_WARNING,
+ WBC_DEBUG_TRACE
+};
+
+struct tevent_req *wb_trans_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct wb_context *wb_ctx, bool need_priv,
+ struct winbindd_request *wb_req);
+wbcErr wb_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_response **presponse);
+struct wb_context *wb_context_init(TALLOC_CTX *mem_ctx, const char* dir);
+int wbcSetDebug(struct wb_context *wb_ctx,
+ void (*debug)(void *context,
+ enum wbcDebugLevel level,
+ const char *fmt,
+ va_list ap) PRINTF_ATTRIBUTE(3,0),
+ void *context);
+int wbcSetDebugStderr(struct wb_context *wb_ctx);
+void wbcDebug(struct wb_context *wb_ctx, enum wbcDebugLevel level,
+ const char *fmt, ...) PRINTF_ATTRIBUTE(3,0);
+
+/* Definitions from wb_reqtrans.c */
+wbcErr map_wbc_err_from_errno(int error);
+
+bool tevent_req_is_wbcerr(struct tevent_req *req, wbcErr *pwbc_err);
+wbcErr tevent_req_simple_recv_wbcerr(struct tevent_req *req);
+
+struct tevent_req *wb_req_read_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ int fd, size_t max_extra_data);
+ssize_t wb_req_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_request **preq, int *err);
+
+struct tevent_req *wb_req_write_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tevent_queue *queue, int fd,
+ struct winbindd_request *wb_req);
+ssize_t wb_req_write_recv(struct tevent_req *req, int *err);
+
+struct tevent_req *wb_resp_read_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev, int fd);
+ssize_t wb_resp_read_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_response **presp, int *err);
+
+struct tevent_req *wb_resp_write_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tevent_queue *queue, int fd,
+ struct winbindd_response *wb_resp);
+ssize_t wb_resp_write_recv(struct tevent_req *req, int *err);
+
+struct tevent_req *wb_simple_trans_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct tevent_queue *queue, int fd,
+ struct winbindd_request *wb_req);
+int wb_simple_trans_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbindd_response **presponse, int *err);
+
+#endif /*_WBC_ASYNC_H_*/
diff --git a/nsswitch/libwbclient/wbc_guid.c b/nsswitch/libwbclient/wbc_guid.c
index c343e24351..d55a197973 100644
--- a/nsswitch/libwbclient/wbc_guid.c
+++ b/nsswitch/libwbclient/wbc_guid.c
@@ -22,6 +22,7 @@
/* Required Headers */
+#include "replace.h"
#include "libwbclient.h"
/* Convert a binary GUID to a character string */
diff --git a/nsswitch/libwbclient/wbc_idmap.c b/nsswitch/libwbclient/wbc_idmap.c
index 5b2ab875f6..10a02fd505 100644
--- a/nsswitch/libwbclient/wbc_idmap.c
+++ b/nsswitch/libwbclient/wbc_idmap.c
@@ -22,6 +22,7 @@
/* Required Headers */
+#include "replace.h"
#include "libwbclient.h"
/* Convert a Windows SID to a Unix uid, allocating an uid if needed */
diff --git a/nsswitch/libwbclient/wbc_pam.c b/nsswitch/libwbclient/wbc_pam.c
index 422665ad2e..4b187273fc 100644
--- a/nsswitch/libwbclient/wbc_pam.c
+++ b/nsswitch/libwbclient/wbc_pam.c
@@ -5,6 +5,7 @@
Copyright (C) Gerald (Jerry) Carter 2007
Copyright (C) Guenther Deschner 2008
+ Copyright (C) Volker Lendecke 2009
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -22,6 +23,7 @@
/* Required Headers */
+#include "replace.h"
#include "libwbclient.h"
/* Authenticate a username/password pair */
@@ -255,7 +257,7 @@ done:
}
static wbcErr wbc_create_logon_info(TALLOC_CTX *mem_ctx,
- const struct winbindd_response *resp,
+ struct winbindd_response *resp,
struct wbcLogonUserInfo **_i)
{
wbcErr wbc_status = WBC_ERR_SUCCESS;
@@ -267,7 +269,8 @@ static wbcErr wbc_create_logon_info(TALLOC_CTX *mem_ctx,
wbc_status = wbc_create_auth_info(i, resp, &i->info);
BAIL_ON_WBC_ERROR(wbc_status);
- if (resp->data.auth.krb5ccname) {
+ if (resp->data.auth.krb5ccname &&
+ strlen(resp->data.auth.krb5ccname)) {
wbc_status = wbcAddNamedBlob(&i->num_blobs,
&i->blobs,
"krb5ccname",
@@ -277,7 +280,8 @@ static wbcErr wbc_create_logon_info(TALLOC_CTX *mem_ctx,
BAIL_ON_WBC_ERROR(wbc_status);
}
- if (resp->data.auth.unix_username) {
+ if (resp->data.auth.unix_username &&
+ strlen(resp->data.auth.unix_username)) {
wbc_status = wbcAddNamedBlob(&i->num_blobs,
&i->blobs,
"unix_username",
@@ -499,6 +503,84 @@ wbcErr wbcCheckTrustCredentials(const char *domain,
struct winbindd_response response;
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if (domain) {
+ strncpy(request.domain_name, domain,
+ sizeof(request.domain_name)-1);
+ }
+
+ /* Send request */
+
+ wbc_status = wbcRequestResponse(WINBINDD_CHECK_MACHACC,
+ &request,
+ &response);
+ if (response.data.auth.nt_status != 0) {
+ if (error) {
+ wbc_status = wbc_create_error_info(NULL,
+ &response,
+ error);
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ wbc_status = WBC_ERR_AUTH_ERROR;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ done:
+ return wbc_status;
+}
+
+/* Trigger a change of the trust credentials for a specific domain */
+wbcErr wbcChangeTrustCredentials(const char *domain,
+ struct wbcAuthErrorInfo **error)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if (domain) {
+ strncpy(request.domain_name, domain,
+ sizeof(request.domain_name)-1);
+ }
+
+ /* Send request */
+
+ wbc_status = wbcRequestResponse(WINBINDD_CHANGE_MACHACC,
+ &request,
+ &response);
+ if (response.data.auth.nt_status != 0) {
+ if (error) {
+ wbc_status = wbc_create_error_info(NULL,
+ &response,
+ error);
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+
+ wbc_status = WBC_ERR_AUTH_ERROR;
+ BAIL_ON_WBC_ERROR(wbc_status);
+ }
+ BAIL_ON_WBC_ERROR(wbc_status);
+
+ done:
+ return wbc_status;
+}
+
+/*
+ * Trigger a no-op NETLOGON call. Lightweight version of
+ * wbcCheckTrustCredentials
+ */
+wbcErr wbcPingDc(const char *domain, struct wbcAuthErrorInfo **error)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+
if (domain) {
/*
* the current protocol doesn't support
@@ -513,7 +595,7 @@ wbcErr wbcCheckTrustCredentials(const char *domain,
/* Send request */
- wbc_status = wbcRequestResponse(WINBINDD_CHECK_MACHACC,
+ wbc_status = wbcRequestResponse(WINBINDD_PING_DC,
&request,
&response);
if (response.data.auth.nt_status != 0) {
@@ -1036,5 +1118,151 @@ wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
struct wbcCredentialCacheInfo **info,
struct wbcAuthErrorInfo **error)
{
- return WBC_ERR_NOT_IMPLEMENTED;
+ wbcErr status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcCredentialCacheInfo *result = NULL;
+ struct winbindd_request request;
+ struct winbindd_response response;
+ struct wbcNamedBlob *initial_blob = NULL;
+ struct wbcNamedBlob *challenge_blob = NULL;
+ int i;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ if (info != NULL) {
+ *info = NULL;
+ }
+ if (error != NULL) {
+ *error = NULL;
+ }
+ if ((params == NULL)
+ || (params->account_name == NULL)
+ || (params->level != WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP)) {
+ status = WBC_ERR_INVALID_PARAM;
+ goto fail;
+ }
+
+ if (params->domain_name != NULL) {
+ status = wbcRequestResponse(WINBINDD_INFO, NULL, &response);
+ if (!WBC_ERROR_IS_OK(status)) {
+ goto fail;
+ }
+ snprintf(request.data.ccache_ntlm_auth.user,
+ sizeof(request.data.ccache_ntlm_auth.user)-1,
+ "%s%c%s", params->domain_name,
+ response.data.info.winbind_separator,
+ params->account_name);
+ } else {
+ strncpy(request.data.ccache_ntlm_auth.user,
+ params->account_name,
+ sizeof(request.data.ccache_ntlm_auth.user)-1);
+ }
+ request.data.ccache_ntlm_auth.uid = getuid();
+
+ for (i=0; i<params->num_blobs; i++) {
+ if (strcasecmp(params->blobs[i].name, "initial_blob") == 0) {
+ initial_blob = &params->blobs[i];
+ break;
+ }
+ if (strcasecmp(params->blobs[i].name, "challenge_blob") == 0) {
+ challenge_blob = &params->blobs[i];
+ break;
+ }
+ }
+
+ request.data.ccache_ntlm_auth.initial_blob_len = 0;
+ request.data.ccache_ntlm_auth.challenge_blob_len = 0;
+ request.extra_len = 0;
+
+ if (initial_blob != NULL) {
+ request.data.ccache_ntlm_auth.initial_blob_len =
+ initial_blob->blob.length;
+ request.extra_len += initial_blob->blob.length;
+ }
+ if (challenge_blob != NULL) {
+ request.data.ccache_ntlm_auth.challenge_blob_len =
+ challenge_blob->blob.length;
+ request.extra_len += challenge_blob->blob.length;
+ }
+
+ if (request.extra_len != 0) {
+ request.extra_data.data = talloc_array(
+ NULL, char, request.extra_len);
+ if (request.extra_data.data == NULL) {
+ status = WBC_ERR_NO_MEMORY;
+ goto fail;
+ }
+ }
+ if (initial_blob != NULL) {
+ memcpy(request.extra_data.data,
+ initial_blob->blob.data, initial_blob->blob.length);
+ }
+ if (challenge_blob != NULL) {
+ memcpy(request.extra_data.data
+ + request.data.ccache_ntlm_auth.initial_blob_len,
+ challenge_blob->blob.data,
+ challenge_blob->blob.length);
+ }
+
+ status = wbcRequestResponse(WINBINDD_CCACHE_NTLMAUTH, &request,
+ &response);
+ if (!WBC_ERROR_IS_OK(status)) {
+ goto fail;
+ }
+
+ result = talloc(NULL, struct wbcCredentialCacheInfo);
+ if (result == NULL) {
+ status = WBC_ERR_NO_MEMORY;
+ goto fail;
+ }
+ result->num_blobs = 0;
+ result->blobs = talloc(result, struct wbcNamedBlob);
+ if (result->blobs == NULL) {
+ status = WBC_ERR_NO_MEMORY;
+ goto fail;
+ }
+ status = wbcAddNamedBlob(&result->num_blobs, &result->blobs,
+ "auth_blob", 0,
+ (uint8_t *)response.extra_data.data,
+ response.data.ccache_ntlm_auth.auth_blob_len);
+ if (!WBC_ERROR_IS_OK(status)) {
+ goto fail;
+ }
+ status = wbcAddNamedBlob(
+ &result->num_blobs, &result->blobs, "session_key", 0,
+ response.data.ccache_ntlm_auth.session_key,
+ sizeof(response.data.ccache_ntlm_auth.session_key));
+ if (!WBC_ERROR_IS_OK(status)) {
+ goto fail;
+ }
+
+ if (response.extra_data.data)
+ free(response.extra_data.data);
+ *info = result;
+ return WBC_ERR_SUCCESS;
+
+fail:
+ TALLOC_FREE(request.extra_data.data);
+ if (response.extra_data.data)
+ free(response.extra_data.data);
+ talloc_free(result);
+ return status;
+}
+
+/* Authenticate a user with cached credentials */
+wbcErr wbcCredentialSave(const char *user, const char *password)
+{
+ struct winbindd_request request;
+ struct winbindd_response response;
+
+ ZERO_STRUCT(request);
+ ZERO_STRUCT(response);
+
+ strncpy(request.data.ccache_save.user, user,
+ sizeof(request.data.ccache_save.user)-1);
+ strncpy(request.data.ccache_save.pass, password,
+ sizeof(request.data.ccache_save.pass)-1);
+ request.data.ccache_save.uid = getuid();
+
+ return wbcRequestResponse(WINBINDD_CCACHE_SAVE, &request, &response);
}
diff --git a/nsswitch/libwbclient/wbc_pwd.c b/nsswitch/libwbclient/wbc_pwd.c
index dacd9499dd..897bf1f5c3 100644
--- a/nsswitch/libwbclient/wbc_pwd.c
+++ b/nsswitch/libwbclient/wbc_pwd.c
@@ -22,6 +22,7 @@
/* Required Headers */
+#include "replace.h"
#include "libwbclient.h"
/** @brief The maximum number of pwent structs to get from winbindd
diff --git a/nsswitch/libwbclient/wbc_sid.c b/nsswitch/libwbclient/wbc_sid.c
index 657c6aec7f..99c9d8e152 100644
--- a/nsswitch/libwbclient/wbc_sid.c
+++ b/nsswitch/libwbclient/wbc_sid.c
@@ -22,6 +22,7 @@
/* Required Headers */
+#include "replace.h"
#include "libwbclient.h"
@@ -813,3 +814,20 @@ wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid,
return wbc_status;
}
+
+const char* wbcSidTypeString(enum wbcSidType type)
+{
+ switch (type) {
+ case WBC_SID_NAME_USE_NONE: return "SID_NONE";
+ case WBC_SID_NAME_USER: return "SID_USER";
+ case WBC_SID_NAME_DOM_GRP: return "SID_DOM_GROUP";
+ case WBC_SID_NAME_DOMAIN: return "SID_DOMAIN";
+ case WBC_SID_NAME_ALIAS: return "SID_ALIAS";
+ case WBC_SID_NAME_WKN_GRP: return "SID_WKN_GROUP";
+ case WBC_SID_NAME_DELETED: return "SID_DELETED";
+ case WBC_SID_NAME_INVALID: return "SID_INVALID";
+ case WBC_SID_NAME_UNKNOWN: return "SID_UNKNOWN";
+ case WBC_SID_NAME_COMPUTER: return "SID_COMPUTER";
+ default: return "Unknown type";
+ }
+}
diff --git a/nsswitch/libwbclient/wbc_util.c b/nsswitch/libwbclient/wbc_util.c
index c39023f15e..16828ae5df 100644
--- a/nsswitch/libwbclient/wbc_util.c
+++ b/nsswitch/libwbclient/wbc_util.c
@@ -22,6 +22,7 @@
/* Required Headers */
+#include "replace.h"
#include "libwbclient.h"
@@ -408,7 +409,7 @@ wbcErr wbcListTrusts(struct wbcDomainInfo **domains, size_t *num_domains)
p = (char *)response.extra_data.data;
- if (strlen(p) == 0) {
+ if ((p == NULL) || (strlen(p) == 0)) {
/* We should always at least get back our
own SAM domain */
@@ -485,7 +486,8 @@ wbcErr wbcLookupDomainController(const char *domain,
ZERO_STRUCT(request);
ZERO_STRUCT(response);
- strncpy(request.domain_name, domain, sizeof(request.domain_name)-1);
+ strncpy(request.data.dsgetdcname.domain_name, domain,
+ sizeof(request.data.dsgetdcname.domain_name)-1);
request.flags = flags;
@@ -499,7 +501,7 @@ wbcErr wbcLookupDomainController(const char *domain,
&response);
BAIL_ON_WBC_ERROR(wbc_status);
- dc->dc_name = talloc_strdup(dc, response.data.dc_name);
+ dc->dc_name = talloc_strdup(dc, response.data.dsgetdcname.dc_unc);
BAIL_ON_PTR_ERROR(dc->dc_name, wbc_status);
*dc_info = dc;
diff --git a/nsswitch/libwbclient/wbclient.c b/nsswitch/libwbclient/wbclient.c
index f5c72315f2..9a1e770690 100644
--- a/nsswitch/libwbclient/wbclient.c
+++ b/nsswitch/libwbclient/wbclient.c
@@ -22,6 +22,9 @@
/* Required Headers */
+#include "replace.h"
+#include "talloc.h"
+#include "tevent.h"
#include "libwbclient.h"
/* From wb_common.c */
diff --git a/nsswitch/libwbclient/wbclient.h b/nsswitch/libwbclient/wbclient.h
index d3c1b634f5..ac206909b0 100644
--- a/nsswitch/libwbclient/wbclient.h
+++ b/nsswitch/libwbclient/wbclient.h
@@ -4,6 +4,7 @@
Winbind client API
Copyright (C) Gerald (Jerry) Carter 2007
+ Copyright (C) Volker Lendecke 2009
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -62,9 +63,11 @@ const char *wbcErrorString(wbcErr error);
* Added wbcRemoveGidMapping()
* 0.3: Added wbcGetpwsid()
* Added wbcGetSidAliases()
+ * 0.4: Added wbcSidTypeString()
+ * 0.5: Added wbcChangeTrustCredentials()
**/
#define WBCLIENT_MAJOR_VERSION 0
-#define WBCLIENT_MINOR_VERSION 3
+#define WBCLIENT_MINOR_VERSION 5
#define WBCLIENT_VENDOR_VERSION "Samba libwbclient"
struct wbcLibraryDetails {
uint16_t major_version;
@@ -507,6 +510,15 @@ void wbcFreeMemory(void*);
*/
/**
+ * @brief Get a string representation of the SID type
+ *
+ * @param type type of the SID
+ *
+ * @return string representation of the SID type
+ */
+const char* wbcSidTypeString(enum wbcSidType type);
+
+/**
* @brief Convert a binary SID to a character string
*
* @param sid Binary Security Identifier
@@ -1141,6 +1153,16 @@ wbcErr wbcCredentialCache(struct wbcCredentialCacheParams *params,
struct wbcCredentialCacheInfo **info,
struct wbcAuthErrorInfo **error);
+/**
+ * @brief Save a password with winbind for doing wbcCredentialCache() later
+ *
+ * @param *user Username
+ * @param *password Password
+ *
+ * @return #wbcErr
+ **/
+wbcErr wbcCredentialSave(const char *user, const char *password);
+
/**********************************************************
* Resolve functions
**********************************************************/
@@ -1173,6 +1195,29 @@ wbcErr wbcResolveWinsByIP(const char *ip, char **name);
/**
* @brief Trigger a verification of the trust credentials of a specific domain
*
+ * @param *domain The name of the domain.
+ * @param error Output details on WBC_ERR_AUTH_ERROR
+ *
+ * @return #wbcErr
+ **/
+wbcErr wbcCheckTrustCredentials(const char *domain,
+ struct wbcAuthErrorInfo **error);
+
+/**
+ * @brief Trigger a change of the trust credentials for a specific domain
+ *
+ * @param *domain The name of the domain.
+ * @param error Output details on WBC_ERR_AUTH_ERROR
+ *
+ * @return #wbcErr
+ **/
+wbcErr wbcChangeTrustCredentials(const char *domain,
+ struct wbcAuthErrorInfo **error);
+
+/**
+ * @brief Trigger a no-op call through the NETLOGON pipe. Low-cost
+ * version of wbcCheckTrustCredentials
+ *
* @param *domain The name of the domain, only NULL for the default domain is
* supported yet. Other values than NULL will result in
* WBC_ERR_NOT_IMPLEMENTED.
@@ -1180,8 +1225,7 @@ wbcErr wbcResolveWinsByIP(const char *ip, char **name);
*
* @return #wbcErr
**/
-wbcErr wbcCheckTrustCredentials(const char *domain,
- struct wbcAuthErrorInfo **error);
+wbcErr wbcPingDc(const char *domain, struct wbcAuthErrorInfo **error);
/**********************************************************
* Helper functions
diff --git a/nsswitch/libwbclient/wbclient_internal.h b/nsswitch/libwbclient/wbclient_internal.h
index fc03c5409b..2d103ab3df 100644
--- a/nsswitch/libwbclient/wbclient_internal.h
+++ b/nsswitch/libwbclient/wbclient_internal.h
@@ -28,5 +28,4 @@ wbcErr wbcRequestResponse(int cmd,
struct winbindd_request *request,
struct winbindd_response *response);
-
#endif /* _WBCLIENT_INTERNAL_H */
diff --git a/nsswitch/nsstest.h b/nsswitch/nsstest.h
index e69f17c857..53adce5500 100644
--- a/nsswitch/nsstest.h
+++ b/nsswitch/nsstest.h
@@ -3,17 +3,21 @@
nss includes for the nss tester
Copyright (C) Kai Blin 2007
- 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 3 of the License, or
- (at your option) any later version.
+ ** NOTE! The following LGPL license applies to the nsstest
+ ** header. This does NOT imply that all of Samba is released
+ ** under the LGPL
- This program is distributed in the hope that it will be useful,
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 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 General Public License for more details.
+ 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 General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
diff --git a/nsswitch/pam_winbind.c b/nsswitch/pam_winbind.c
index b411eb7f77..b80203674b 100644
--- a/nsswitch/pam_winbind.c
+++ b/nsswitch/pam_winbind.c
@@ -11,6 +11,8 @@
*/
#include "pam_winbind.h"
+#define CONST_DISCARD(type,ptr) ((type)(void *)ptr)
+
static int wbc_error_to_pam_error(wbcErr status)
{
@@ -410,49 +412,51 @@ static int _pam_parse(const pam_handle_t *pamh,
config_file = PAM_WINBIND_CONFIG_FILE;
}
- d = iniparser_load(config_file);
+ d = iniparser_load(CONST_DISCARD(char *, config_file));
if (d == NULL) {
goto config_from_pam;
}
- if (iniparser_getboolean(d, "global:debug", false)) {
+ if (iniparser_getboolean(d, CONST_DISCARD(char *, "global:debug"), false)) {
ctrl |= WINBIND_DEBUG_ARG;
}
- if (iniparser_getboolean(d, "global:debug_state", false)) {
+ if (iniparser_getboolean(d, CONST_DISCARD(char *, "global:debug_state"), false)) {
ctrl |= WINBIND_DEBUG_STATE;
}
- if (iniparser_getboolean(d, "global:cached_login", false)) {
+ if (iniparser_getboolean(d, CONST_DISCARD(char *, "global:cached_login"), false)) {
ctrl |= WINBIND_CACHED_LOGIN;
}
- if (iniparser_getboolean(d, "global:krb5_auth", false)) {
+ if (iniparser_getboolean(d, CONST_DISCARD(char *, "global:krb5_auth"), false)) {
ctrl |= WINBIND_KRB5_AUTH;
}
- if (iniparser_getboolean(d, "global:silent", false)) {
+ if (iniparser_getboolean(d, CONST_DISCARD(char *, "global:silent"), false)) {
ctrl |= WINBIND_SILENT;
}
- if (iniparser_getstr(d, "global:krb5_ccache_type") != NULL) {
+ if (iniparser_getstr(d, CONST_DISCARD(char *, "global:krb5_ccache_type")) != NULL) {
ctrl |= WINBIND_KRB5_CCACHE_TYPE;
}
- if ((iniparser_getstr(d, "global:require-membership-of") != NULL) ||
- (iniparser_getstr(d, "global:require_membership_of") != NULL)) {
+ if ((iniparser_getstr(d, CONST_DISCARD(char *, "global:require-membership-of"))
+ != NULL) ||
+ (iniparser_getstr(d, CONST_DISCARD(char *, "global:require_membership_of"))
+ != NULL)) {
ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
}
- if (iniparser_getboolean(d, "global:try_first_pass", false)) {
+ if (iniparser_getboolean(d, CONST_DISCARD(char *, "global:try_first_pass"), false)) {
ctrl |= WINBIND_TRY_FIRST_PASS_ARG;
}
- if (iniparser_getint(d, "global:warn_pwd_expire", 0)) {
+ if (iniparser_getint(d, CONST_DISCARD(char *, "global:warn_pwd_expire"), 0)) {
ctrl |= WINBIND_WARN_PWD_EXPIRE;
}
- if (iniparser_getboolean(d, "global:mkhomedir", false)) {
+ if (iniparser_getboolean(d, CONST_DISCARD(char *, "global:mkhomedir"), false)) {
ctrl |= WINBIND_MKHOMEDIR;
}
@@ -803,6 +807,43 @@ static int wbc_auth_error_to_pam_error(struct pwb_context *ctx,
return pam_winbind_request_log(ctx, ret, username, fn);
}
+#if defined(HAVE_PAM_RADIO_TYPE)
+static bool _pam_winbind_change_pwd(struct pwb_context *ctx)
+{
+ struct pam_message msg, *pmsg;
+ struct pam_response *resp = NULL;
+ const char *prompt;
+ int ret;
+ bool retval = false;
+ prompt = _("Do you want to change your password now?");
+ pmsg = &msg;
+ msg.msg_style = PAM_RADIO_TYPE;
+ msg.msg = prompt;
+ ret = converse(ctx->pamh, 1, &pmsg, &resp);
+ if (resp == NULL) {
+ if (ret == PAM_SUCCESS) {
+ _pam_log(ctx, LOG_CRIT, "pam_winbind: system error!\n");
+ return false;
+ }
+ }
+ if (ret != PAM_SUCCESS) {
+ return false;
+ }
+ _pam_log(ctx, LOG_CRIT, "Received [%s] reply from application.\n", resp->resp);
+
+ if (strcasecmp(resp->resp, "yes") == 0) {
+ retval = true;
+ }
+
+ _pam_drop_reply(resp, 1);
+ return retval;
+}
+#else
+static bool _pam_winbind_change_pwd(struct pwb_context *ctx)
+{
+ return false;
+}
+#endif
/**
* send a password expiry message if required
@@ -819,15 +860,22 @@ static bool _pam_send_password_expiry_message(struct pwb_context *ctx,
time_t next_change,
time_t now,
int warn_pwd_expire,
- bool *already_expired)
+ bool *already_expired,
+ bool *change_pwd)
{
int days = 0;
struct tm tm_now, tm_next_change;
+ bool retval = false;
+ int ret;
if (already_expired) {
*already_expired = false;
}
+ if (change_pwd) {
+ *change_pwd = false;
+ }
+
if (next_change <= now) {
PAM_WB_REMARK_DIRECT(ctx, "NT_STATUS_PASSWORD_EXPIRED");
if (already_expired) {
@@ -850,15 +898,61 @@ static bool _pam_send_password_expiry_message(struct pwb_context *ctx,
(tm_now.tm_yday+tm_now.tm_year*365);
if (days == 0) {
- _make_remark(ctx, PAM_TEXT_INFO,
- _("Your password expires today"));
+ ret = _make_remark(ctx, PAM_TEXT_INFO,
+ _("Your password expires today.\n"));
+
+ /*
+ * If change_pwd and already_expired is null.
+ * We are just sending a notification message.
+ * We don't expect any response in this case.
+ */
+
+ if (!change_pwd && !already_expired) {
+ return true;
+ }
+
+ /*
+ * successfully sent the warning message.
+ * Give the user a chance to change pwd.
+ */
+ if (ret == PAM_SUCCESS) {
+ if (change_pwd) {
+ retval = _pam_winbind_change_pwd(ctx);
+ if (retval) {
+ *change_pwd = true;
+ }
+ }
+ }
return true;
}
if (days > 0 && days < warn_pwd_expire) {
- _make_remark_format(ctx, PAM_TEXT_INFO,
- _("Your password will expire in %d %s"),
- days, (days > 1) ? _("days"):_("day"));
+
+ ret = _make_remark_format(ctx, PAM_TEXT_INFO,
+ _("Your password will expire in %d %s.\n"),
+ days, (days > 1) ? _("days"):_("day"));
+ /*
+ * If change_pwd and already_expired is null.
+ * We are just sending a notification message.
+ * We don't expect any response in this case.
+ */
+
+ if (!change_pwd && !already_expired) {
+ return true;
+ }
+
+ /*
+ * successfully sent the warning message.
+ * Give the user a chance to change pwd.
+ */
+ if (ret == PAM_SUCCESS) {
+ if (change_pwd) {
+ retval = _pam_winbind_change_pwd(ctx);
+ if (retval) {
+ *change_pwd = true;
+ }
+ }
+ }
return true;
}
@@ -879,7 +973,8 @@ static void _pam_warn_password_expiry(struct pwb_context *ctx,
const struct wbcAuthUserInfo *info,
const struct wbcUserPasswordPolicyInfo *policy,
int warn_pwd_expire,
- bool *already_expired)
+ bool *already_expired,
+ bool *change_pwd)
{
time_t now = time(NULL);
time_t next_change = 0;
@@ -892,6 +987,10 @@ static void _pam_warn_password_expiry(struct pwb_context *ctx,
*already_expired = false;
}
+ if (change_pwd) {
+ *change_pwd = false;
+ }
+
/* accounts with WBC_ACB_PWNOEXP set never receive a warning */
if (info->acct_flags & WBC_ACB_PWNOEXP) {
return;
@@ -907,7 +1006,8 @@ static void _pam_warn_password_expiry(struct pwb_context *ctx,
if (_pam_send_password_expiry_message(ctx, next_change, now,
warn_pwd_expire,
- already_expired)) {
+ already_expired,
+ change_pwd)) {
return;
}
@@ -923,7 +1023,8 @@ static void _pam_warn_password_expiry(struct pwb_context *ctx,
if (_pam_send_password_expiry_message(ctx, next_change, now,
warn_pwd_expire,
- already_expired)) {
+ already_expired,
+ change_pwd)) {
return;
}
@@ -1752,11 +1853,13 @@ static int winbind_auth_request(struct pwb_context *ctx,
if ((ret == PAM_SUCCESS) && user_info && policy && info) {
bool already_expired = false;
+ bool change_pwd = false;
/* warn a user if the password is about to expire soon */
_pam_warn_password_expiry(ctx, user_info, policy,
warn_pwd_expire,
- &already_expired);
+ &already_expired,
+ &change_pwd);
if (already_expired == true) {
@@ -1766,15 +1869,20 @@ static int winbind_auth_request(struct pwb_context *ctx,
"Password has expired "
"(Password was last set: %lld, "
"the policy says it should expire here "
- "%lld (now it's: %lu))\n",
+ "%lld (now it's: %ld))\n",
(long long int)last_set,
(long long int)last_set +
policy->expire,
- time(NULL));
+ (long)time(NULL));
return PAM_AUTHTOK_EXPIRED;
}
+ if (change_pwd) {
+ ret = PAM_NEW_AUTHTOK_REQD;
+ goto done;
+ }
+
/* inform about logon type */
_pam_warn_logon_type(ctx, user, user_info->user_flags);
@@ -2331,7 +2439,6 @@ static char* winbind_upn_to_username(struct pwb_context *ctx,
if (!name) {
return NULL;
}
-
if ((p = strchr(name, '@')) != NULL) {
*p = 0;
domain = p + 1;
@@ -3132,7 +3239,7 @@ int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
* expire soon */
_pam_warn_password_expiry(ctx, user_info, policy,
warn_pwd_expire,
- NULL);
+ NULL, NULL);
/* set some info3 info for other modules in the
* stack */
diff --git a/nsswitch/tests/test_wbinfo.sh b/nsswitch/tests/test_wbinfo.sh
index 2e94c24640..8d8f116e70 100755
--- a/nsswitch/tests/test_wbinfo.sh
+++ b/nsswitch/tests/test_wbinfo.sh
@@ -150,8 +150,10 @@ testfail "wbinfo -Y against $TARGET using invalid SID" $wbinfo -Y "S-1-22-1-3000
testit "wbinfo -t against $TARGET" $wbinfo -t || failed=`expr $failed + 1`
-testit "wbinfo --trusted-domains against $TARGET" $wbinfo --trusted-domains || failed=`expr $failed + 1`
-testit "wbinfo --all-domains against $TARGET" $wbinfo --all-domains || failed=`expr $failed + 1`
+#didn't really work anyway
+knownfail "wbinfo --trusted-domains against $TARGET" $wbinfo --trusted-domains || failed=`expr $failed + 1`
+knownfail "wbinfo --all-domains against $TARGET" $wbinfo --all-domains || failed=`expr $failed + 1`
+
testit "wbinfo --own-domain against $TARGET" $wbinfo --own-domain || failed=`expr $failed + 1`
echo "test: wbinfo --own-domain against $TARGET check output"
@@ -165,7 +167,9 @@ fi
# this does not work
knownfail "wbinfo --sequence against $TARGET" $wbinfo --sequence
-knownfail "wbinfo -D against $TARGET" $wbinfo -D $DOMAIN || failed=`expr $failed + 1`
+
+# this is stubbed out now
+testit "wbinfo -D against $TARGET" $wbinfo -D $DOMAIN || failed=`expr $failed + 1`
testit "wbinfo -i against $TARGET" $wbinfo -i "$DOMAIN/$USERNAME" || failed=`expr $failed + 1`
diff --git a/nsswitch/wbinfo.c b/nsswitch/wbinfo.c
index d12e512166..a43ce8f4c9 100644
--- a/nsswitch/wbinfo.c
+++ b/nsswitch/wbinfo.c
@@ -4,7 +4,8 @@
Winbind status program.
Copyright (C) Tim Potter 2000-2003
- Copyright (C) Andrew Bartlett 2002
+ Copyright (C) Andrew Bartlett 2002-2007
+ Copyright (C) Volker Lendecke 2009
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
@@ -23,9 +24,16 @@
#include "includes.h"
#include "winbind_client.h"
#include "libwbclient/wbclient.h"
+#include "lib/popt/popt.h"
+#include "../libcli/auth/libcli_auth.h"
+#if !(_SAMBA_VERSION_) < 4
+#include "lib/cmdline/popt_common.h"
+#endif
+#ifdef DBGC_CLASS
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
+#endif
static struct wbcInterfaceDetails *init_interface_details(void)
{
@@ -38,13 +46,14 @@ static struct wbcInterfaceDetails *init_interface_details(void)
wbc_status = wbcInterfaceDetails(&details);
if (!WBC_ERROR_IS_OK(wbc_status)) {
- d_fprintf(stderr, "could not obtain winbind interface details!\n");
+ d_fprintf(stderr, "could not obtain winbind interface "
+ "details!\n");
}
return details;
}
-static char winbind_separator_int(bool strict)
+static char winbind_separator(void)
{
struct wbcInterfaceDetails *details;
static bool got_sep;
@@ -57,11 +66,7 @@ static char winbind_separator_int(bool strict)
if (!details) {
d_fprintf(stderr, "could not obtain winbind separator!\n");
- if (strict) {
- return 0;
- }
- /* HACK: (this module should not call lp_ funtions) */
- return *lp_winbind_separator();
+ return 0;
}
sep = details->winbind_separator;
@@ -69,21 +74,12 @@ static char winbind_separator_int(bool strict)
if (!sep) {
d_fprintf(stderr, "winbind separator was NULL!\n");
- if (strict) {
- return 0;
- }
- /* HACK: (this module should not call lp_ funtions) */
- sep = *lp_winbind_separator();
+ return 0;
}
return sep;
}
-static char winbind_separator(void)
-{
- return winbind_separator_int(false);
-}
-
static const char *get_winbind_domain(void)
{
static struct wbcInterfaceDetails *details;
@@ -92,14 +88,26 @@ static const char *get_winbind_domain(void)
if (!details) {
d_fprintf(stderr, "could not obtain winbind domain name!\n");
-
- /* HACK: (this module should not call lp_ functions) */
- return lp_workgroup();
+ return 0;
}
return details->netbios_domain;
}
+static const char *get_winbind_netbios_name(void)
+{
+ static struct wbcInterfaceDetails *details;
+
+ details = init_interface_details();
+
+ if (!details) {
+ d_fprintf(stderr, "could not obtain winbind netbios name!\n");
+ return 0;
+ }
+
+ return details->netbios_name;
+}
+
/* Copy of parse_domain_user from winbindd_util.c. Parse a string of the
form DOMAIN/user into a domain and a user */
@@ -232,17 +240,25 @@ static bool wbinfo_get_groupinfo(const char *group)
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
struct group *grp;
+ char **mem;
wbc_status = wbcGetgrnam(group, &grp);
if (!WBC_ERROR_IS_OK(wbc_status)) {
return false;
}
- d_printf("%s:%s:%u\n",
+ d_printf("%s:%s:%u:",
grp->gr_name,
grp->gr_passwd,
(unsigned int)grp->gr_gid);
+ mem = grp->gr_mem;
+ while (*mem != NULL) {
+ d_printf("%s%s", *mem, *(mem+1) != NULL ? "," : "");
+ mem += 1;
+ }
+ d_printf("\n");
+
wbcFreeMemory(grp);
return true;
@@ -253,17 +269,25 @@ static bool wbinfo_get_gidinfo(int gid)
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
struct group *grp;
+ char **mem;
wbc_status = wbcGetgrgid(gid, &grp);
if (!WBC_ERROR_IS_OK(wbc_status)) {
return false;
}
- d_printf("%s:%s:%u\n",
+ d_printf("%s:%s:%u:",
grp->gr_name,
grp->gr_passwd,
(unsigned int)grp->gr_gid);
+ mem = grp->gr_mem;
+ while (*mem != NULL) {
+ d_printf("%s%s", *mem, *(mem+1) != NULL ? "," : "");
+ mem += 1;
+ }
+ d_printf("\n");
+
wbcFreeMemory(grp);
return true;
@@ -549,7 +573,8 @@ static bool wbinfo_list_own_domain(void)
/* show sequence numbers */
static bool wbinfo_show_sequence(const char *domain)
{
- d_printf("This command has been deprecated. Please use the --online-status option instead.\n");
+ d_printf("This command has been deprecated. Please use the "
+ "--online-status option instead.\n");
return false;
}
@@ -575,7 +600,8 @@ static bool wbinfo_show_onlinestatus(const char *domain)
}
}
- is_offline = (domain_list[i].domain_flags & WBC_DOMINFO_DOMAIN_OFFLINE);
+ is_offline = (domain_list[i].domain_flags &
+ WBC_DOMINFO_DOMAIN_OFFLINE);
d_printf("%s : %s\n",
domain_list[i].short_name,
@@ -594,7 +620,7 @@ static bool wbinfo_domain_info(const char *domain)
struct wbcDomainInfo *dinfo = NULL;
char *sid_str = NULL;
- if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')) {
+ if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')){
domain = get_winbind_domain();
}
@@ -621,10 +647,12 @@ static bool wbinfo_domain_info(const char *domain)
d_printf("Active Directory : %s\n",
(dinfo->domain_flags & WBC_DOMINFO_DOMAIN_AD) ? "Yes" : "No");
d_printf("Native : %s\n",
- (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_NATIVE) ? "Yes" : "No");
+ (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_NATIVE) ?
+ "Yes" : "No");
d_printf("Primary : %s\n",
- (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_PRIMARY) ? "Yes" : "No");
+ (dinfo->domain_flags & WBC_DOMINFO_DOMAIN_PRIMARY) ?
+ "Yes" : "No");
wbcFreeMemory(sid_str);
wbcFreeMemory(dinfo);
@@ -645,9 +673,9 @@ static bool wbinfo_getdcname(const char *domain_name)
/* Send request */
- if (winbindd_request_response(WINBINDD_GETDCNAME, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- d_fprintf(stderr, "Could not get dc name for %s\n", domain_name);
+ if (winbindd_request_response(WINBINDD_GETDCNAME, &request,
+ &response) != NSS_STATUS_SUCCESS) {
+ d_fprintf(stderr, "Could not get dc name for %s\n",domain_name);
return false;
}
@@ -661,50 +689,107 @@ static bool wbinfo_getdcname(const char *domain_name)
/* Find a DC */
static bool wbinfo_dsgetdcname(const char *domain_name, uint32_t flags)
{
- struct winbindd_request request;
- struct winbindd_response response;
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcDomainControllerInfoEx *dc_info;
+ char *str = NULL;
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
+ wbc_status = wbcLookupDomainControllerEx(domain_name, NULL, NULL,
+ flags | DS_DIRECTORY_SERVICE_REQUIRED,
+ &dc_info);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ printf("Could not find dc for %s\n", domain_name);
+ return false;
+ }
- fstrcpy(request.data.dsgetdcname.domain_name, domain_name);
- request.data.dsgetdcname.flags = flags;
+ wbcGuidToString(dc_info->domain_guid, &str);
- request.flags |= DS_DIRECTORY_SERVICE_REQUIRED;
+ d_printf("%s\n", dc_info->dc_unc);
+ d_printf("%s\n", dc_info->dc_address);
+ d_printf("%d\n", dc_info->dc_address_type);
+ d_printf("%s\n", str);
+ d_printf("%s\n", dc_info->domain_name);
+ d_printf("%s\n", dc_info->forest_name);
+ d_printf("0x%08x\n", dc_info->dc_flags);
+ d_printf("%s\n", dc_info->dc_site_name);
+ d_printf("%s\n", dc_info->client_site_name);
- /* Send request */
+ return true;
+}
+
+/* Check trust account password */
+
+static bool wbinfo_check_secret(const char *domain)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcAuthErrorInfo *error = NULL;
+ const char *domain_name;
+
+ if (domain) {
+ domain_name = domain;
+ } else {
+ domain_name = get_winbind_domain();
+ }
- if (winbindd_request_response(WINBINDD_DSGETDCNAME, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- d_fprintf(stderr, "Could not find dc for %s\n", domain_name);
+ wbc_status = wbcCheckTrustCredentials(domain_name, &error);
+
+ d_printf("checking the trust secret for domain %s via RPC calls %s\n",
+ domain_name,
+ WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
+
+ if (wbc_status == WBC_ERR_AUTH_ERROR) {
+ d_fprintf(stderr, "error code was %s (0x%x)\n",
+ error->nt_string, error->nt_status);
+ wbcFreeMemory(error);
+ }
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
return false;
}
- /* Display response */
+ return true;
+}
- d_printf("%s\n", response.data.dsgetdcname.dc_unc);
- d_printf("%s\n", response.data.dsgetdcname.dc_address);
- d_printf("%d\n", response.data.dsgetdcname.dc_address_type);
- d_printf("%s\n", response.data.dsgetdcname.domain_guid);
- d_printf("%s\n", response.data.dsgetdcname.domain_name);
- d_printf("%s\n", response.data.dsgetdcname.forest_name);
- d_printf("0x%08x\n", response.data.dsgetdcname.dc_flags);
- d_printf("%s\n", response.data.dsgetdcname.dc_site_name);
- d_printf("%s\n", response.data.dsgetdcname.client_site_name);
+/* Change trust account password */
+
+static bool wbinfo_change_secret(const char *domain)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ struct wbcAuthErrorInfo *error = NULL;
+ const char *domain_name;
+
+ if (domain) {
+ domain_name = domain;
+ } else {
+ domain_name = get_winbind_domain();
+ }
+
+ wbc_status = wbcChangeTrustCredentials(domain_name, &error);
+
+ d_printf("changing the trust secret for domain %s via RPC calls %s\n",
+ domain_name,
+ WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
+
+ if (wbc_status == WBC_ERR_AUTH_ERROR) {
+ d_fprintf(stderr, "error code was %s (0x%x)\n",
+ error->nt_string, error->nt_status);
+ wbcFreeMemory(error);
+ }
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ return false;
+ }
return true;
}
-/* Check trust account password */
+/* Check DC connection */
-static bool wbinfo_check_secret(void)
+static bool wbinfo_ping_dc(void)
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
struct wbcAuthErrorInfo *error = NULL;
- wbc_status = wbcCheckTrustCredentials(NULL, &error);
+ wbc_status = wbcPingDc(NULL, &error);
- d_printf("checking the trust secret via RPC calls %s\n",
+ d_printf("checking the NETLOGON dc connection %s\n",
WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
if (wbc_status == WBC_ERR_AUTH_ERROR) {
@@ -1038,13 +1123,13 @@ static bool wbinfo_lookuprids(const char *domain, const char *arg)
enum wbcSidType *types = NULL;
size_t i;
int num_rids;
- uint32 *rids = NULL;
+ uint32_t *rids = NULL;
const char *p;
char *ridstr;
TALLOC_CTX *mem_ctx = NULL;
bool ret = false;
- if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')) {
+ if ((domain == NULL) || (strequal(domain, ".")) || (domain[0] == '\0')){
domain = get_winbind_domain();
}
@@ -1068,8 +1153,13 @@ static bool wbinfo_lookuprids(const char *domain, const char *arg)
p = arg;
while (next_token_talloc(mem_ctx, &p, &ridstr, " ,\n")) {
- uint32 rid = strtoul(ridstr, NULL, 10);
- ADD_TO_ARRAY(mem_ctx, uint32, rid, &rids, &num_rids);
+ uint32_t rid = strtoul(ridstr, NULL, 10);
+ rids = talloc_realloc(mem_ctx, rids, uint32_t, num_rids + 1);
+ if (rids == NULL) {
+ d_printf("talloc_realloc failed\n");
+ }
+ rids[num_rids] = rid;
+ num_rids += 1;
}
if (rids == NULL) {
@@ -1089,7 +1179,7 @@ static bool wbinfo_lookuprids(const char *domain, const char *arg)
for (i=0; i<num_rids; i++) {
d_printf("%8d: %s (%s)\n", rids[i], names[i],
- sid_type_lookup(types[i]));
+ wbcSidTypeString(types[i]));
}
ret = true;
@@ -1139,20 +1229,21 @@ static bool wbinfo_lookupname(const char *full_name)
/* Display response */
- d_printf("%s %s (%d)\n", sid_str, sid_type_lookup(type), type);
+ d_printf("%s %s (%d)\n", sid_str, wbcSidTypeString(type), type);
wbcFreeMemory(sid_str);
return true;
}
-static char *wbinfo_prompt_pass(const char *prefix,
+static char *wbinfo_prompt_pass(TALLOC_CTX *mem_ctx,
+ const char *prefix,
const char *username)
{
char *prompt;
const char *ret = NULL;
- prompt = talloc_asprintf(talloc_tos(), "Enter %s's ", username);
+ prompt = talloc_asprintf(mem_ctx, "Enter %s's ", username);
if (!prompt) {
return NULL;
}
@@ -1170,73 +1261,124 @@ static char *wbinfo_prompt_pass(const char *prefix,
ret = getpass(prompt);
TALLOC_FREE(prompt);
- return SMB_STRDUP(ret);
+ return talloc_strdup(mem_ctx, ret);
}
/* Authenticate a user with a plaintext password */
-static bool wbinfo_auth_krb5(char *username, const char *cctype, uint32 flags)
+static bool wbinfo_auth_krb5(char *username, const char *cctype, uint32_t flags)
{
- struct winbindd_request request;
- struct winbindd_response response;
- NSS_STATUS result;
- char *p;
- char *password;
-
- /* Send off request */
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ char *s = NULL;
+ char *p = NULL;
+ char *password = NULL;
+ char *name = NULL;
+ char *local_cctype = NULL;
+ uid_t uid;
+ struct wbcLogonUserParams params;
+ struct wbcLogonUserInfo *info;
+ struct wbcAuthErrorInfo *error;
+ struct wbcUserPasswordPolicyInfo *policy;
+ TALLOC_CTX *frame = talloc_tos();
- p = strchr(username, '%');
+ if ((s = talloc_strdup(frame, username)) == NULL) {
+ return false;
+ }
- if (p) {
+ if ((p = strchr(s, '%')) != NULL) {
*p = 0;
- fstrcpy(request.data.auth.user, username);
- fstrcpy(request.data.auth.pass, p + 1);
- *p = '%';
+ p++;
+ password = talloc_strdup(frame, p);
} else {
- fstrcpy(request.data.auth.user, username);
- password = wbinfo_prompt_pass(NULL, username);
- fstrcpy(request.data.auth.pass, password);
- SAFE_FREE(password);
+ password = wbinfo_prompt_pass(frame, NULL, username);
}
- request.flags = flags;
+ local_cctype = talloc_strdup(frame, cctype);
- fstrcpy(request.data.auth.krb5_cc_type, cctype);
+ name = s;
- request.data.auth.uid = geteuid();
+ uid = geteuid();
- result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
+ params.username = name;
+ params.password = password;
+ params.num_blobs = 0;
+ params.blobs = NULL;
- /* Display response */
+ wbc_status = wbcAddNamedBlob(&params.num_blobs,
+ &params.blobs,
+ "flags",
+ 0,
+ (uint8_t *)&flags,
+ sizeof(flags));
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ goto done;
+ }
- d_printf("plaintext kerberos password authentication for [%s] %s (requesting cctype: %s)\n",
- username, (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", cctype);
+ wbc_status = wbcAddNamedBlob(&params.num_blobs,
+ &params.blobs,
+ "user_uid",
+ 0,
+ (uint8_t *)&uid,
+ sizeof(uid));
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ goto done;
+ }
- if (response.data.auth.nt_status)
- d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status,
- response.data.auth.error_string);
+ wbc_status = wbcAddNamedBlob(&params.num_blobs,
+ &params.blobs,
+ "krb5_cc_type",
+ 0,
+ (uint8_t *)local_cctype,
+ strlen(cctype)+1);
+ if (!WBC_ERROR_IS_OK(wbc_status)) {
+ goto done;
+ }
+
+ wbc_status = wbcLogonUser(&params, &info, &error, &policy);
+
+ d_printf("plaintext kerberos password authentication for [%s] %s "
+ "(requesting cctype: %s)\n",
+ username, WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed",
+ cctype);
- if (result == NSS_STATUS_SUCCESS) {
+ if (error) {
+ d_fprintf(stderr,
+ "error code was %s (0x%x)\nerror messsage was: %s\n",
+ error->nt_string,
+ error->nt_status,
+ error->display_string);
+ }
- if (request.flags & WBFLAG_PAM_INFO3_TEXT) {
- if (response.data.auth.info3.user_flgs & NETLOGON_CACHED_ACCOUNT) {
- d_printf("user_flgs: NETLOGON_CACHED_ACCOUNT\n");
+ if (WBC_ERROR_IS_OK(wbc_status)) {
+ if (flags & WBFLAG_PAM_INFO3_TEXT) {
+ if (info && info->info && info->info->user_flags &
+ NETLOGON_CACHED_ACCOUNT) {
+ d_printf("user_flgs: "
+ "NETLOGON_CACHED_ACCOUNT\n");
}
}
- if (response.data.auth.krb5ccname[0] != '\0') {
- d_printf("credentials were put in: %s\n", response.data.auth.krb5ccname);
+ if (info) {
+ int i;
+ for (i=0; i < info->num_blobs; i++) {
+ if (strequal(info->blobs[i].name,
+ "krb5ccname")) {
+ d_printf("credentials were put "
+ "in: %s\n",
+ (const char *)
+ info->blobs[i].blob.data);
+ break;
+ }
+ }
} else {
d_printf("no credentials cached\n");
}
}
+ done:
- return result == NSS_STATUS_SUCCESS;
+ wbcFreeMemory(params.blobs);
+
+ return WBC_ERROR_IS_OK(wbc_status);
}
/* Authenticate a user with a plaintext password */
@@ -1248,17 +1390,18 @@ static bool wbinfo_auth(char *username)
char *p = NULL;
char *password = NULL;
char *name = NULL;
+ TALLOC_CTX *frame = talloc_tos();
- if ((s = SMB_STRDUP(username)) == NULL) {
+ if ((s = talloc_strdup(frame, username)) == NULL) {
return false;
}
if ((p = strchr(s, '%')) != NULL) {
*p = 0;
p++;
- password = SMB_STRDUP(p);
+ password = talloc_strdup(frame, p);
} else {
- password = wbinfo_prompt_pass(NULL, username);
+ password = wbinfo_prompt_pass(frame, NULL, username);
}
name = s;
@@ -1270,21 +1413,19 @@ static bool wbinfo_auth(char *username)
#if 0
if (response.data.auth.nt_status)
- d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
+ d_fprintf(stderr,
+ "error code was %s (0x%x)\nerror messsage was: %s\n",
response.data.auth.nt_status_string,
response.data.auth.nt_status,
response.data.auth.error_string);
#endif
- SAFE_FREE(s);
- SAFE_FREE(password);
-
return WBC_ERROR_IS_OK(wbc_status);
}
/* Authenticate a user with a challenge/response */
-static bool wbinfo_auth_crap(char *username)
+static bool wbinfo_auth_crap(char *username, bool use_ntlmv2, bool use_lanman)
{
wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
struct wbcAuthUserParams params;
@@ -1296,14 +1437,15 @@ static bool wbinfo_auth_crap(char *username)
fstring name_domain;
char *pass;
char *p;
+ TALLOC_CTX *frame = talloc_tos();
p = strchr(username, '%');
if (p) {
*p = 0;
- pass = SMB_STRDUP(p + 1);
+ pass = talloc_strdup(frame, p + 1);
} else {
- pass = wbinfo_prompt_pass(NULL, username);
+ pass = wbinfo_prompt_pass(frame, NULL, username);
}
parse_wbinfo_domain_user(username, name_domain, name_user);
@@ -1320,31 +1462,35 @@ static bool wbinfo_auth_crap(char *username)
generate_random_buffer(params.password.response.challenge, 8);
- if (lp_client_ntlmv2_auth()) {
+ if (use_ntlmv2) {
DATA_BLOB server_chal;
DATA_BLOB names_blob;
server_chal = data_blob(params.password.response.challenge, 8);
/* Pretend this is a login to 'us', for blob purposes */
- names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup());
+ names_blob = NTLMv2_generate_names_blob(NULL,
+ get_winbind_netbios_name(),
+ get_winbind_domain());
- if (!SMBNTLMv2encrypt(name_user, name_domain, pass, &server_chal,
+ if (!SMBNTLMv2encrypt(NULL, name_user, name_domain, pass,
+ &server_chal,
&names_blob,
- &lm, &nt, NULL)) {
+ &lm, &nt, NULL, NULL)) {
data_blob_free(&names_blob);
data_blob_free(&server_chal);
- SAFE_FREE(pass);
+ TALLOC_FREE(pass);
return false;
}
data_blob_free(&names_blob);
data_blob_free(&server_chal);
} else {
- if (lp_client_lanman_auth()) {
+ if (use_lanman) {
bool ok;
lm = data_blob(NULL, 24);
- ok = SMBencrypt(pass, params.password.response.challenge,
+ ok = SMBencrypt(pass,
+ params.password.response.challenge,
lm.data);
if (!ok) {
data_blob_free(&lm);
@@ -1368,7 +1514,8 @@ static bool wbinfo_auth_crap(char *username)
WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
if (wbc_status == WBC_ERR_AUTH_ERROR) {
- d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
+ d_fprintf(stderr,
+ "error code was %s (0x%x)\nerror messsage was: %s\n",
err->nt_string,
err->nt_status,
err->display_string);
@@ -1379,11 +1526,48 @@ static bool wbinfo_auth_crap(char *username)
data_blob_free(&nt);
data_blob_free(&lm);
- SAFE_FREE(pass);
return WBC_ERROR_IS_OK(wbc_status);
}
+/* Save creds with winbind */
+
+static bool wbinfo_ccache_save(char *username)
+{
+ wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
+ char *s = NULL;
+ char *p = NULL;
+ char *password = NULL;
+ char *name = NULL;
+ TALLOC_CTX *frame = talloc_stackframe();
+
+ s = talloc_strdup(frame, username);
+ if (s == NULL) {
+ return false;
+ }
+
+ p = strchr(s, '%');
+ if (p != NULL) {
+ *p = 0;
+ p++;
+ password = talloc_strdup(frame, p);
+ } else {
+ password = wbinfo_prompt_pass(frame, NULL, username);
+ }
+
+ name = s;
+
+ wbc_status = wbcCredentialSave(name, password);
+
+ d_printf("saving creds %s\n",
+ WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
+
+ TALLOC_FREE(frame);
+
+ return WBC_ERROR_IS_OK(wbc_status);
+}
+
+#ifdef WITH_FAKE_KASERVER
/* Authenticate a user with a plaintext password and set a token */
static bool wbinfo_klog(char *username)
@@ -1412,7 +1596,8 @@ static bool wbinfo_klog(char *username)
request.flags |= WBFLAG_PAM_AFS_TOKEN;
- result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
+ result = winbindd_request_response(WINBINDD_PAM_AUTH, &request,
+ &response);
/* Display response */
@@ -1420,7 +1605,8 @@ static bool wbinfo_klog(char *username)
(result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
if (response.data.auth.nt_status)
- d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
+ d_fprintf(stderr,
+ "error code was %s (0x%x)\nerror messsage was: %s\n",
response.data.auth.nt_status_string,
response.data.auth.nt_status,
response.data.auth.error_string);
@@ -1441,6 +1627,13 @@ static bool wbinfo_klog(char *username)
d_printf("Successfully created AFS token\n");
return true;
}
+#else
+static bool wbinfo_klog(char *username)
+{
+ d_fprintf(stderr, "No AFS support compiled in.\n");
+ return false;
+}
+#endif
/* Print domain users */
@@ -1506,92 +1699,15 @@ static bool print_domain_groups(const char *domain)
static bool wbinfo_set_auth_user(char *username)
{
- const char *password;
- char *p;
- fstring user, domain;
-
- /* Separate into user and password */
-
- parse_wbinfo_domain_user(username, domain, user);
-
- p = strchr(user, '%');
-
- if (p != NULL) {
- *p = 0;
- password = p+1;
- } else {
- char *thepass = getpass("Password: ");
- if (thepass) {
- password = thepass;
- } 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;
+ d_fprintf(stderr, "This functionality was moved to the 'net' utility.\n"
+ "See 'net help setauthuser' for details.\n");
+ return false;
}
static void wbinfo_get_auth_user(void)
{
- char *user, *domain, *password;
-
- /* Lift data from secrets file */
-
- secrets_fetch_ipc_userpass(&user, &domain, &password);
-
- if ((!user || !*user) && (!domain || !*domain ) && (!password || !*password)){
-
- SAFE_FREE(user);
- SAFE_FREE(domain);
- SAFE_FREE(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 ? lp_winbind_separator(): "",
- user, password ? "%" : "", password ? password : "");
-
- SAFE_FREE(user);
- SAFE_FREE(domain);
- SAFE_FREE(password);
+ d_fprintf(stderr, "This functionality was moved to the 'net' utility.\n"
+ "See 'net help getauthuser' for details.\n");
}
static bool wbinfo_ping(void)
@@ -1613,20 +1729,18 @@ static bool wbinfo_change_user_password(const char *username)
wbcErr wbc_status;
char *old_password = NULL;
char *new_password = NULL;
+ TALLOC_CTX *frame = talloc_tos();
- old_password = wbinfo_prompt_pass("old", username);
- new_password = wbinfo_prompt_pass("new", username);
+ old_password = wbinfo_prompt_pass(frame, "old", username);
+ new_password = wbinfo_prompt_pass(frame, "new", username);
- wbc_status = wbcChangeUserPassword(username, old_password, new_password);
+ wbc_status = wbcChangeUserPassword(username, old_password,new_password);
/* Display response */
d_printf("Password change for user %s %s\n", username,
WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");
- SAFE_FREE(old_password);
- SAFE_FREE(new_password);
-
return WBC_ERROR_IS_OK(wbc_status);
}
@@ -1658,7 +1772,11 @@ enum {
OPT_VERBOSE,
OPT_ONLINESTATUS,
OPT_CHANGE_USER_PASSWORD,
- OPT_SID_TO_FULLNAME
+ OPT_PING_DC,
+ OPT_CCACHE_SAVE,
+ OPT_SID_TO_FULLNAME,
+ OPT_NTLMV2,
+ OPT_LANMAN
};
int main(int argc, char **argv, char **envp)
@@ -1673,6 +1791,8 @@ int main(int argc, char **argv, char **envp)
int int_subarg = -1;
int result = 1;
bool verbose = false;
+ bool use_ntlmv2 = false;
+ bool use_lanman = false;
struct poptOption long_options[] = {
POPT_AUTOHELP
@@ -1702,6 +1822,9 @@ int main(int argc, char **argv, char **envp)
{ "remove-uid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_REMOVE_UID_MAPPING, "Remove uid to sid mapping in idmap", "UID,SID" },
{ "remove-gid-mapping", 0, POPT_ARG_STRING, &string_arg, OPT_REMOVE_GID_MAPPING, "Remove gid to sid mapping in idmap", "GID,SID" },
{ "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
+ { "change-secret", 'c', POPT_ARG_NONE, 0, 'c', "Change shared secret" },
+ { "ping-dc", 0, POPT_ARG_NONE, 0, OPT_PING_DC,
+ "Check the NETLOGON connection" },
{ "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
{ "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" },
{ "own-domain", 0, POPT_ARG_NONE, 0, OPT_LIST_OWN_DOMAIN, "List own domain" },
@@ -1720,6 +1843,9 @@ int main(int argc, char **argv, char **envp)
{ "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" },
{ "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" },
{ "set-auth-user", 0, POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" },
+ { "ccache-save", 0, POPT_ARG_STRING, &string_arg,
+ OPT_CCACHE_SAVE, "Store user and password for ccache "
+ "operation", "user%password" },
{ "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME,
"Get a DC name for a foreign domain", "domainname" },
{ "dsgetdcname", 0, POPT_ARG_STRING, &string_arg, OPT_DSGETDCNAME, "Find a DC for a domain", "domainname" },
@@ -1737,7 +1863,8 @@ int main(int argc, char **argv, char **envp)
{ "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL },
{ "verbose", 0, POPT_ARG_NONE, 0, OPT_VERBOSE, "Print additional information per command", NULL },
{ "change-user-password", 0, POPT_ARG_STRING, &string_arg, OPT_CHANGE_USER_PASSWORD, "Change the password for a user", NULL },
- POPT_COMMON_CONFIGFILE
+ { "ntlmv2", 0, POPT_ARG_NONE, 0, OPT_NTLMV2, "Use NTLMv2 cryptography for user authentication", NULL},
+ { "lanman", 0, POPT_ARG_NONE, 0, OPT_LANMAN, "Use lanman cryptography for user authentication", NULL},
POPT_COMMON_VERSION
POPT_TABLEEND
};
@@ -1748,7 +1875,8 @@ int main(int argc, char **argv, char **envp)
/* Parse options */
- pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0);
+ pc = poptGetContext("wbinfo", argc, (const char **)argv,
+ long_options, 0);
/* Parse command line options */
@@ -1761,24 +1889,19 @@ int main(int argc, char **argv, char **envp)
/* get the generic configuration parameters like --domain */
switch (opt) {
case OPT_VERBOSE:
- verbose = True;
+ verbose = true;
+ break;
+ case OPT_NTLMV2:
+ use_ntlmv2 = true;
+ break;
+ case OPT_LANMAN:
+ use_lanman = true;
break;
}
}
poptFreeContext(pc);
- if (!lp_load(get_dyn_CONFIGFILE(), true, false, false, true)) {
- d_fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n",
- get_dyn_CONFIGFILE(), strerror(errno));
- exit(1);
- }
-
- if (!init_names())
- return 1;
-
- load_interfaces();
-
pc = poptGetContext(NULL, argc, (const char **)argv, long_options,
POPT_CONTEXT_KEEP_FIRST);
@@ -1786,19 +1909,23 @@ int main(int argc, char **argv, char **envp)
switch (opt) {
case 'u':
if (!print_domain_users(opt_domain_name)) {
- d_fprintf(stderr, "Error looking up domain users\n");
+ d_fprintf(stderr,
+ "Error looking up domain users\n");
goto done;
}
break;
case 'g':
if (!print_domain_groups(opt_domain_name)) {
- d_fprintf(stderr, "Error looking up domain groups\n");
+ d_fprintf(stderr,
+ "Error looking up domain groups\n");
goto done;
}
break;
case 's':
if (!wbinfo_lookupsid(string_arg)) {
- d_fprintf(stderr, "Could not lookup sid %s\n", string_arg);
+ d_fprintf(stderr,
+ "Could not lookup sid %s\n",
+ string_arg);
goto done;
}
break;
@@ -1811,52 +1938,63 @@ int main(int argc, char **argv, char **envp)
break;
case 'R':
if (!wbinfo_lookuprids(opt_domain_name, string_arg)) {
- d_fprintf(stderr, "Could not lookup RIDs %s\n", string_arg);
+ d_fprintf(stderr, "Could not lookup RIDs %s\n",
+ string_arg);
goto done;
}
break;
case 'n':
if (!wbinfo_lookupname(string_arg)) {
- d_fprintf(stderr, "Could not lookup name %s\n", string_arg);
+ d_fprintf(stderr, "Could not lookup name %s\n",
+ string_arg);
goto done;
}
break;
case 'N':
if (!wbinfo_wins_byname(string_arg)) {
- d_fprintf(stderr, "Could not lookup WINS by name %s\n", string_arg);
+ d_fprintf(stderr,
+ "Could not lookup WINS by name %s\n",
+ string_arg);
goto done;
}
break;
case 'I':
if (!wbinfo_wins_byip(string_arg)) {
- d_fprintf(stderr, "Could not lookup WINS by IP %s\n", string_arg);
+ d_fprintf(stderr,
+ "Could not lookup WINS by IP %s\n",
+ string_arg);
goto done;
}
break;
case 'U':
if (!wbinfo_uid_to_sid(int_arg)) {
- d_fprintf(stderr, "Could not convert uid %d to sid\n", int_arg);
+ d_fprintf(stderr,
+ "Could not convert uid %d to sid\n",
+ int_arg);
goto done;
}
break;
case 'G':
if (!wbinfo_gid_to_sid(int_arg)) {
- d_fprintf(stderr, "Could not convert gid %d to sid\n",
- int_arg);
+ d_fprintf(stderr,
+ "Could not convert gid %d to sid\n",
+ int_arg);
goto done;
}
break;
case 'S':
if (!wbinfo_sid_to_uid(string_arg)) {
- d_fprintf(stderr, "Could not convert sid %s to uid\n",
- string_arg);
+ d_fprintf(stderr,
+ "Could not convert sid %s to uid\n",
+ string_arg);
goto done;
}
break;
case 'Y':
if (!wbinfo_sid_to_gid(string_arg)) {
- d_fprintf(stderr, "Could not convert sid %s to gid\n",
- string_arg);
+ d_fprintf(stderr,
+ "Could not convert sid %s to gid\n",
+ string_arg);
goto done;
}
break;
@@ -1915,46 +2053,64 @@ int main(int argc, char **argv, char **envp)
}
break;
case 't':
- if (!wbinfo_check_secret()) {
+ if (!wbinfo_check_secret(opt_domain_name)) {
d_fprintf(stderr, "Could not check secret\n");
goto done;
}
break;
+ case 'c':
+ if (!wbinfo_change_secret(opt_domain_name)) {
+ d_fprintf(stderr, "Could not change secret\n");
+ goto done;
+ }
+ break;
+ case OPT_PING_DC:
+ if (!wbinfo_ping_dc()) {
+ d_fprintf(stderr, "Could not ping our DC\n");
+ goto done;
+ }
+ break;
case 'm':
if (!wbinfo_list_domains(false, verbose)) {
- d_fprintf(stderr, "Could not list trusted domains\n");
+ d_fprintf(stderr,
+ "Could not list trusted domains\n");
goto done;
}
break;
case OPT_SEQUENCE:
if (!wbinfo_show_sequence(opt_domain_name)) {
- d_fprintf(stderr, "Could not show sequence numbers\n");
+ d_fprintf(stderr,
+ "Could not show sequence numbers\n");
goto done;
}
break;
case OPT_ONLINESTATUS:
if (!wbinfo_show_onlinestatus(opt_domain_name)) {
- d_fprintf(stderr, "Could not show online-status\n");
+ d_fprintf(stderr,
+ "Could not show online-status\n");
goto done;
}
break;
case 'D':
if (!wbinfo_domain_info(string_arg)) {
- d_fprintf(stderr, "Could not get domain info\n");
+ d_fprintf(stderr,
+ "Could not get domain info\n");
goto done;
}
break;
case 'i':
if (!wbinfo_get_userinfo(string_arg)) {
- d_fprintf(stderr, "Could not get info for user %s\n",
- string_arg);
+ d_fprintf(stderr,
+ "Could not get info for user %s\n",
+ string_arg);
goto done;
}
break;
case OPT_USER_SIDINFO:
if ( !wbinfo_get_user_sidinfo(string_arg)) {
- d_fprintf(stderr, "Could not get info for user sid %s\n",
- string_arg);
+ d_fprintf(stderr,
+ "Could not get info for user "
+ "sid %s\n", string_arg);
goto done;
}
break;
@@ -1981,27 +2137,31 @@ int main(int argc, char **argv, char **envp)
break;
case 'r':
if (!wbinfo_get_usergroups(string_arg)) {
- d_fprintf(stderr, "Could not get groups for user %s\n",
- string_arg);
+ d_fprintf(stderr,
+ "Could not get groups for user %s\n",
+ string_arg);
goto done;
}
break;
case OPT_USERSIDS:
if (!wbinfo_get_usersids(string_arg)) {
- d_fprintf(stderr, "Could not get group SIDs for user SID %s\n",
- string_arg);
+ d_fprintf(stderr, "Could not get group SIDs "
+ "for user SID %s\n",
+ string_arg);
goto done;
}
break;
case OPT_USERDOMGROUPS:
if (!wbinfo_get_userdomgroups(string_arg)) {
- d_fprintf(stderr, "Could not get user's domain groups "
- "for user SID %s\n", string_arg);
+ d_fprintf(stderr, "Could not get user's domain "
+ "groups for user SID %s\n",
+ string_arg);
goto done;
}
break;
case OPT_SIDALIASES:
- if (!wbinfo_get_sidaliases(opt_domain_name, string_arg)) {
+ if (!wbinfo_get_sidaliases(opt_domain_name,
+ string_arg)) {
d_fprintf(stderr, "Could not get sid aliases "
"for user SID %s\n", string_arg);
goto done;
@@ -2011,14 +2171,19 @@ int main(int argc, char **argv, char **envp)
bool got_error = false;
if (!wbinfo_auth(string_arg)) {
- d_fprintf(stderr, "Could not authenticate user %s with "
- "plaintext password\n", string_arg);
+ d_fprintf(stderr,
+ "Could not authenticate user "
+ "%s with plaintext "
+ "password\n", string_arg);
got_error = true;
}
- if (!wbinfo_auth_crap(string_arg)) {
- d_fprintf(stderr, "Could not authenticate user %s with "
- "challenge/response\n", string_arg);
+ if (!wbinfo_auth_crap(string_arg, use_ntlmv2,
+ use_lanman)) {
+ d_fprintf(stderr,
+ "Could not authenticate user "
+ "%s with challenge/response\n",
+ string_arg);
got_error = true;
}
@@ -2027,14 +2192,19 @@ int main(int argc, char **argv, char **envp)
break;
}
case 'K': {
- uint32 flags = WBFLAG_PAM_KRB5 |
- WBFLAG_PAM_CACHED_LOGIN |
+ uint32_t flags = WBFLAG_PAM_KRB5 |
+ WBFLAG_PAM_CACHED_LOGIN |
WBFLAG_PAM_FALLBACK_AFTER_KRB5 |
- WBFLAG_PAM_INFO3_TEXT;
-
- if (!wbinfo_auth_krb5(string_arg, "FILE", flags)) {
- d_fprintf(stderr, "Could not authenticate user [%s] with "
- "Kerberos (ccache: %s)\n", string_arg, "FILE");
+ WBFLAG_PAM_INFO3_TEXT |
+ WBFLAG_PAM_CONTACT_TRUSTDOM;
+
+ if (!wbinfo_auth_krb5(string_arg, "FILE",
+ flags)) {
+ d_fprintf(stderr,
+ "Could not authenticate user "
+ "[%s] with Kerberos "
+ "(ccache: %s)\n", string_arg,
+ "FILE");
goto done;
}
break;
@@ -2058,6 +2228,12 @@ int main(int argc, char **argv, char **envp)
break;
case OPT_GET_AUTH_USER:
wbinfo_get_auth_user();
+ goto done;
+ break;
+ case OPT_CCACHE_SAVE:
+ if (!wbinfo_ccache_save(string_arg)) {
+ goto done;
+ }
break;
case OPT_GETDCNAME:
if (!wbinfo_getdcname(string_arg)) {
@@ -2070,7 +2246,7 @@ int main(int argc, char **argv, char **envp)
}
break;
case OPT_SEPARATOR: {
- const char sep = winbind_separator_int(true);
+ const char sep = winbind_separator();
if ( !sep ) {
goto done;
}
@@ -2089,7 +2265,8 @@ int main(int argc, char **argv, char **envp)
break;
case OPT_CHANGE_USER_PASSWORD:
if (!wbinfo_change_user_password(string_arg)) {
- d_fprintf(stderr, "Could not change user password "
+ d_fprintf(stderr,
+ "Could not change user password "
"for user %s\n", string_arg);
goto done;
}
@@ -2100,6 +2277,10 @@ int main(int argc, char **argv, char **envp)
break;
case OPT_VERBOSE:
break;
+ case OPT_NTLMV2:
+ break;
+ case OPT_LANMAN:
+ break;
default:
d_fprintf(stderr, "Invalid option\n");
poptPrintHelp(pc, stderr, 0);
@@ -2112,7 +2293,7 @@ int main(int argc, char **argv, char **envp)
/* Exit code */
done:
- talloc_destroy(frame);
+ talloc_free(frame);
poptFreeContext(pc);
return result;
diff --git a/nsswitch/wbinfo4.c b/nsswitch/wbinfo4.c
deleted file mode 100644
index bb6d7a8cf9..0000000000
--- a/nsswitch/wbinfo4.c
+++ /dev/null
@@ -1,1331 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Winbind status program.
-
- Copyright (C) Tim Potter 2000-2003
- Copyright (C) Andrew Bartlett 2002-2007
-
- 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 3 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, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "includes.h"
-#include "winbind_client.h"
-#include "librpc/gen_ndr/ndr_netlogon.h"
-#include "libcli/auth/libcli_auth.h"
-#include "libcli/security/security.h"
-#include "lib/cmdline/popt_common.h"
-#include "dynconfig/dynconfig.h"
-#include "param/param.h"
-
-#ifndef fstrcpy
-#define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1)
-#endif
-
-extern int winbindd_fd;
-
-static char winbind_separator_int(bool strict)
-{
- 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_response(WINBINDD_INFO, NULL, &response) !=
- NSS_STATUS_SUCCESS) {
- d_fprintf(stderr, "could not obtain winbind separator!\n");
- if (strict) {
- return 0;
- }
- /* HACK: (this module should not call lp_ funtions) */
- return *lp_winbind_separator(cmdline_lp_ctx);
- }
-
- sep = response.data.info.winbind_separator;
- got_sep = true;
-
- if (!sep) {
- d_fprintf(stderr, "winbind separator was NULL!\n");
- if (strict) {
- return 0;
- }
- /* HACK: (this module should not call lp_ funtions) */
- sep = *lp_winbind_separator(cmdline_lp_ctx);
- }
-
- return sep;
-}
-
-static char winbind_separator(void)
-{
- return winbind_separator_int(false);
-}
-
-static const char *get_winbind_domain(void)
-{
- struct winbindd_response response;
- static fstring winbind_domain;
-
- ZERO_STRUCT(response);
-
- /* Send off request */
-
- if (winbindd_request_response(WINBINDD_DOMAIN_NAME, NULL, &response) !=
- NSS_STATUS_SUCCESS) {
- d_fprintf(stderr, "could not obtain winbind domain name!\n");
-
- /* HACK: (this module should not call lp_ funtions) */
- return lp_workgroup(cmdline_lp_ctx);
- }
-
- 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_m(domain);
-
- return true;
-}
-
-/* pull pwent info for a given user */
-
-static bool wbinfo_get_userinfo(char *user)
-{
- struct winbindd_request request;
- struct winbindd_response response;
- NSS_STATUS result;
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- /* Send request */
-
- fstrcpy(request.data.username, user);
-
- result = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response);
-
- if (result != NSS_STATUS_SUCCESS)
- return false;
-
- d_printf( "%s:%s:%d:%d:%s:%s:%s\n",
- response.data.pw.pw_name,
- response.data.pw.pw_passwd,
- response.data.pw.pw_uid,
- response.data.pw.pw_gid,
- response.data.pw.pw_gecos,
- response.data.pw.pw_dir,
- response.data.pw.pw_shell );
-
- return true;
-}
-
-/* pull pwent info for a given uid */
-static bool wbinfo_get_uidinfo(int uid)
-{
- struct winbindd_request request;
- struct winbindd_response response;
- NSS_STATUS result;
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- request.data.uid = uid;
-
- result = winbindd_request_response(WINBINDD_GETPWUID, &request, &response);
-
- if (result != NSS_STATUS_SUCCESS)
- return false;
-
- d_printf( "%s:%s:%d:%d:%s:%s:%s\n",
- response.data.pw.pw_name,
- response.data.pw.pw_passwd,
- response.data.pw.pw_uid,
- response.data.pw.pw_gid,
- response.data.pw.pw_gecos,
- response.data.pw.pw_dir,
- response.data.pw.pw_shell );
-
- return true;
-}
-
-/* pull grent for a given group */
-static bool wbinfo_get_groupinfo(char *group)
-{
- struct winbindd_request request;
- struct winbindd_response response;
- NSS_STATUS result;
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- /* Send request */
-
- fstrcpy(request.data.groupname, group);
-
- result = winbindd_request_response(WINBINDD_GETGRNAM, &request,
- &response);
-
- if ( result != NSS_STATUS_SUCCESS)
- return false;
-
- d_printf( "%s:%s:%d\n",
- response.data.gr.gr_name,
- response.data.gr.gr_passwd,
- response.data.gr.gr_gid );
-
- return true;
-}
-
-/* pull grent for a given gid */
-static bool wbinfo_get_gidinfo(int gid)
-{
- struct winbindd_request request;
- struct winbindd_response response;
- NSS_STATUS result;
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- /* Send request */
-
- request.data.gid = gid;
-
- result = winbindd_request_response(WINBINDD_GETGRGID, &request,
- &response);
-
- if ( result != NSS_STATUS_SUCCESS)
- return false;
-
- d_printf( "%s:%s:%d\n",
- response.data.gr.gr_name,
- response.data.gr.gr_passwd,
- response.data.gr.gr_gid );
-
- 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(request);
- ZERO_STRUCT(response);
-
- /* Send request */
-
- fstrcpy(request.data.username, user);
-
- result = winbindd_request_response(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.data)[i]);
-
- SAFE_FREE(response.extra_data.data);
-
- return true;
-}
-
-
-/* List group SIDs a user SID is a member of */
-static bool wbinfo_get_usersids(char *user_sid)
-{
- struct winbindd_request request;
- struct winbindd_response response;
- NSS_STATUS result;
- int i;
- const char *s;
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- /* Send request */
- fstrcpy(request.data.sid, user_sid);
-
- result = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response);
-
- if (result != NSS_STATUS_SUCCESS)
- return false;
-
- s = (const char *)response.extra_data.data;
- for (i = 0; i < response.data.num_entries; i++) {
- d_printf("%s\n", s);
- s += strlen(s) + 1;
- }
-
- SAFE_FREE(response.extra_data.data);
-
- return true;
-}
-
-static bool wbinfo_get_userdomgroups(const char *user_sid)
-{
- struct winbindd_request request;
- struct winbindd_response response;
- NSS_STATUS result;
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- /* Send request */
- fstrcpy(request.data.sid, user_sid);
-
- result = winbindd_request_response(WINBINDD_GETUSERDOMGROUPS, &request,
- &response);
-
- if (result != NSS_STATUS_SUCCESS)
- return false;
-
- if (response.data.num_entries != 0)
- printf("%s", (char *)response.extra_data.data);
-
- SAFE_FREE(response.extra_data.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_response(WINBINDD_WINS_BYNAME, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- return false;
- }
-
- /* Display response */
-
- d_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_response(WINBINDD_WINS_BYIP, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- return false;
- }
-
- /* Display response */
-
- d_printf("%s\n", response.data.winsresp);
-
- return true;
-}
-
-/* List trusted domains */
-
-static bool wbinfo_list_domains(bool list_all_domains)
-{
- struct winbindd_request request;
- struct winbindd_response response;
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- /* Send request */
-
- request.data.list_all_domains = list_all_domains;
-
- if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, &request, &response) !=
- NSS_STATUS_SUCCESS)
- return false;
-
- /* Display response */
-
- if (response.extra_data.data) {
- const char *extra_data = (char *)response.extra_data.data;
- fstring name;
- char *p;
-
- while(next_token(&extra_data, name, "\n", sizeof(fstring))) {
- p = strchr(name, '\\');
- if (p == 0) {
- d_fprintf(stderr, "Got invalid response: %s\n",
- extra_data);
- return false;
- }
- *p = 0;
- d_printf("%s\n", name);
- }
-
- SAFE_FREE(response.extra_data.data);
- }
-
- return true;
-}
-
-/* List own domain */
-
-static bool wbinfo_list_own_domain(void)
-{
- d_printf("%s\n", get_winbind_domain());
-
- return true;
-}
-
-/* show sequence numbers */
-static bool wbinfo_show_sequence(const char *domain)
-{
- struct winbindd_request request;
- struct winbindd_response response;
-
- ZERO_STRUCT(response);
- ZERO_STRUCT(request);
-
- if ( domain )
- fstrcpy( request.domain_name, domain );
-
- /* Send request */
-
- if (winbindd_request_response(WINBINDD_SHOW_SEQUENCE, &request, &response) !=
- NSS_STATUS_SUCCESS)
- return false;
-
- /* Display response */
-
- if (response.extra_data.data) {
- char *extra_data = (char *)response.extra_data.data;
- d_printf("%s", extra_data);
- SAFE_FREE(response.extra_data.data);
- }
-
- return true;
-}
-
-/* Show domain info */
-
-static bool wbinfo_domain_info(const char *domain_name)
-{
- struct winbindd_request request;
- struct winbindd_response response;
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- if ((strequal(domain_name, ".")) || (domain_name[0] == '\0'))
- fstrcpy(request.domain_name, get_winbind_domain());
- else
- fstrcpy(request.domain_name, domain_name);
-
- /* Send request */
-
- if (winbindd_request_response(WINBINDD_DOMAIN_INFO, &request, &response) !=
- NSS_STATUS_SUCCESS)
- return false;
-
- /* Display response */
-
- d_printf("Name : %s\n", response.data.domain_info.name);
- d_printf("Alt_Name : %s\n", response.data.domain_info.alt_name);
-
- d_printf("SID : %s\n", response.data.domain_info.sid);
-
- d_printf("Active Directory : %s\n",
- response.data.domain_info.active_directory ? "Yes" : "No");
- d_printf("Native : %s\n",
- response.data.domain_info.native_mode ? "Yes" : "No");
-
- d_printf("Primary : %s\n",
- response.data.domain_info.primary ? "Yes" : "No");
-
- return true;
-}
-
-/* Get a foreign DC's name */
-static bool wbinfo_getdcname(const char *domain_name)
-{
- struct winbindd_request request;
- struct winbindd_response response;
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- fstrcpy(request.domain_name, domain_name);
-
- /* Send request */
-
- if (winbindd_request_response(WINBINDD_GETDCNAME, &request, &response) !=
- NSS_STATUS_SUCCESS) {
- d_fprintf(stderr, "Could not get dc name for %s\n", domain_name);
- return false;
- }
-
- /* Display response */
-
- d_printf("%s\n", response.data.dc_name);
-
- 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_response(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_fprintf(stderr, "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_response(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_response(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_response(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_response(WINBINDD_SID_TO_GID, &request, &response) !=
- NSS_STATUS_SUCCESS)
- return false;
-
- /* Display response */
-
- d_printf("%d\n", (int)response.data.gid);
-
- return true;
-}
-
-static const char *sid_type_lookup(enum lsa_SidType r)
-{
- switch (r) {
- case SID_NAME_USE_NONE: return "SID_NAME_USE_NONE"; break;
- case SID_NAME_USER: return "SID_NAME_USER"; break;
- case SID_NAME_DOM_GRP: return "SID_NAME_DOM_GRP"; break;
- case SID_NAME_DOMAIN: return "SID_NAME_DOMAIN"; break;
- case SID_NAME_ALIAS: return "SID_NAME_ALIAS"; break;
- case SID_NAME_WKN_GRP: return "SID_NAME_WKN_GRP"; break;
- case SID_NAME_DELETED: return "SID_NAME_DELETED"; break;
- case SID_NAME_INVALID: return "SID_NAME_INVALID"; break;
- case SID_NAME_UNKNOWN: return "SID_NAME_UNKNOWN"; break;
- case SID_NAME_COMPUTER: return "SID_NAME_COMPUTER"; break;
- }
- return "Invalid sid type\n";
-}
-
-/* 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_response(WINBINDD_LOOKUPSID, &request, &response) !=
- NSS_STATUS_SUCCESS)
- return false;
-
- /* Display response */
-
- d_printf("%s%c%s %s\n", response.data.name.dom_name,
- winbind_separator(), response.data.name.name,
- sid_type_lookup(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_response(WINBINDD_LOOKUPNAME, &request, &response) !=
- NSS_STATUS_SUCCESS)
- return false;
-
- /* Display response */
-
- d_printf("%s %s (%d)\n", response.data.sid.sid, sid_type_lookup(response.data.sid.type), response.data.sid.type);
-
- return true;
-}
-
-/* Authenticate a user with a plaintext password */
-
-static bool wbinfo_auth_krb5(char *username, const char *cctype, uint32_t flags)
-{
- 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);
-
- request.flags = flags;
-
- fstrcpy(request.data.auth.krb5_cc_type, cctype);
-
- request.data.auth.uid = geteuid();
-
- result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
-
- /* Display response */
-
- d_printf("plaintext kerberos password authentication for [%s] %s (requesting cctype: %s)\n",
- username, (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", cctype);
-
- if (response.data.auth.nt_status)
- d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status,
- response.data.auth.error_string);
-
- if (result == NSS_STATUS_SUCCESS) {
-
- if (request.flags & WBFLAG_PAM_INFO3_TEXT) {
- if (response.data.auth.info3.user_flgs & NETLOGON_CACHED_ACCOUNT) {
- d_printf("user_flgs: NETLOGON_CACHED_ACCOUNT\n");
- }
- }
-
- if (response.data.auth.krb5ccname[0] != '\0') {
- d_printf("credentials were put in: %s\n", response.data.auth.krb5ccname);
- } else {
- d_printf("no credentials cached\n");
- }
- }
-
- return result == NSS_STATUS_SUCCESS;
-}
-
-/* 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_response(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_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status,
- response.data.auth.error_string);
-
- return result == NSS_STATUS_SUCCESS;
-}
-
-/* Authenticate a user with a challenge/response */
-
-static bool wbinfo_auth_crap(struct loadparm_context *lp_ctx, 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);
-
- request.data.auth_crap.logon_parameters = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;
-
- 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);
-
- if (lp_client_ntlmv2_auth(lp_ctx)) {
- DATA_BLOB server_chal;
- DATA_BLOB names_blob;
-
- DATA_BLOB lm_response;
- DATA_BLOB nt_response;
-
- TALLOC_CTX *mem_ctx;
- mem_ctx = talloc_new(NULL);
- if (mem_ctx == NULL) {
- d_printf("talloc_new failed\n");
- return false;
- }
-
- server_chal = data_blob(request.data.auth_crap.chal, 8);
-
- /* Pretend this is a login to 'us', for blob purposes */
- names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_netbios_name(lp_ctx), lp_workgroup(lp_ctx));
-
- if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain, pass, &server_chal,
- &names_blob,
- &lm_response, &nt_response, NULL, NULL)) {
- data_blob_free(&names_blob);
- data_blob_free(&server_chal);
- return false;
- }
- data_blob_free(&names_blob);
- data_blob_free(&server_chal);
-
- memcpy(request.data.auth_crap.nt_resp, nt_response.data,
- MIN(nt_response.length,
- sizeof(request.data.auth_crap.nt_resp)));
- request.data.auth_crap.nt_resp_len = nt_response.length;
-
- memcpy(request.data.auth_crap.lm_resp, lm_response.data,
- MIN(lm_response.length,
- sizeof(request.data.auth_crap.lm_resp)));
- request.data.auth_crap.lm_resp_len = lm_response.length;
-
- data_blob_free(&nt_response);
- data_blob_free(&lm_response);
-
- } else {
- if (lp_client_lanman_auth(lp_ctx)
- && SMBencrypt(pass, request.data.auth_crap.chal,
- (unsigned char *)request.data.auth_crap.lm_resp)) {
- request.data.auth_crap.lm_resp_len = 24;
- } else {
- request.data.auth_crap.lm_resp_len = 0;
- }
- SMBNTencrypt(pass, request.data.auth_crap.chal,
- (unsigned char *)request.data.auth_crap.nt_resp);
-
- request.data.auth_crap.nt_resp_len = 24;
- }
-
- result = winbindd_request_response(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_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
- response.data.auth.nt_status_string,
- response.data.auth.nt_status,
- response.data.auth.error_string);
-
- return result == NSS_STATUS_SUCCESS;
-}
-
-/* Print domain users */
-
-static bool print_domain_users(const char *domain)
-{
- struct winbindd_request request;
- struct winbindd_response response;
- const char *extra_data;
- fstring name;
-
- /* Send request to winbind daemon */
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- if (domain) {
- /* '.' is the special sign for our own domain */
- if ( strequal(domain, ".") )
- fstrcpy( request.domain_name, get_winbind_domain() );
- else
- fstrcpy( request.domain_name, domain );
- }
-
- if (winbindd_request_response(WINBINDD_LIST_USERS, &request, &response) !=
- NSS_STATUS_SUCCESS)
- return false;
-
- /* Look through extra data */
-
- if (!response.extra_data.data)
- return false;
-
- extra_data = (const char *)response.extra_data.data;
-
- while(next_token(&extra_data, name, ",", sizeof(fstring)))
- d_printf("%s\n", name);
-
- SAFE_FREE(response.extra_data.data);
-
- return true;
-}
-
-/* Print domain groups */
-
-static bool print_domain_groups(const char *domain)
-{
- struct winbindd_request request;
- struct winbindd_response response;
- const char *extra_data;
- fstring name;
-
- ZERO_STRUCT(request);
- ZERO_STRUCT(response);
-
- if (domain) {
- if ( strequal(domain, ".") )
- fstrcpy( request.domain_name, get_winbind_domain() );
- else
- fstrcpy( request.domain_name, domain );
- }
-
- if (winbindd_request_response(WINBINDD_LIST_GROUPS, &request, &response) !=
- NSS_STATUS_SUCCESS)
- return false;
-
- /* Look through extra data */
-
- if (!response.extra_data.data)
- return false;
-
- extra_data = (const char *)response.extra_data.data;
-
- while(next_token(&extra_data, name, ",", sizeof(fstring)))
- d_printf("%s\n", name);
-
- SAFE_FREE(response.extra_data.data);
-
- return true;
-}
-
-static bool wbinfo_ping(void)
-{
- NSS_STATUS result;
-
- result = winbindd_request_response(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_DOMAIN_NAME,
- OPT_SEQUENCE,
- OPT_GETDCNAME,
- OPT_USERDOMGROUPS,
- OPT_USERSIDS,
- OPT_ALLOCATE_UID,
- OPT_ALLOCATE_GID,
- OPT_SEPARATOR,
- OPT_LIST_ALL_DOMAINS,
- OPT_LIST_OWN_DOMAIN,
- OPT_UID_INFO,
- OPT_GROUP_INFO,
- OPT_GID_INFO,
-};
-
-int main(int argc, char **argv, char **envp)
-{
- int opt;
-
- poptContext pc;
- static char *string_arg;
- static char *opt_domain_name;
- static int int_arg;
- 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"},
- { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups", "domain" },
- { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP", "NETBIOS-NAME" },
- { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "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" },
- { "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" },
- { "own-domain", 0, POPT_ARG_NONE, 0, OPT_LIST_OWN_DOMAIN, "List own domain" },
- { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
- { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" },
- { "user-info", 'i', POPT_ARG_STRING, &string_arg, 'i', "Get user info", "USER" },
- { "uid-info", 0, POPT_ARG_INT, &int_arg, OPT_UID_INFO, "Get user info from uid", "UID" },
- { "group-info", 0, POPT_ARG_STRING, &string_arg, OPT_GROUP_INFO, "Get group info", "GROUP" },
- { "gid-info", 0, POPT_ARG_INT, &int_arg, OPT_GID_INFO, "Get group info from gid", "GID" },
- { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
- { "user-domgroups", 0, POPT_ARG_STRING, &string_arg,
- OPT_USERDOMGROUPS, "Get user domain groups", "SID" },
- { "user-sids", 0, POPT_ARG_STRING, &string_arg, OPT_USERSIDS, "Get user group sids for user SID", "SID" },
- { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" },
- { "getdcname", 0, POPT_ARG_STRING, &string_arg, OPT_GETDCNAME,
- "Get a DC name for a foreign domain", "domainname" },
- { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" },
- { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" },
-#ifdef HAVE_KRB5
- { "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" },
- /* destroys wbinfo --help output */
- /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */
-#endif
- { "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL },
- POPT_COMMON_VERSION
- POPT_COMMON_SAMBA
- POPT_TABLEEND
- };
-
- /* 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) {
- /* get the generic configuration parameters like --domain */
- }
-
- 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(opt_domain_name)) {
- d_fprintf(stderr, "Error looking up domain users\n");
- goto done;
- }
- break;
- case 'g':
- if (!print_domain_groups(opt_domain_name)) {
- d_fprintf(stderr, "Error looking up domain groups\n");
- goto done;
- }
- break;
- case 's':
- if (!wbinfo_lookupsid(string_arg)) {
- d_fprintf(stderr, "Could not lookup sid %s\n", string_arg);
- goto done;
- }
- break;
- case 'n':
- if (!wbinfo_lookupname(string_arg)) {
- d_fprintf(stderr, "Could not lookup name %s\n", string_arg);
- goto done;
- }
- break;
- case 'N':
- if (!wbinfo_wins_byname(string_arg)) {
- d_fprintf(stderr, "Could not lookup WINS by name %s\n", string_arg);
- goto done;
- }
- break;
- case 'I':
- if (!wbinfo_wins_byip(string_arg)) {
- d_fprintf(stderr, "Could not lookup WINS by IP %s\n", string_arg);
- goto done;
- }
- break;
- case 'U':
- if (!wbinfo_uid_to_sid(int_arg)) {
- d_fprintf(stderr, "Could not convert uid %d to sid\n", int_arg);
- goto done;
- }
- break;
- case 'G':
- if (!wbinfo_gid_to_sid(int_arg)) {
- d_fprintf(stderr, "Could not convert gid %d to sid\n",
- int_arg);
- goto done;
- }
- break;
- case 'S':
- if (!wbinfo_sid_to_uid(string_arg)) {
- d_fprintf(stderr, "Could not convert sid %s to uid\n",
- string_arg);
- goto done;
- }
- break;
- case 'Y':
- if (!wbinfo_sid_to_gid(string_arg)) {
- d_fprintf(stderr, "Could not convert sid %s to gid\n",
- string_arg);
- goto done;
- }
- break;
- case 't':
- if (!wbinfo_check_secret()) {
- d_fprintf(stderr, "Could not check secret\n");
- goto done;
- }
- break;
- case 'm':
- if (!wbinfo_list_domains(false)) {
- d_fprintf(stderr, "Could not list trusted domains\n");
- goto done;
- }
- break;
- case OPT_SEQUENCE:
- if (!wbinfo_show_sequence(opt_domain_name)) {
- d_fprintf(stderr, "Could not show sequence numbers\n");
- goto done;
- }
- break;
- case 'D':
- if (!wbinfo_domain_info(string_arg)) {
- d_fprintf(stderr, "Could not get domain info\n");
- goto done;
- }
- break;
- case 'i':
- if (!wbinfo_get_userinfo(string_arg)) {
- d_fprintf(stderr, "Could not get info for user %s\n",
- string_arg);
- goto done;
- }
- break;
- case OPT_UID_INFO:
- if ( !wbinfo_get_uidinfo(int_arg)) {
- d_fprintf(stderr, "Could not get info for uid "
- "%d\n", int_arg);
- goto done;
- }
- break;
- case OPT_GROUP_INFO:
- if ( !wbinfo_get_groupinfo(string_arg)) {
- d_fprintf(stderr, "Could not get info for "
- "group %s\n", string_arg);
- goto done;
- }
- break;
- case OPT_GID_INFO:
- if ( !wbinfo_get_gidinfo(int_arg)) {
- d_fprintf(stderr, "Could not get info for gid "
- "%d\n", int_arg);
- goto done;
- }
- break;
- case 'r':
- if (!wbinfo_get_usergroups(string_arg)) {
- d_fprintf(stderr, "Could not get groups for user %s\n",
- string_arg);
- goto done;
- }
- break;
- case OPT_USERSIDS:
- if (!wbinfo_get_usersids(string_arg)) {
- d_fprintf(stderr, "Could not get group SIDs for user SID %s\n",
- string_arg);
- goto done;
- }
- break;
- case OPT_USERDOMGROUPS:
- if (!wbinfo_get_userdomgroups(string_arg)) {
- d_fprintf(stderr, "Could not get user's domain groups "
- "for user SID %s\n", string_arg);
- goto done;
- }
- break;
- case 'a': {
- bool got_error = false;
-
- if (!wbinfo_auth(string_arg)) {
- d_fprintf(stderr, "Could not authenticate user %s with "
- "plaintext password\n", string_arg);
- got_error = true;
- }
-
- if (!wbinfo_auth_crap(cmdline_lp_ctx, string_arg)) {
- d_fprintf(stderr, "Could not authenticate user %s with "
- "challenge/response\n", string_arg);
- got_error = true;
- }
-
- if (got_error)
- goto done;
- break;
- }
- case 'K': {
- uint32_t flags = WBFLAG_PAM_KRB5 |
- WBFLAG_PAM_CACHED_LOGIN |
- WBFLAG_PAM_FALLBACK_AFTER_KRB5 |
- WBFLAG_PAM_INFO3_TEXT;
-
- if (!wbinfo_auth_krb5(string_arg, "FILE", flags)) {
- d_fprintf(stderr, "Could not authenticate user [%s] with "
- "Kerberos (ccache: %s)\n", string_arg, "FILE");
- goto done;
- }
- break;
- }
- case 'p':
- if (!wbinfo_ping()) {
- d_fprintf(stderr, "could not ping winbindd!\n");
- goto done;
- }
- break;
- case OPT_GETDCNAME:
- if (!wbinfo_getdcname(string_arg)) {
- goto done;
- }
- break;
- case OPT_SEPARATOR: {
- const char sep = winbind_separator_int(true);
- if ( !sep ) {
- goto done;
- }
- d_printf("%c\n", sep);
- break;
- }
- case OPT_LIST_ALL_DOMAINS:
- if (!wbinfo_list_domains(true)) {
- goto done;
- }
- break;
- case OPT_LIST_OWN_DOMAIN:
- if (!wbinfo_list_own_domain()) {
- goto done;
- }
- break;
- /* generic configuration options */
- case OPT_DOMAIN_NAME:
- 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/nsswitch/winbind_nss_netbsd.c b/nsswitch/winbind_nss_netbsd.c
index 9b8e0a2265..f6738061ad 100644
--- a/nsswitch/winbind_nss_netbsd.c
+++ b/nsswitch/winbind_nss_netbsd.c
@@ -124,7 +124,7 @@ netbsdwinbind_getgrent_r(void *nsrv, void *nscb, va_list ap)
*result = NULL;
rerrno = 0;
- rv = _nss_winbind_getgrent_r(grp, buffer, buflen, rerrno);
+ rv = _nss_winbind_getgrent_r(grp, buffer, buflen, &rerrno);
if (rv == NS_SUCCESS)
*result = grp;
else
@@ -215,7 +215,6 @@ netbsdwinbind_getgroupmembership(void *nsrv, void *nscb, va_list ap)
{
int *result = va_arg(ap, int *);
const char *uname = va_arg(ap, const char *);
- gid_t agroup = va_arg(ap, gid_t);
gid_t *groups = va_arg(ap, gid_t *);
int maxgrp = va_arg(ap, int);
int *groupc = va_arg(ap, int *);
@@ -312,7 +311,7 @@ netbsdwinbind_getpwent_r(void *nsrv, void *nscb, va_list ap)
*result = NULL;
rerrno = 0;
- rv = _nss_winbind_getpwent_r(pw, buffer, buflen, rerrno);
+ rv = _nss_winbind_getpwent_r(pw, buffer, buflen, &rerrno);
if (rv == NS_SUCCESS)
*result = pw;
else
diff --git a/nsswitch/winbind_struct_protocol.h b/nsswitch/winbind_struct_protocol.h
index 11b2069c3a..2e0751f79a 100644
--- a/nsswitch/winbind_struct_protocol.h
+++ b/nsswitch/winbind_struct_protocol.h
@@ -15,6 +15,11 @@
#define SAFE_FREE(x) do { if(x) {free(x); x=NULL;} } while(0)
#endif
+#ifndef FSTRING_LEN
+#define FSTRING_LEN 256
+typedef char fstring[FSTRING_LEN];
+#endif
+
#ifndef _WINBINDD_NTDOM_H
#define _WINBINDD_NTDOM_H
@@ -42,8 +47,11 @@
/* Update this when you change the interface.
* 21: added WINBINDD_GETPWSID
* added WINBINDD_GETSIDALIASES
+ * 22: added WINBINDD_PING_DC
+ * 23: added session_key to ccache_ntlm_auth response
+ * added WINBINDD_CCACHE_SAVE
*/
-#define WINBIND_INTERFACE_VERSION 21
+#define WINBIND_INTERFACE_VERSION 23
/* Have to deal with time_t being 4 or 8 bytes due to structure alignment.
On a 64bit Linux box, we have to support a constant structure size
@@ -113,6 +121,8 @@ enum winbindd_cmd {
/* Miscellaneous other stuff */
WINBINDD_CHECK_MACHACC, /* Check machine account pw works */
+ WINBINDD_CHANGE_MACHACC, /* Change machine account pw */
+ WINBINDD_PING_DC, /* Ping the DC through NETLOGON */
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()) */
@@ -164,9 +174,12 @@ enum winbindd_cmd {
WINBINDD_DUAL_USERINFO,
WINBINDD_DUAL_GETSIDALIASES,
+ WINBINDD_DUAL_NDRCMD,
+
/* Complete the challenge phase of the NTLM authentication
protocol using cached password. */
WINBINDD_CCACHE_NTLMAUTH,
+ WINBINDD_CCACHE_SAVE,
WINBINDD_NUM_CMDS
};
@@ -242,6 +255,7 @@ struct winbindd_request {
fstring groupname; /* getgrnam */
uid_t uid; /* getpwuid, uid_to_sid */
gid_t gid; /* getgrgid, gid_to_sid */
+ uint32_t ndrcmd;
struct {
/* We deliberatedly don't split into domain/user to
avoid having the client know what the separator
@@ -324,6 +338,11 @@ struct winbindd_request {
uint32_t challenge_blob_len;
} ccache_ntlm_auth;
struct {
+ uid_t uid;
+ fstring user;
+ fstring pass;
+ } ccache_save;
+ struct {
fstring domain_name;
fstring domain_guid;
fstring site_name;
@@ -467,6 +486,7 @@ struct winbindd_response {
uint32_t group_rid;
} user_info;
struct {
+ uint8_t session_key[16];
uint32_t auth_blob_len; /* blob in extra_data */
} ccache_ntlm_auth;
struct {