2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Guenther Deschner 2008
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.
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.
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/>.
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "lib/netapi/netapi.h"
24 #include "lib/netapi/netapi_private.h"
25 #include "lib/netapi/libnetapi.h"
27 /****************************************************************
28 ****************************************************************/
30 WERROR NetUserAdd_l(struct libnetapi_ctx *ctx,
33 return WERR_NOT_SUPPORTED;
36 /****************************************************************
37 ****************************************************************/
39 static void convert_USER_INFO_1_to_samr_user_info25(struct USER_INFO_1 *info1,
40 DATA_BLOB *user_session_key,
41 struct samr_UserInfo25 *info25)
43 uint32_t fields_present = SAMR_FIELD_ACCT_FLAGS;
44 struct samr_LogonHours zero_logon_hours;
45 struct lsa_BinaryString zero_parameters;
46 uint32_t acct_flags = 0;
50 ZERO_STRUCT(zero_logon_hours);
51 ZERO_STRUCT(zero_parameters);
53 if (info1->usri1_name) {
54 fields_present |= SAMR_FIELD_FULL_NAME;
56 if (info1->usri1_password) {
57 fields_present |= SAMR_FIELD_PASSWORD;
59 if (info1->usri1_flags) {
60 fields_present |= SAMR_FIELD_ACCT_FLAGS;
62 if (info1->usri1_name) {
63 fields_present |= SAMR_FIELD_FULL_NAME;
65 if (info1->usri1_home_dir) {
66 fields_present |= SAMR_FIELD_HOME_DIRECTORY;
68 if (info1->usri1_script_path) {
69 fields_present |= SAMR_FIELD_LOGON_SCRIPT;
71 if (info1->usri1_comment) {
72 fields_present |= SAMR_FIELD_DESCRIPTION;
74 if (info1->usri1_password_age) {
75 fields_present |= SAMR_FIELD_FORCE_PWD_CHANGE;
78 acct_flags |= info1->usri1_flags | ACB_NORMAL;
80 unix_to_nt_time_abs(&password_age, info1->usri1_password_age);
82 /* TODO: info1->usri1_priv */
83 init_samr_user_info21(&info25->info,
92 info1->usri1_home_dir,
94 info1->usri1_script_path,
113 if (info1->usri1_password) {
115 struct MD5Context ctx;
116 uint8_t confounder[16];
117 DATA_BLOB confounded_session_key = data_blob(NULL, 16);
119 encode_pw_buffer(pwbuf, info1->usri1_password, STR_UNICODE);
121 generate_random_buffer((uint8_t *)confounder, 16);
124 MD5Update(&ctx, confounder, 16);
125 MD5Update(&ctx, user_session_key->data,
126 user_session_key->length);
127 MD5Final(confounded_session_key.data, &ctx);
129 SamOEMhashBlob(pwbuf, 516, &confounded_session_key);
130 memcpy(&pwbuf[516], confounder, 16);
132 memcpy(info25->password.data, pwbuf, sizeof(pwbuf));
133 data_blob_free(&confounded_session_key);
137 /****************************************************************
138 ****************************************************************/
140 WERROR NetUserAdd_r(struct libnetapi_ctx *ctx,
141 struct NetUserAdd *r)
143 struct cli_state *cli = NULL;
144 struct rpc_pipe_client *pipe_cli = NULL;
147 uint32_t resume_handle = 0;
148 uint32_t num_entries = 0;
149 POLICY_HND connect_handle, domain_handle, user_handle;
150 struct samr_SamArray *sam = NULL;
151 const char *domain_name = NULL;
152 struct lsa_String lsa_domain_name, lsa_account_name;
153 struct dom_sid2 *domain_sid = NULL;
154 struct samr_UserInfo25 info25;
155 union samr_UserInfo *user_info = NULL;
156 struct samr_PwInfo pw_info;
157 uint32_t access_granted = 0;
159 bool domain_found = true;
161 struct USER_INFO_1 *info1;
163 ZERO_STRUCT(connect_handle);
164 ZERO_STRUCT(domain_handle);
165 ZERO_STRUCT(user_handle);
168 return WERR_INVALID_PARAM;
171 switch (r->in.level) {
173 info1 = (struct USER_INFO_1 *)r->in.buffer;
179 werr = WERR_NOT_SUPPORTED;
183 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
184 if (!W_ERROR_IS_OK(werr)) {
188 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
189 if (!W_ERROR_IS_OK(werr)) {
193 status = rpccli_try_samr_connects(pipe_cli, ctx,
194 SAMR_ACCESS_ENUM_DOMAINS |
195 SAMR_ACCESS_OPEN_DOMAIN,
197 if (!NT_STATUS_IS_OK(status)) {
198 werr = ntstatus_to_werror(status);
202 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
208 if (!NT_STATUS_IS_OK(status)) {
209 werr = ntstatus_to_werror(status);
213 for (i=0; i<num_entries; i++) {
215 domain_name = sam->entries[i].name.string;
217 if (strequal(domain_name, builtin_domain_name())) {
226 werr = WERR_NO_SUCH_DOMAIN;
230 init_lsa_String(&lsa_domain_name, domain_name);
232 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
236 if (!NT_STATUS_IS_OK(status)) {
237 werr = ntstatus_to_werror(status);
241 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
243 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
244 SAMR_DOMAIN_ACCESS_CREATE_USER |
245 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
248 if (!NT_STATUS_IS_OK(status)) {
249 werr = ntstatus_to_werror(status);
253 init_lsa_String(&lsa_account_name, info1->usri1_name);
255 status = rpccli_samr_CreateUser2(pipe_cli, ctx,
261 SAMR_USER_ACCESS_SET_PASSWORD |
262 SAMR_USER_ACCESS_SET_ATTRIBUTES |
263 SAMR_USER_ACCESS_GET_ATTRIBUTES,
267 if (!NT_STATUS_IS_OK(status)) {
268 werr = ntstatus_to_werror(status);
272 status = rpccli_samr_QueryUserInfo(pipe_cli, ctx,
276 if (!NT_STATUS_IS_OK(status)) {
277 werr = ntstatus_to_werror(status);
281 if (!(user_info->info16.acct_flags & ACB_NORMAL)) {
282 werr = WERR_INVALID_PARAM;
286 status = rpccli_samr_GetUserPwInfo(pipe_cli, ctx,
289 if (!NT_STATUS_IS_OK(status)) {
290 werr = ntstatus_to_werror(status);
294 ZERO_STRUCTP(user_info);
296 convert_USER_INFO_1_to_samr_user_info25(info1,
297 &cli->user_session_key,
300 if (info1->usri1_password) {
301 user_info->info25 = info25;
302 status = rpccli_samr_SetUserInfo2(pipe_cli, ctx,
307 user_info->info21 = info25.info;
308 status = rpccli_samr_SetUserInfo(pipe_cli, ctx,
314 if (!NT_STATUS_IS_OK(status)) {
315 werr = ntstatus_to_werror(status);
323 rpccli_samr_DeleteUser(pipe_cli, ctx,
331 if (is_valid_policy_hnd(&user_handle)) {
332 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
334 if (is_valid_policy_hnd(&domain_handle)) {
335 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
337 if (is_valid_policy_hnd(&connect_handle)) {
338 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
344 /****************************************************************
345 ****************************************************************/
347 WERROR NetUserDel_r(struct libnetapi_ctx *ctx,
348 struct NetUserDel *r)
350 struct cli_state *cli = NULL;
351 struct rpc_pipe_client *pipe_cli = NULL;
354 uint32_t resume_handle = 0;
355 uint32_t num_entries = 0;
356 POLICY_HND connect_handle, builtin_handle, domain_handle, user_handle;
357 struct samr_SamArray *sam = NULL;
358 const char *domain_name = NULL;
359 struct lsa_String lsa_domain_name, lsa_account_name;
360 struct samr_Ids user_rids, name_types;
361 struct dom_sid2 *domain_sid = NULL;
362 struct dom_sid2 user_sid;
363 bool domain_found = true;
366 ZERO_STRUCT(connect_handle);
367 ZERO_STRUCT(builtin_handle);
368 ZERO_STRUCT(domain_handle);
369 ZERO_STRUCT(user_handle);
371 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
372 if (!W_ERROR_IS_OK(werr)) {
376 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
377 if (!W_ERROR_IS_OK(werr)) {
381 status = rpccli_try_samr_connects(pipe_cli, ctx,
382 SAMR_ACCESS_ENUM_DOMAINS |
383 SAMR_ACCESS_OPEN_DOMAIN,
385 if (!NT_STATUS_IS_OK(status)) {
386 werr = ntstatus_to_werror(status);
390 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
396 if (!NT_STATUS_IS_OK(status)) {
397 werr = ntstatus_to_werror(status);
401 for (i=0; i<num_entries; i++) {
403 domain_name = sam->entries[i].name.string;
405 if (strequal(domain_name, builtin_domain_name())) {
414 werr = WERR_NO_SUCH_DOMAIN;
418 init_lsa_String(&lsa_domain_name, domain_name);
420 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
424 if (!NT_STATUS_IS_OK(status)) {
425 werr = ntstatus_to_werror(status);
429 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
431 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
434 if (!NT_STATUS_IS_OK(status)) {
435 werr = ntstatus_to_werror(status);
439 status = rpccli_samr_OpenDomain(pipe_cli, ctx,
441 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
442 CONST_DISCARD(DOM_SID *, &global_sid_Builtin),
444 if (!NT_STATUS_IS_OK(status)) {
445 werr = ntstatus_to_werror(status);
449 init_lsa_String(&lsa_account_name, r->in.user_name);
451 status = rpccli_samr_LookupNames(pipe_cli, ctx,
457 if (!NT_STATUS_IS_OK(status)) {
458 werr = ntstatus_to_werror(status);
462 status = rpccli_samr_OpenUser(pipe_cli, ctx,
464 STD_RIGHT_DELETE_ACCESS,
467 if (!NT_STATUS_IS_OK(status)) {
468 werr = ntstatus_to_werror(status);
472 sid_compose(&user_sid, domain_sid, user_rids.ids[0]);
474 status = rpccli_samr_RemoveMemberFromForeignDomain(pipe_cli, ctx,
477 if (!NT_STATUS_IS_OK(status)) {
478 werr = ntstatus_to_werror(status);
482 status = rpccli_samr_DeleteUser(pipe_cli, ctx,
484 if (!NT_STATUS_IS_OK(status)) {
485 werr = ntstatus_to_werror(status);
496 if (is_valid_policy_hnd(&user_handle)) {
497 rpccli_samr_Close(pipe_cli, ctx, &user_handle);
499 if (is_valid_policy_hnd(&builtin_handle)) {
500 rpccli_samr_Close(pipe_cli, ctx, &builtin_handle);
502 if (is_valid_policy_hnd(&domain_handle)) {
503 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
505 if (is_valid_policy_hnd(&connect_handle)) {
506 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
512 /****************************************************************
513 ****************************************************************/
515 WERROR NetUserDel_l(struct libnetapi_ctx *ctx,
516 struct NetUserDel *r)
518 return WERR_NOT_SUPPORTED;
521 /****************************************************************
522 ****************************************************************/
524 static WERROR convert_samr_samarray_to_USER_INFO_buffer(TALLOC_CTX *mem_ctx,
525 struct samr_SamArray *sam_array,
529 struct USER_INFO_0 *info0 = NULL;
534 info0 = TALLOC_ZERO_ARRAY(mem_ctx, struct USER_INFO_0,
536 W_ERROR_HAVE_NO_MEMORY(info0);
538 for (i=0; i<sam_array->count; i++) {
539 info0[i].usri0_name = talloc_strdup(mem_ctx,
540 sam_array->entries[i].name.string);
541 W_ERROR_HAVE_NO_MEMORY(info0[i].usri0_name);
544 *buffer = (uint8_t *)talloc_memdup(mem_ctx, info0,
545 sizeof(struct USER_INFO_0) * sam_array->count);
546 W_ERROR_HAVE_NO_MEMORY(*buffer);
549 return WERR_NOT_SUPPORTED;
555 /****************************************************************
556 ****************************************************************/
558 WERROR NetUserEnum_r(struct libnetapi_ctx *ctx,
559 struct NetUserEnum *r)
561 struct cli_state *cli = NULL;
562 struct rpc_pipe_client *pipe_cli = NULL;
563 struct policy_handle connect_handle;
564 struct dom_sid2 *domain_sid = NULL;
565 struct policy_handle domain_handle;
566 struct samr_SamArray *sam = NULL;
567 uint32_t num_entries = 0;
569 const char *domain_name = NULL;
570 bool domain_found = true;
571 uint32_t dom_resume_handle = 0;
572 struct lsa_String lsa_domain_name;
577 ZERO_STRUCT(connect_handle);
578 ZERO_STRUCT(domain_handle);
580 switch (r->in.level) {
591 return WERR_NOT_SUPPORTED;
594 werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
595 if (!W_ERROR_IS_OK(werr)) {
599 werr = libnetapi_open_pipe(ctx, cli, PI_SAMR, &pipe_cli);
600 if (!W_ERROR_IS_OK(werr)) {
604 status = rpccli_try_samr_connects(pipe_cli, ctx,
605 SAMR_ACCESS_OPEN_DOMAIN |
606 SAMR_ACCESS_ENUM_DOMAINS,
608 if (!NT_STATUS_IS_OK(status)) {
609 werr = ntstatus_to_werror(status);
613 status = rpccli_samr_EnumDomains(pipe_cli, ctx,
619 if (!NT_STATUS_IS_OK(status)) {
620 werr = ntstatus_to_werror(status);
624 for (i=0; i<num_entries; i++) {
626 domain_name = sam->entries[i].name.string;
628 if (strequal(domain_name, builtin_domain_name())) {
637 werr = WERR_NO_SUCH_DOMAIN;
641 init_lsa_String(&lsa_domain_name, domain_name);
643 status = rpccli_samr_LookupDomain(pipe_cli, ctx,
647 if (!NT_STATUS_IS_OK(status)) {
648 werr = ntstatus_to_werror(status);
652 status = rpccli_samr_OpenDomain(pipe_cli,
655 SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2 |
656 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS |
657 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
660 if (!NT_STATUS_IS_OK(status)) {
661 werr = ntstatus_to_werror(status);
665 status = rpccli_samr_EnumDomainUsers(pipe_cli,
672 r->out.entries_read);
673 if (!NT_STATUS_IS_OK(status)) {
674 werr = ntstatus_to_werror(status);
678 werr = convert_samr_samarray_to_USER_INFO_buffer(ctx, sam,
687 if (is_valid_policy_hnd(&domain_handle)) {
688 rpccli_samr_Close(pipe_cli, ctx, &domain_handle);
690 if (is_valid_policy_hnd(&connect_handle)) {
691 rpccli_samr_Close(pipe_cli, ctx, &connect_handle);
697 /****************************************************************
698 ****************************************************************/
700 WERROR NetUserEnum_l(struct libnetapi_ctx *ctx,
701 struct NetUserEnum *r)
703 return WERR_NOT_SUPPORTED;
706 /****************************************************************
707 ****************************************************************/
710 WERROR NetQueryDisplayInformation_r(struct libnetapi_ctx *ctx,
711 struct NetQueryDisplayInformation *r)
713 return WERR_NOT_SUPPORTED;
716 /****************************************************************
717 ****************************************************************/
720 WERROR NetQueryDisplayInformation_l(struct libnetapi_ctx *ctx,
721 struct NetQueryDisplayInformation *r)
723 return WERR_NOT_SUPPORTED;