This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ 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,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
-#include "torture/torture.h"
-#include "torture/basic/proto.h"
#include "libcli/libcli.h"
-#include "libcli/raw/interfaces.h"
+#include "libcli/raw/raw_proto.h"
+#include "torture/torture.h"
+#include "torture/unix/proto.h"
#include "lib/cmdline/popt_common.h"
#include "auth/credentials/credentials.h"
+#include "param/param.h"
+#include "libcli/resolve/resolve.h"
+#include <ldb.h>
+#include "lib/util/util_ldb.h"
+#include "ldb_wrap.h"
+#include "dsdb/samdb/samdb.h"
+#include "../libcli/security/security.h"
-#define SMB_QUERY_POSIX_WHOAMI 0x202
/* Size (in bytes) of the required fields in the SMBwhoami response. */
#define WHOAMI_REQUIRED_SIZE 40
-enum smb_whoami_flags {
- SMB_WHOAMI_GUEST = 0x1 /* Logged in as (or squashed to) guest */
-};
-
/*
SMBWhoami - Query the user mapping performed by the server for the
connected tree. This is a subcommand of the TRANS2_QFSINFO.
4 bytes - pad / reserved (must be zero)
8 bytes unsigned[] - list of GIDs (may be empty)
- DOM_SID[] - list of SIDs (may be empty)
+ struct dom_sid[] - list of SIDs (may be empty)
*/
struct smb_whoami
struct dom_sid ** sid_list;
};
-static struct smbcli_state *connect_to_server(void *mem_ctx)
+static struct smbcli_state *connect_to_server(struct torture_context *tctx,
+ struct cli_credentials *creds)
{
NTSTATUS status;
struct smbcli_state *cli;
- const char *host = lp_parm_string(-1, "torture", "host");
- const char *share = lp_parm_string(-1, "torture", "share");
+ const char *host = torture_setting_string(tctx, "host", NULL);
+ const char *share = torture_setting_string(tctx, "share", NULL);
+ struct smbcli_options options;
+ struct smbcli_session_options session_options;
+
+ lpcfg_smbcli_options(tctx->lp_ctx, &options);
+ lpcfg_smbcli_session_options(tctx->lp_ctx, &session_options);
- status = smbcli_full_connection(mem_ctx, &cli,
- host, share, NULL,
- cmdline_credentials, NULL);
+ status = smbcli_full_connection(tctx, &cli, host,
+ lpcfg_smb_ports(tctx->lp_ctx),
+ share, NULL, lpcfg_socket_options(tctx->lp_ctx),
+ creds, lpcfg_resolve_context(tctx->lp_ctx),
+ tctx->ev, &options, &session_options,
+ lpcfg_gensec_settings(tctx, tctx->lp_ctx));
if (!NT_STATUS_IS_OK(status)) {
- printf("failed to connect to //%s/%s: %s\n",
- host, share, nt_errstr(status));
+ torture_comment(tctx,
+ "FATAL: Failed to connect to //%s/%s "
+ "with %s - %s\n",
+ host,
+ share,
+ cli_credentials_get_username(creds),
+ nt_errstr(status));
return NULL;
}
return cli;
}
-static BOOL sid_parse(void *mem_ctx,
+static bool whoami_sid_parse(void *mem_ctx,
struct torture_context *torture,
DATA_BLOB *data, size_t *offset,
struct dom_sid **psid)
torture_assert(torture, (*psid)->num_auths <= 15,
"invalid sub_auth value");
- (*psid)->sub_auths = talloc_array(mem_ctx, uint32_t,
- (*psid)->num_auths);
- torture_assert(torture, (*psid)->sub_auths != NULL,
- "out of memory");
-
for (i = 0; i < (*psid)->num_auths; i++) {
(*psid)->sub_auths[i] = IVAL(data->data, *offset);
(*offset) += 4;
}
- return True;
+ return true;
}
-static BOOL smb_raw_query_posix_whoami(void *mem_ctx,
+static bool smb_raw_query_posix_whoami(void *mem_ctx,
struct torture_context *torture,
struct smbcli_state *cli,
struct smb_whoami *whoami,
tp.in.max_data = (uint16_t)max_data;
tp.in.setup = &setup;
tp.in.trans_name = NULL;
- SSVAL(&info_level, 0, SMB_QUERY_POSIX_WHOAMI);
+ SSVAL(&info_level, 0, SMB_QFS_POSIX_WHOAMI);
tp.in.params = data_blob_talloc(mem_ctx, &info_level, 2);
tp.in.data = data_blob_talloc(mem_ctx, NULL, 0);
status = smb_raw_trans2(cli->tree, mem_ctx, &tp);
torture_assert_ntstatus_equal(torture, status, NT_STATUS_OK,
- "doing SMB_QUERY_POSIX_WHOAMI");
+ "doing SMB_QFS_POSIX_WHOAMI");
/* Make sure we got back all the required fields. */
torture_assert(torture, tp.out.params.length == 0,
printf("\tmapping_flags=0x%08x mapping_mask=0x%08x\n",
whoami->mapping_flags, whoami->mapping_mask);
- printf("\tserver UID=%lld GID=%lld\n",
- whoami->server_uid, whoami->server_gid);
+ printf("\tserver UID=%llu GID=%llu\n",
+ (unsigned long long)whoami->server_uid, (unsigned long long)whoami->server_gid);
printf("\t%u GIDs, %u SIDs, %u SID bytes\n",
whoami->num_gids, whoami->num_sids,
whoami->num_sid_bytes);
"invalid SID count");
torture_assert_int_equal(torture, whoami->num_sid_bytes, 0,
"invalid SID byte count");
- return True;
+ return true;
}
if (whoami->num_gids != 0) {
whoami->gid_list = talloc_array(mem_ctx, uint64_t, whoami->num_gids);
torture_assert(torture, whoami->gid_list != NULL, "out of memory");
+ torture_comment(torture, "\tGIDs:\n");
+
for (i = 0; i < whoami->num_gids; ++i) {
whoami->gid_list[i] = BVAL(tp.out.data.data, offset);
offset += 8;
+ torture_comment(torture, "\t\t%u\n", (unsigned int)whoami->gid_list[i]);
}
}
if (tp.out.data.length == offset) {
torture_assert_int_equal(torture, whoami->num_sids, 0,
"invalid SID count");
- return True;
+ return true;
}
/* All the remaining bytes must be the SID list. */
torture_assert(torture, whoami->sid_list != NULL,
"out of memory");
+ torture_comment(torture, "\tSIDs:\n");
+
for (i = 0; i < whoami->num_sids; ++i) {
- if (!sid_parse(mem_ctx, torture,
+ if (!whoami_sid_parse(mem_ctx, torture,
&tp.out.data, &offset,
&whoami->sid_list[i])) {
- return False;
+ return false;
}
+ torture_comment(torture, "\t\t%s\n",
+ dom_sid_string(torture, whoami->sid_list[i]));
}
}
torture_assert_int_equal(torture, tp.out.data.length, offset,
"trailing garbage bytes");
- return True;
+ return true;
+}
+
+static bool test_against_ldap(struct torture_context *torture, struct ldb_context *ldb, bool is_dc,
+ struct smb_whoami *whoami)
+{
+ struct ldb_message *msg;
+ struct ldb_message_element *el;
+
+ const char *attrs[] = { "tokenGroups", NULL };
+ int i;
+
+ torture_assert_int_equal(torture, dsdb_search_one(ldb, torture, &msg, NULL, LDB_SCOPE_BASE, attrs, 0, NULL), LDB_SUCCESS, "searching for tokenGroups");
+ el = ldb_msg_find_element(msg, "tokenGroups");
+ torture_assert(torture, el, "obtaining tokenGroups");
+ torture_assert(torture, el->num_values > 0, "Number of SIDs from LDAP needs to be more than 0");
+ torture_assert(torture, whoami->num_sids > 0, "Number of SIDs from LDAP needs to be more than 0");
+
+ if (is_dc) {
+ torture_assert_int_equal(torture, el->num_values, whoami->num_sids, "Number of SIDs from LDAP and number of SIDs from CIFS does not match!");
+
+ for (i = 0; i < el->num_values; i++) {
+ struct dom_sid *sid = talloc(torture, struct dom_sid);
+ struct sid_parse_ret ret;
+ torture_assert(torture, sid != NULL, "talloc failed");
+
+ ret = sid_parse(el->values[i].data,
+ el->values[i].length, sid);
+ torture_assert(torture,
+ ret.len != -1,
+ "sid parse failed");
+ torture_assert_str_equal(torture, dom_sid_string(sid, sid), dom_sid_string(sid, whoami->sid_list[i]), "SID from LDAP and SID from CIFS does not match!");
+ talloc_free(sid);
+ }
+ } else {
+ unsigned int num_domain_sids_dc = 0, num_domain_sids_member = 0;
+ struct dom_sid *user_sid = talloc(torture, struct dom_sid);
+ struct dom_sid *dom_sid = talloc(torture, struct dom_sid);
+ struct dom_sid *dc_sids = talloc_array(torture, struct dom_sid, el->num_values);
+ struct dom_sid *member_sids = talloc_array(torture, struct dom_sid, whoami->num_sids);
+ struct sid_parse_ret ret;
+ torture_assert(torture, user_sid != NULL, "talloc failed");
+ ret = sid_parse(el->values[0].data,
+ el->values[0].length,
+ user_sid);
+ torture_assert(torture,
+ ret.len != -1,
+ "sid parse failed");
+ torture_assert_ntstatus_equal(torture, dom_sid_split_rid(torture, user_sid, &dom_sid, NULL), NT_STATUS_OK, "failed to split domain SID from user SID");
+ for (i = 0; i < el->num_values; i++) {
+ struct dom_sid *sid = talloc(dc_sids, struct dom_sid);
+ torture_assert(torture, sid != NULL, "talloc failed");
+
+ ret = sid_parse(el->values[i].data,
+ el->values[i].length,
+ sid);
+ torture_assert(torture,
+ ret.len != -1,
+ "sid parse failed");
+ if (dom_sid_in_domain(dom_sid, sid)) {
+ dc_sids[num_domain_sids_dc] = *sid;
+ num_domain_sids_dc++;
+ }
+ talloc_free(sid);
+ }
+
+ for (i = 0; i < whoami->num_sids; i++) {
+ if (dom_sid_in_domain(dom_sid, whoami->sid_list[i])) {
+ member_sids[num_domain_sids_member] = *whoami->sid_list[i];
+ num_domain_sids_member++;
+ }
+ }
+
+ torture_assert_int_equal(torture, num_domain_sids_dc, num_domain_sids_member, "Number of Domain SIDs from LDAP DC and number of SIDs from CIFS member does not match!");
+ for (i = 0; i < num_domain_sids_dc; i++) {
+ torture_assert_str_equal(torture, dom_sid_string(dc_sids, &dc_sids[i]), dom_sid_string(member_sids, &member_sids[i]), "Domain SID from LDAP DC and SID from CIFS member server does not match!");
+ }
+ talloc_free(dc_sids);
+ talloc_free(member_sids);
+ }
+ return true;
}
-BOOL torture_unix_whoami(struct torture_context *torture)
+bool torture_unix_whoami(struct torture_context *torture)
{
struct smbcli_state *cli;
struct smb_whoami whoami;
- void *mem_ctx;
+ bool ret = false;
+ struct ldb_context *ldb;
+ const char *addc, *host;
+
+ cli = connect_to_server(torture, popt_get_cmdline_credentials());
+ torture_assert(torture, cli, "connecting to server with authenticated credentials");
- mem_ctx = talloc_init("smb_query_posix_whoami");
- torture_assert(torture, mem_ctx != NULL, "malloc failed");
+ /* Test basic authenticated mapping. */
+ torture_assert_goto(torture, smb_raw_query_posix_whoami(torture, torture,
+ cli, &whoami, 0xFFFF), ret, fail,
+ "calling SMB_QFS_POSIX_WHOAMI on an authenticated connection");
- if (!(cli = connect_to_server(mem_ctx))) {
- goto fail;
+ /* Check that our anonymous login mapped us to guest on the server, but
+ * only if the server supports this.
+ */
+ if (whoami.mapping_mask & SMB_WHOAMI_GUEST) {
+ bool guest = whoami.mapping_flags & SMB_WHOAMI_GUEST;
+ torture_comment(torture, "checking whether we were logged in as guest... %s\n",
+ guest ? "YES" : "NO");
+ torture_assert(torture,
+ cli_credentials_is_anonymous(
+ popt_get_cmdline_credentials()) == guest,
+ "login did not credentials map to guest");
+ } else {
+ torture_comment(torture, "server does not support SMB_WHOAMI_GUEST flag\n");
}
- /* Test basic authenticated mapping. */
- printf("calling SMB_QUERY_POSIX_WHOAMI on an authenticated connection\n");
- if (!smb_raw_query_posix_whoami(mem_ctx, torture,
- cli, &whoami, 0xFFFF)) {
- smbcli_tdis(cli);
- goto fail;
+ addc = torture_setting_string(torture, "addc", NULL);
+ host = torture_setting_string(torture, "host", NULL);
+
+ if (addc) {
+ ldb = ldb_wrap_connect(torture, torture->ev, torture->lp_ctx, talloc_asprintf(torture, "ldap://%s", addc),
+ NULL, popt_get_cmdline_credentials(), 0);
+ torture_assert(torture, ldb, "ldb connect failed");
+
+ /* We skip this testing if we could not contact the LDAP server */
+ if (!test_against_ldap(torture, ldb, strcasecmp(addc, host) == 0, &whoami)) {
+ goto fail;
+ }
}
/* Test that the server drops the UID and GID list. */
- printf("calling SMB_QUERY_POSIX_WHOAMI with a small buffer\n");
- if (!smb_raw_query_posix_whoami(mem_ctx, torture,
- cli, &whoami, 0x40)) {
- smbcli_tdis(cli);
- goto fail;
- }
+ torture_assert_goto(torture, smb_raw_query_posix_whoami(torture, torture,
+ cli, &whoami, 0x40), ret, fail,
+ "calling SMB_QFS_POSIX_WHOAMI with a small buffer\n");
torture_assert_int_equal(torture, whoami.num_gids, 0,
"invalid GID count");
"invalid SID bytes count");
smbcli_tdis(cli);
- cli_credentials_set_anonymous(cmdline_credentials);
-
- if (!(cli = connect_to_server(mem_ctx))) {
- goto fail;
- }
-
- printf("calling SMB_QUERY_POSIX_WHOAMI on an anonymous connection\n");
- if (!smb_raw_query_posix_whoami(mem_ctx, torture,
- cli, &whoami, 0xFFFF)) {
- smbcli_tdis(cli);
- goto fail;
- }
-
- smbcli_tdis(cli);
-
- /* Check that our anonymous login mapped us to guest on the server, but
- * only if the server supports this.
- */
- if (whoami.mapping_mask & SMB_WHOAMI_GUEST) {
- printf("checking whether we were logged in as guest... %s\n",
- whoami.mapping_flags & SMB_WHOAMI_GUEST ? "YES" : "NO");
- torture_assert(torture, whoami.mapping_flags & SMB_WHOAMI_GUEST,
- "anonymous login did not map to guest");
- } else {
- printf("server does not support SMB_WHOAMI_GUEST flag\n");
- }
-
- talloc_free(mem_ctx);
- return True;
+ return true;
fail:
- talloc_free(mem_ctx);
- return False;
+ smbcli_tdis(cli);
+ return ret;
}
/* vim: set sts=8 sw=8 : */