1/* 2 * Unix SMB/CIFS implementation. 3 * NetApi Samr Support 4 * Copyright (C) Guenther Deschner 2008 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 20#include "includes.h" 21#include "lib/netapi/netapi.h" 22#include "lib/netapi/netapi_private.h" 23#include "../librpc/gen_ndr/cli_samr.h" 24 25/**************************************************************** 26****************************************************************/ 27 28WERROR libnetapi_samr_open_domain(struct libnetapi_ctx *mem_ctx, 29 struct rpc_pipe_client *pipe_cli, 30 uint32_t connect_mask, 31 uint32_t domain_mask, 32 struct policy_handle *connect_handle, 33 struct policy_handle *domain_handle, 34 struct dom_sid2 **domain_sid) 35{ 36 NTSTATUS status; 37 WERROR werr; 38 struct libnetapi_private_ctx *priv; 39 uint32_t resume_handle = 0; 40 uint32_t num_entries = 0; 41 struct samr_SamArray *sam = NULL; 42 const char *domain_name = NULL; 43 struct lsa_String lsa_domain_name; 44 bool domain_found = true; 45 int i; 46 47 priv = talloc_get_type_abort(mem_ctx->private_data, 48 struct libnetapi_private_ctx); 49 50 if (is_valid_policy_hnd(&priv->samr.connect_handle)) { 51 if ((priv->samr.connect_mask & connect_mask) == connect_mask) { 52 *connect_handle = priv->samr.connect_handle; 53 } else { 54 libnetapi_samr_close_connect_handle(mem_ctx, 55 &priv->samr.connect_handle); 56 } 57 } 58 59 if (is_valid_policy_hnd(&priv->samr.domain_handle)) { 60 if ((priv->samr.domain_mask & domain_mask) == domain_mask) { 61 *domain_handle = priv->samr.domain_handle; 62 } else { 63 libnetapi_samr_close_domain_handle(mem_ctx, 64 &priv->samr.domain_handle); 65 } 66 } 67 68 if (priv->samr.domain_sid) { 69 *domain_sid = priv->samr.domain_sid; 70 } 71 72 if (is_valid_policy_hnd(&priv->samr.connect_handle) && 73 ((priv->samr.connect_mask & connect_mask) == connect_mask) && 74 is_valid_policy_hnd(&priv->samr.domain_handle) && 75 (priv->samr.domain_mask & domain_mask) == domain_mask) { 76 return WERR_OK; 77 } 78 79 if (!is_valid_policy_hnd(connect_handle)) { 80 status = rpccli_try_samr_connects(pipe_cli, mem_ctx, 81 connect_mask, 82 connect_handle); 83 if (!NT_STATUS_IS_OK(status)) { 84 werr = ntstatus_to_werror(status); 85 goto done; 86 } 87 } 88 89 status = rpccli_samr_EnumDomains(pipe_cli, mem_ctx, 90 connect_handle, 91 &resume_handle, 92 &sam, 93 0xffffffff, 94 &num_entries); 95 if (!NT_STATUS_IS_OK(status)) { 96 werr = ntstatus_to_werror(status); 97 goto done; 98 } 99 100 for (i=0; i<num_entries; i++) { 101 102 domain_name = sam->entries[i].name.string; 103 104 if (strequal(domain_name, builtin_domain_name())) { 105 continue; 106 } 107 108 domain_found = true; 109 break; 110 } 111 112 if (!domain_found) { 113 werr = WERR_NO_SUCH_DOMAIN; 114 goto done; 115 } 116 117 init_lsa_String(&lsa_domain_name, domain_name); 118 119 status = rpccli_samr_LookupDomain(pipe_cli, mem_ctx, 120 connect_handle, 121 &lsa_domain_name, 122 domain_sid); 123 if (!NT_STATUS_IS_OK(status)) { 124 werr = ntstatus_to_werror(status); 125 goto done; 126 } 127 128 status = rpccli_samr_OpenDomain(pipe_cli, mem_ctx, 129 connect_handle, 130 domain_mask, 131 *domain_sid, 132 domain_handle); 133 if (!NT_STATUS_IS_OK(status)) { 134 werr = ntstatus_to_werror(status); 135 goto done; 136 } 137 138 priv->samr.cli = pipe_cli; 139 140 priv->samr.domain_name = domain_name; 141 priv->samr.domain_sid = *domain_sid; 142 143 priv->samr.connect_mask = connect_mask; 144 priv->samr.connect_handle = *connect_handle; 145 146 priv->samr.domain_mask = domain_mask; 147 priv->samr.domain_handle = *domain_handle; 148 149 werr = WERR_OK; 150 151 done: 152 return werr; 153} 154 155/**************************************************************** 156****************************************************************/ 157 158WERROR libnetapi_samr_open_builtin_domain(struct libnetapi_ctx *mem_ctx, 159 struct rpc_pipe_client *pipe_cli, 160 uint32_t connect_mask, 161 uint32_t builtin_mask, 162 struct policy_handle *connect_handle, 163 struct policy_handle *builtin_handle) 164{ 165 NTSTATUS status; 166 WERROR werr; 167 struct libnetapi_private_ctx *priv; 168 169 priv = talloc_get_type_abort(mem_ctx->private_data, 170 struct libnetapi_private_ctx); 171 172 if (is_valid_policy_hnd(&priv->samr.connect_handle)) { 173 if ((priv->samr.connect_mask & connect_mask) == connect_mask) { 174 *connect_handle = priv->samr.connect_handle; 175 } else { 176 libnetapi_samr_close_connect_handle(mem_ctx, 177 &priv->samr.connect_handle); 178 } 179 } 180 181 if (is_valid_policy_hnd(&priv->samr.builtin_handle)) { 182 if ((priv->samr.builtin_mask & builtin_mask) == builtin_mask) { 183 *builtin_handle = priv->samr.builtin_handle; 184 } else { 185 libnetapi_samr_close_builtin_handle(mem_ctx, 186 &priv->samr.builtin_handle); 187 } 188 } 189 190 if (is_valid_policy_hnd(&priv->samr.connect_handle) && 191 ((priv->samr.connect_mask & connect_mask) == connect_mask) && 192 is_valid_policy_hnd(&priv->samr.builtin_handle) && 193 (priv->samr.builtin_mask & builtin_mask) == builtin_mask) { 194 return WERR_OK; 195 } 196 197 if (!is_valid_policy_hnd(connect_handle)) { 198 status = rpccli_try_samr_connects(pipe_cli, mem_ctx, 199 connect_mask, 200 connect_handle); 201 if (!NT_STATUS_IS_OK(status)) { 202 werr = ntstatus_to_werror(status); 203 goto done; 204 } 205 } 206 207 status = rpccli_samr_OpenDomain(pipe_cli, mem_ctx, 208 connect_handle, 209 builtin_mask, 210 CONST_DISCARD(DOM_SID *, &global_sid_Builtin), 211 builtin_handle); 212 if (!NT_STATUS_IS_OK(status)) { 213 werr = ntstatus_to_werror(status); 214 goto done; 215 } 216 217 priv->samr.cli = pipe_cli; 218 219 priv->samr.connect_mask = connect_mask; 220 priv->samr.connect_handle = *connect_handle; 221 222 priv->samr.builtin_mask = builtin_mask; 223 priv->samr.builtin_handle = *builtin_handle; 224 225 werr = WERR_OK; 226 227 done: 228 return werr; 229} 230 231/**************************************************************** 232****************************************************************/ 233 234void libnetapi_samr_close_domain_handle(struct libnetapi_ctx *ctx, 235 struct policy_handle *handle) 236{ 237 struct libnetapi_private_ctx *priv; 238 239 if (!is_valid_policy_hnd(handle)) { 240 return; 241 } 242 243 priv = talloc_get_type_abort(ctx->private_data, 244 struct libnetapi_private_ctx); 245 246 if (!policy_hnd_equal(handle, &priv->samr.domain_handle)) { 247 return; 248 } 249 250 rpccli_samr_Close(priv->samr.cli, ctx, handle); 251 252 ZERO_STRUCT(priv->samr.domain_handle); 253} 254 255/**************************************************************** 256****************************************************************/ 257 258void libnetapi_samr_close_builtin_handle(struct libnetapi_ctx *ctx, 259 struct policy_handle *handle) 260{ 261 struct libnetapi_private_ctx *priv; 262 263 if (!is_valid_policy_hnd(handle)) { 264 return; 265 } 266 267 priv = talloc_get_type_abort(ctx->private_data, 268 struct libnetapi_private_ctx); 269 270 if (!policy_hnd_equal(handle, &priv->samr.builtin_handle)) { 271 return; 272 } 273 274 rpccli_samr_Close(priv->samr.cli, ctx, handle); 275 276 ZERO_STRUCT(priv->samr.builtin_handle); 277} 278 279/**************************************************************** 280****************************************************************/ 281 282void libnetapi_samr_close_connect_handle(struct libnetapi_ctx *ctx, 283 struct policy_handle *handle) 284{ 285 struct libnetapi_private_ctx *priv; 286 287 if (!is_valid_policy_hnd(handle)) { 288 return; 289 } 290 291 priv = talloc_get_type_abort(ctx->private_data, 292 struct libnetapi_private_ctx); 293 294 if (!policy_hnd_equal(handle, &priv->samr.connect_handle)) { 295 return; 296 } 297 298 rpccli_samr_Close(priv->samr.cli, ctx, handle); 299 300 ZERO_STRUCT(priv->samr.connect_handle); 301} 302 303/**************************************************************** 304****************************************************************/ 305 306void libnetapi_samr_free(struct libnetapi_ctx *ctx) 307{ 308 struct libnetapi_private_ctx *priv; 309 310 if (!ctx->private_data) { 311 return; 312 } 313 314 priv = talloc_get_type_abort(ctx->private_data, 315 struct libnetapi_private_ctx); 316 317 libnetapi_samr_close_domain_handle(ctx, &priv->samr.domain_handle); 318 libnetapi_samr_close_builtin_handle(ctx, &priv->samr.builtin_handle); 319 libnetapi_samr_close_connect_handle(ctx, &priv->samr.connect_handle); 320} 321