1/* 2 Unix SMB/CIFS implementation. 3 Test suite for libnet calls. 4 5 Copyright (C) Rafal Szczesniak 2005 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19*/ 20 21#include "includes.h" 22#include "lib/cmdline/popt_common.h" 23#include "auth/credentials/credentials.h" 24#include "libnet/libnet.h" 25#include "libcli/security/security.h" 26#include "librpc/ndr/libndr.h" 27#include "librpc/gen_ndr/ndr_lsa.h" 28#include "librpc/gen_ndr/ndr_samr.h" 29#include "librpc/gen_ndr/ndr_srvsvc.h" 30#include "librpc/rpc/dcerpc.h" 31#include "torture/rpc/rpc.h" 32#include "torture/torture.h" 33#include "param/param.h" 34 35 36static bool test_connect_service(struct libnet_context *ctx, 37 const struct ndr_interface_table *iface, 38 const char *binding_string, 39 const char *hostname, 40 const enum libnet_RpcConnect_level level, 41 bool badcreds, NTSTATUS expected_status) 42{ 43 NTSTATUS status; 44 struct libnet_RpcConnect connect_r; 45 ZERO_STRUCT(connect_r); 46 47 connect_r.level = level; 48 connect_r.in.binding = binding_string; 49 connect_r.in.name = hostname; 50 connect_r.in.dcerpc_iface = iface; 51 52 /* if bad credentials are needed, set baduser%badpassword instead 53 of default commandline-passed credentials */ 54 if (badcreds) { 55 cli_credentials_set_username(ctx->cred, "baduser", CRED_SPECIFIED); 56 cli_credentials_set_password(ctx->cred, "badpassword", CRED_SPECIFIED); 57 } 58 59 status = libnet_RpcConnect(ctx, ctx, &connect_r); 60 61 if (!NT_STATUS_EQUAL(status, expected_status)) { 62 d_printf("Connecting to rpc service %s on %s.\n\tFAILED. Expected: %s." 63 "Received: %s\n", 64 connect_r.in.dcerpc_iface->name, connect_r.in.binding, nt_errstr(expected_status), 65 nt_errstr(status)); 66 67 return false; 68 } 69 70 d_printf("PASSED. Expected: %s, received: %s\n", nt_errstr(expected_status), 71 nt_errstr(status)); 72 73 if (connect_r.level == LIBNET_RPC_CONNECT_DC_INFO && NT_STATUS_IS_OK(status)) { 74 d_printf("Domain Controller Info:\n"); 75 d_printf("\tDomain Name:\t %s\n", connect_r.out.domain_name); 76 d_printf("\tDomain SID:\t %s\n", dom_sid_string(ctx, connect_r.out.domain_sid)); 77 d_printf("\tRealm:\t\t %s\n", connect_r.out.realm); 78 d_printf("\tGUID:\t\t %s\n", GUID_string(ctx, connect_r.out.guid)); 79 80 } else if (!NT_STATUS_IS_OK(status)) { 81 d_printf("Error string: %s\n", connect_r.out.error_string); 82 } 83 84 return true; 85} 86 87 88static bool torture_rpc_connect(struct torture_context *torture, 89 const enum libnet_RpcConnect_level level, 90 const char *bindstr, const char *hostname) 91{ 92 struct libnet_context *ctx; 93 94 ctx = libnet_context_init(torture->ev, torture->lp_ctx); 95 ctx->cred = cmdline_credentials; 96 97 d_printf("Testing connection to LSA interface\n"); 98 if (!test_connect_service(ctx, &ndr_table_lsarpc, bindstr, 99 hostname, level, false, NT_STATUS_OK)) { 100 d_printf("failed to connect LSA interface\n"); 101 return false; 102 } 103 104 d_printf("Testing connection to SAMR interface\n"); 105 if (!test_connect_service(ctx, &ndr_table_samr, bindstr, 106 hostname, level, false, NT_STATUS_OK)) { 107 d_printf("failed to connect SAMR interface\n"); 108 return false; 109 } 110 111 d_printf("Testing connection to SRVSVC interface\n"); 112 if (!test_connect_service(ctx, &ndr_table_srvsvc, bindstr, 113 hostname, level, false, NT_STATUS_OK)) { 114 d_printf("failed to connect SRVSVC interface\n"); 115 return false; 116 } 117 118 d_printf("Testing connection to LSA interface with wrong credentials\n"); 119 if (!test_connect_service(ctx, &ndr_table_lsarpc, bindstr, 120 hostname, level, true, NT_STATUS_LOGON_FAILURE)) { 121 d_printf("failed to test wrong credentials on LSA interface\n"); 122 return false; 123 } 124 125 d_printf("Testing connection to SAMR interface with wrong credentials\n"); 126 if (!test_connect_service(ctx, &ndr_table_samr, bindstr, 127 hostname, level, true, NT_STATUS_LOGON_FAILURE)) { 128 d_printf("failed to test wrong credentials on SAMR interface\n"); 129 return false; 130 } 131 132 talloc_free(ctx); 133 134 return true; 135} 136 137 138bool torture_rpc_connect_srv(struct torture_context *torture) 139{ 140 const enum libnet_RpcConnect_level level = LIBNET_RPC_CONNECT_SERVER; 141 NTSTATUS status; 142 struct dcerpc_binding *binding; 143 144 status = torture_rpc_binding(torture, &binding); 145 if (!NT_STATUS_IS_OK(status)) { 146 return false; 147 } 148 149 return torture_rpc_connect(torture, level, NULL, binding->host); 150} 151 152 153bool torture_rpc_connect_pdc(struct torture_context *torture) 154{ 155 const enum libnet_RpcConnect_level level = LIBNET_RPC_CONNECT_PDC; 156 NTSTATUS status; 157 struct dcerpc_binding *binding; 158 const char *domain_name; 159 160 status = torture_rpc_binding(torture, &binding); 161 if (!NT_STATUS_IS_OK(status)) { 162 return false; 163 } 164 165 /* we're accessing domain controller so the domain name should be 166 passed (it's going to be resolved to dc name and address) instead 167 of specific server name. */ 168 domain_name = lp_workgroup(torture->lp_ctx); 169 return torture_rpc_connect(torture, level, NULL, domain_name); 170} 171 172 173bool torture_rpc_connect_dc(struct torture_context *torture) 174{ 175 const enum libnet_RpcConnect_level level = LIBNET_RPC_CONNECT_DC; 176 NTSTATUS status; 177 struct dcerpc_binding *binding; 178 const char *domain_name; 179 180 status = torture_rpc_binding(torture, &binding); 181 if (!NT_STATUS_IS_OK(status)) { 182 return false; 183 } 184 185 /* we're accessing domain controller so the domain name should be 186 passed (it's going to be resolved to dc name and address) instead 187 of specific server name. */ 188 domain_name = lp_workgroup(torture->lp_ctx); 189 return torture_rpc_connect(torture, level, NULL, domain_name); 190} 191 192 193bool torture_rpc_connect_dc_info(struct torture_context *torture) 194{ 195 const enum libnet_RpcConnect_level level = LIBNET_RPC_CONNECT_DC_INFO; 196 NTSTATUS status; 197 struct dcerpc_binding *binding; 198 const char *domain_name; 199 200 status = torture_rpc_binding(torture, &binding); 201 if (!NT_STATUS_IS_OK(status)) { 202 return false; 203 } 204 205 /* we're accessing domain controller so the domain name should be 206 passed (it's going to be resolved to dc name and address) instead 207 of specific server name. */ 208 domain_name = lp_workgroup(torture->lp_ctx); 209 return torture_rpc_connect(torture, level, NULL, domain_name); 210} 211 212 213bool torture_rpc_connect_binding(struct torture_context *torture) 214{ 215 const enum libnet_RpcConnect_level level = LIBNET_RPC_CONNECT_BINDING; 216 NTSTATUS status; 217 struct dcerpc_binding *binding; 218 const char *bindstr; 219 220 status = torture_rpc_binding(torture, &binding); 221 if (!NT_STATUS_IS_OK(status)) { 222 return false; 223 } 224 225 bindstr = dcerpc_binding_string(torture, binding); 226 227 return torture_rpc_connect(torture, level, bindstr, NULL); 228} 229