2 OpenChange Exchange Administration library.
4 Based on the work by Andrew Tridgell, 2004
6 Original source code available in SAMBA_4_0:
7 source/torture/rpc/testjoin.c
9 Copyright (C) Julien Kerihuel 2007-2010.
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 3 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "libmapiadmin/libmapiadmin.h"
30 #include <credentials.h>
31 #include <ldb_errors.h>
35 #include <core/error.h>
36 #include <gen_ndr/ndr_samr.h>
37 #include <gen_ndr/ndr_samr_c.h>
43 User management functions for mapiadmin
47 * open connection so SAMR + Join Domain
48 * common code needed when adding or removing users
50 static enum MAPISTATUS mapiadmin_samr_connect(struct mapiadmin_ctx *mapiadmin_ctx,
54 struct tevent_context *ev;
55 struct mapi_context *mapi_ctx;
56 struct mapi_profile *profile;
57 struct samr_Connect c;
58 struct samr_OpenDomain o;
59 struct samr_LookupDomain l;
60 struct policy_handle handle;
61 struct policy_handle domain_handle;
62 struct lsa_String name;
64 MAPI_RETVAL_IF(!mapiadmin_ctx, MAPI_E_NOT_INITIALIZED, NULL);
65 MAPI_RETVAL_IF(!mapiadmin_ctx->session, MAPI_E_NOT_INITIALIZED, NULL);
66 MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile, MAPI_E_NOT_INITIALIZED, NULL);
67 MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile->credentials, MAPI_E_NOT_INITIALIZED, NULL);
68 MAPI_RETVAL_IF(!mapiadmin_ctx->username, MAPI_E_NOT_INITIALIZED, NULL);
70 mapi_ctx = mapiadmin_ctx->session->mapi_ctx;
71 MAPI_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
73 profile = mapiadmin_ctx->session->profile;
75 mapiadmin_ctx->user_ctx = talloc_zero(mem_ctx, struct test_join);
76 MAPI_RETVAL_IF(!mapiadmin_ctx->user_ctx, MAPI_E_NOT_ENOUGH_RESOURCES ,NULL);
78 DEBUG(3, ("Connecting to SAMR\n"));
80 ev = tevent_context_init(mem_ctx);
82 status = dcerpc_pipe_connect(mapiadmin_ctx->user_ctx,
83 &mapiadmin_ctx->user_ctx->p,
84 mapiadmin_ctx->dc_binding ?
85 mapiadmin_ctx->dc_binding :
86 mapiadmin_ctx->binding,
88 profile->credentials, ev, mapi_ctx->lp_ctx);
90 MAPI_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, NULL);
92 profile = mapiadmin_ctx->session->profile;
94 c.in.system_name = NULL;
95 c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
96 c.out.connect_handle = &handle;
98 status = dcerpc_samr_Connect_r(mapiadmin_ctx->user_ctx->p->binding_handle, mapiadmin_ctx->user_ctx, &c);
99 if (!NT_STATUS_IS_OK(status)) {
100 const char *errstr = nt_errstr(status);
101 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
102 errstr = dcerpc_errstr(mapiadmin_ctx->user_ctx, mapiadmin_ctx->user_ctx->p->last_fault_code);
104 DEBUG(3, ("samr_Connect failed - %s\n", errstr));
105 return MAPI_E_CALL_FAILED;
108 DEBUG(3, ("Opening domain %s\n", profile->domain));
110 name.string = profile->domain;
111 l.in.connect_handle = &handle;
112 l.in.domain_name = &name;
114 l.out.sid = talloc(mem_ctx, struct dom_sid2 *);
115 talloc_steal(mapiadmin_ctx->user_ctx, l.out.sid);
117 status = dcerpc_samr_LookupDomain_r(mapiadmin_ctx->user_ctx->p->binding_handle, mapiadmin_ctx->user_ctx, &l);
118 if (!NT_STATUS_IS_OK(status)) {
119 DEBUG(3, ("LookupDomain failed - %s\n", nt_errstr(status)));
120 return MAPI_E_CALL_FAILED;
123 mapiadmin_ctx->user_ctx->dom_sid = *l.out.sid;
124 mapiadmin_ctx->user_ctx->dom_netbios_name = talloc_strdup(mapiadmin_ctx->user_ctx, profile->domain);
125 if (!mapiadmin_ctx->user_ctx->dom_netbios_name) return MAPI_E_CALL_FAILED;
127 o.in.connect_handle = &handle;
128 o.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
129 o.in.sid = *l.out.sid;
130 o.out.domain_handle = &domain_handle;
132 status = dcerpc_samr_OpenDomain_r(mapiadmin_ctx->user_ctx->p->binding_handle, mapiadmin_ctx->user_ctx, &o);
133 if (!NT_STATUS_IS_OK(status)) {
134 DEBUG(3, ("OpenDomain failed - %s\n", nt_errstr(status)));
135 return MAPI_E_CALL_FAILED;
138 mapiadmin_ctx->handle = talloc_memdup(mem_ctx, &domain_handle, sizeof (struct policy_handle));
141 return MAPI_E_SUCCESS;
145 struct tce_async_context {
149 static int tce_search_callback(struct ldb_request *req, struct ldb_reply *ares)
151 struct tce_async_context *actx = talloc_get_type(req->context, struct tce_async_context);
154 switch (ares->type) {
156 case LDB_REPLY_ENTRY:
157 if (ldb_msg_find_element(ares->message, "msExchMailboxGuid") != NULL) {
158 DEBUG(3, ("[%s:%d]: msExchMailboxGuid found!\n", __FUNCTION__, __LINE__));
161 return ldb_request_done(req, LDB_SUCCESS);
168 DEBUG(3, ("[%s:%d]: unknown Reply Type ignore it\n", __FUNCTION__, __LINE__));
170 return LDB_ERR_OTHER;
173 if (talloc_free(ares) == -1) {
174 DEBUG(3, ("[%s:%d]: talloc_free failed\n", __FUNCTION__, __LINE__));
175 return LDB_ERR_OPERATIONS_ERROR;
182 * Extend user attributes to be Exchange user
184 _PUBLIC_ enum MAPISTATUS mapiadmin_user_extend(struct mapiadmin_ctx *mapiadmin_ctx)
187 enum MAPISTATUS retval;
188 struct tevent_context *ev = NULL;
189 struct mapi_context *mapi_ctx;
190 struct mapi_profile *profile;
191 struct ldb_context *remote_ldb;
192 struct ldb_request *req;
193 struct ldb_message *msg;
194 struct ldb_result *res;
195 struct ldb_control **controls;
196 const char *control_strings[2] = { "notification:0", NULL };
197 struct tce_async_context *tce_ctx;
198 const struct dom_sid *dom_sid;
199 char *remote_ldb_url;
200 const char * const dom_attrs[] = { "*", NULL };
204 const char *exch_attrs[7];
208 const char *UserAccountControl;
209 struct ldb_dn *account_dn;
212 MAPI_RETVAL_IF(!mapiadmin_ctx, MAPI_E_NOT_INITIALIZED, NULL);
213 MAPI_RETVAL_IF(!mapiadmin_ctx->session, MAPI_E_NOT_INITIALIZED, NULL);
214 MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile, MAPI_E_NOT_INITIALIZED, NULL);
215 MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile->credentials, MAPI_E_NOT_INITIALIZED, NULL);
216 MAPI_RETVAL_IF(!mapiadmin_ctx->user_ctx, MAPI_E_NOT_INITIALIZED, NULL);
218 mapi_ctx = mapiadmin_ctx->session->mapi_ctx;
219 MAPI_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
221 profile = mapiadmin_ctx->session->profile;
222 dom_sid = mapiadmin_ctx->user_ctx->user_sid;
224 /* initialize memory context */
225 mem_ctx = talloc_named(NULL, 0, "mapiadmin_user_extend");
227 /* open LDAP connection */
228 ev = tevent_context_init(talloc_autofree_context());
229 remote_ldb_url = talloc_asprintf(mem_ctx, "ldap://%s", profile->server);
230 MAPI_RETVAL_IF(!remote_ldb_url, MAPI_E_CORRUPT_DATA, mem_ctx);
231 remote_ldb = ldb_wrap_connect(mem_ctx, ev, mapi_ctx->lp_ctx, remote_ldb_url,
232 NULL, mapiadmin_ctx->session->profile->credentials, 0);
233 MAPI_RETVAL_IF(!remote_ldb, MAPI_E_NETWORK_ERROR, mem_ctx);
235 /* Search the user_dn */
236 account_dn = samdb_search_dn(remote_ldb, mem_ctx, NULL,
237 "(&(objectSid=%s)(objectClass=user))",
238 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
240 ret = ldb_search(remote_ldb, mem_ctx, &res, account_dn, LDB_SCOPE_SUBTREE, dom_attrs, "(objectSid=%s)",
241 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
242 MAPI_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, mem_ctx);
243 MAPI_RETVAL_IF(res->count != 1, MAPI_E_NOT_FOUND, mem_ctx);
245 /* Prepare a new message for modify */
246 msg = ldb_msg_new(mem_ctx);
247 MAPI_RETVAL_IF(!msg, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
249 msg->dn = res->msgs[0]->dn;
251 /* message: givenName */
252 exch_attrs[0] = talloc_strdup(mem_ctx, mapiadmin_ctx->username);
253 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "givenName", exch_attrs[0]);
254 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
256 /* message: userAccountControl */
257 exch_attrs[1] = talloc_asprintf(mem_ctx, "513");
258 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "userAccountControl",
260 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
261 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
264 retval = GetProfileAttr(profile, "ProxyAddress", &count, &values);
265 MAPI_RETVAL_IF(retval, retval, mem_ctx);
267 for (i = 0; i < count; i++) {
268 if (values[i] && !strncasecmp("smtp", values[i], 4)) {
269 realm = strchr(values[i], '@');
273 MAPI_RETVAL_IF(!realm, MAPI_E_NOT_FOUND, mem_ctx);
275 exch_attrs[2] = talloc_asprintf(mem_ctx, "%s@%s", mapiadmin_ctx->username, realm);
276 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "mail", exch_attrs[2]);
277 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
279 /* message: mailNickname */
280 exch_attrs[3] = talloc_strdup(mem_ctx, mapiadmin_ctx->username);
281 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "mailNickname", exch_attrs[3]);
282 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
284 /* message: mDBUseDefaults */
285 exch_attrs[4] = talloc_asprintf(mem_ctx, "TRUE");
286 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
287 "mDBUseDefaults", exch_attrs[4]);
288 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
290 /* message: legacyExchangeDN */
291 org = talloc_strndup(mem_ctx, profile->mailbox,
292 strlen(profile->mailbox) - strlen(profile->username));
293 exch_attrs[5] = talloc_asprintf(mem_ctx, "%s%s", org, mapiadmin_ctx->username);
295 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
296 "legacyExchangeDN", exch_attrs[5]);
297 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
299 /* message: msExchHomeServerName */
300 exch_attrs[6] = talloc_strdup(mem_ctx, profile->homemdb);
301 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
302 "msExchHomeServerName", exch_attrs[6]);
303 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
305 /* Prior we call ldb_modify, set up async ldb request on
308 req = talloc_zero(mem_ctx, struct ldb_request);
309 tce_ctx = talloc_zero(mem_ctx, struct tce_async_context);
310 controls = ldb_parse_control_strings(remote_ldb, mem_ctx, control_strings);
312 ret = ldb_build_search_req(&req, remote_ldb, mem_ctx,
321 DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_build_search_req", ldb_strerror(ret)));
322 MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CALL_FAILED, mem_ctx);
324 ldb_set_timeout(mem_ctx, req, 60);
326 ret = ldb_request(remote_ldb, req);
327 DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_request", ldb_strerror(ret)));
328 MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CALL_FAILED, mem_ctx);
330 ret = ldb_modify(remote_ldb, msg);
331 DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_modify", ldb_strerror(ret)));
332 MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CORRUPT_DATA, mem_ctx);
335 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
336 DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_wait", ldb_strerror(ret)));
337 MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CALL_FAILED, mem_ctx);
338 MAPI_RETVAL_IF(!tce_ctx->found, MAPI_E_CALL_FAILED, mem_ctx);
340 /* When successful replace UserAccountControl attr in the user
344 msg = ldb_msg_new(mem_ctx);
345 MAPI_RETVAL_IF(!msg, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
346 msg->dn = res->msgs[0]->dn;
348 UserAccountControl = talloc_asprintf(mem_ctx, "66048");
349 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
350 "UserAccountControl", UserAccountControl);
351 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
352 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
354 ret = ldb_modify(remote_ldb, msg);
355 DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_modify", ldb_strerror(ret)));
356 MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CORRUPT_DATA, mem_ctx);
358 /* reset errno before leaving */
360 talloc_free(mem_ctx);
361 return MAPI_E_SUCCESS;
365 * Add a user to Active Directory
367 _PUBLIC_ enum MAPISTATUS mapiadmin_user_add(struct mapiadmin_ctx *mapiadmin_ctx)
371 enum MAPISTATUS retval;
372 struct mapi_context *mapi_ctx;
373 struct mapi_profile *profile;
374 struct samr_CreateUser2 r;
375 struct samr_GetUserPwInfo pwp;
376 struct samr_SetUserInfo s;
377 union samr_UserInfo u;
378 uint32_t access_granted;
380 DATA_BLOB session_key;
381 struct lsa_String name;
382 int policy_min_pw_len = 0;
384 mem_ctx = talloc_named(NULL, 0, "mapiadmin_user_add");
386 retval = mapiadmin_samr_connect(mapiadmin_ctx, mem_ctx);
387 MAPI_RETVAL_IF(retval, retval, mem_ctx);
389 DEBUG(3, ("Creating account %s\n", mapiadmin_ctx->username));
390 profile = mapiadmin_ctx->session->profile;
392 mapi_ctx = mapiadmin_ctx->session->mapi_ctx;
393 MAPI_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, mem_ctx);
396 name.string = mapiadmin_ctx->username;
397 r.in.domain_handle = mapiadmin_ctx->handle;
398 r.in.account_name = &name;
399 r.in.acct_flags = ACB_NORMAL;
400 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
401 r.out.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
402 r.out.access_granted = &access_granted;
405 status = dcerpc_samr_CreateUser2_r(mapiadmin_ctx->user_ctx->p->binding_handle, mapiadmin_ctx->user_ctx, &r);
407 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
408 mapiadmin_user_del(mapiadmin_ctx);
409 if (NT_STATUS_IS_OK(status)) {
412 MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
416 if (!NT_STATUS_IS_OK(status)) {
417 DEBUG(3, ("CreateUser2 failed - %s\n", nt_errstr(status)));
418 MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
421 mapiadmin_ctx->user_ctx->user_sid = dom_sid_add_rid(mapiadmin_ctx->user_ctx, mapiadmin_ctx->user_ctx->dom_sid, rid);
423 pwp.in.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
424 pwp.out.info = talloc_zero(mem_ctx, struct samr_PwInfo);
426 status = dcerpc_samr_GetUserPwInfo_r(mapiadmin_ctx->user_ctx->p->binding_handle, mapiadmin_ctx->user_ctx, &pwp);
427 if (NT_STATUS_IS_OK(status)) {
428 policy_min_pw_len = pwp.out.info->min_password_length;
430 DEBUG(3, ("GetUserPwInfo failed - %s\n", nt_errstr(status)));
431 MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
434 if (!mapiadmin_ctx->password) {
435 mapiadmin_ctx->password = generate_random_str(mapiadmin_ctx->user_ctx, MAX(8, policy_min_pw_len));
438 DEBUG(3, ("Setting account password '%s'\n", mapiadmin_ctx->password));
441 s.in.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
445 encode_pw_buffer(u.info24.password.data, mapiadmin_ctx->password, STR_UNICODE);
446 u.info24.password_expired = 0;
448 status = dcerpc_fetch_session_key(mapiadmin_ctx->user_ctx->p, &session_key);
449 if (!NT_STATUS_IS_OK(status)) {
450 DEBUG(3, ("SetUserInfo level %d - no session key - %s\n",
451 s.in.level, nt_errstr(status)));
452 mapiadmin_user_del(mapiadmin_ctx);
453 MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
456 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
458 status = dcerpc_samr_SetUserInfo_r(mapiadmin_ctx->user_ctx->p->binding_handle, mapiadmin_ctx->user_ctx, &s);
459 if (!NT_STATUS_IS_OK(status)) {
460 DEBUG(3, ("SetUserInfo failed - %s\n", nt_errstr(status)));
461 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
462 MAPI_RETVAL_IF(1, MAPI_E_BAD_VALUE, mem_ctx);
464 MAPI_RETVAL_IF(1, MAPI_E_CALL_FAILED, mem_ctx);
469 s.in.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
473 u.info21.acct_flags = ACB_NORMAL | ACB_PWNOEXP;
474 u.info21.fields_present = SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;
476 u.info21.comment.string = talloc_asprintf(mapiadmin_ctx->user_ctx,
477 mapiadmin_ctx->comment ?
478 mapiadmin_ctx->comment :
479 "Created by OpenChange: %s",
480 timestring(mapiadmin_ctx->user_ctx, time(NULL)));
482 u.info21.full_name.string = talloc_asprintf(mapiadmin_ctx->user_ctx,
483 mapiadmin_ctx->fullname ?
484 mapiadmin_ctx->fullname :
485 "Account for OpenChange: %s",
486 timestring(mapiadmin_ctx->user_ctx, time(NULL)));
488 u.info21.description.string = talloc_asprintf(mapiadmin_ctx->user_ctx,
489 mapiadmin_ctx->description ?
490 mapiadmin_ctx->description :
491 "OpenChange account created by host %s: %s",
492 lpcfg_netbios_name(mapi_ctx->lp_ctx),
493 timestring(mapiadmin_ctx->user_ctx, time(NULL)));
495 DEBUG(3, ("Resetting ACB flags, force pw change time\n"));
497 status = dcerpc_samr_SetUserInfo_r(mapiadmin_ctx->user_ctx->p->binding_handle, mapiadmin_ctx->user_ctx, &s);
498 if (!NT_STATUS_IS_OK(status)) {
499 DEBUG(3, ("SetUserInfo failed - %s\n", nt_errstr(status)));
500 MAPI_RETVAL_IF(1, MAPI_E_CALL_FAILED, mem_ctx);
502 retval = mapiadmin_user_extend(mapiadmin_ctx);
503 if (retval != MAPI_E_SUCCESS) {
504 DEBUG(3, ("mapiadmin_user_extend: 0x%x\n", GetLastError()));
505 mapiadmin_user_del(mapiadmin_ctx);
506 MAPI_RETVAL_IF(1, MAPI_E_CALL_FAILED,mem_ctx);
509 talloc_free(mem_ctx);
510 return MAPI_E_SUCCESS;
514 * Delete a user from Active Directory
516 _PUBLIC_ enum MAPISTATUS mapiadmin_user_del(struct mapiadmin_ctx *mapiadmin_ctx)
519 enum MAPISTATUS retval;
521 struct samr_DeleteUser d;
522 struct policy_handle user_handle;
524 struct samr_LookupNames n;
525 struct lsa_String sname;
526 struct samr_OpenUser r;
528 MAPI_RETVAL_IF(!mapiadmin_ctx, MAPI_E_NOT_INITIALIZED, NULL);
529 MAPI_RETVAL_IF(!mapiadmin_ctx->username, MAPI_E_NOT_INITIALIZED, NULL);
531 mem_ctx = talloc_named(NULL, 0, "mapiadmin_user_del");
533 /* Initiate SAMR connection if not already done */
534 if (!mapiadmin_ctx->user_ctx) {
535 retval = mapiadmin_samr_connect(mapiadmin_ctx, mem_ctx);
536 MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
539 sname.string = mapiadmin_ctx->username;
541 n.in.domain_handle = mapiadmin_ctx->handle;
545 n.out.rids = talloc_zero(mem_ctx, struct samr_Ids);
546 n.out.types = talloc_zero(mem_ctx, struct samr_Ids);
548 status = dcerpc_samr_LookupNames_r(mapiadmin_ctx->user_ctx->p->binding_handle, mem_ctx, &n);
549 if (NT_STATUS_IS_OK(status)) {
550 rid = n.out.rids->ids[0];
552 talloc_free(mem_ctx);
553 return MAPI_E_NOT_FOUND;
556 r.in.domain_handle = mapiadmin_ctx->handle;
557 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
559 r.out.user_handle = &user_handle;
561 status = dcerpc_samr_OpenUser_r(mapiadmin_ctx->user_ctx->p->binding_handle, mem_ctx, &r);
562 if (!NT_STATUS_IS_OK(status)) {
563 DEBUG(3, ("OpenUser(%s) failed - %s\n", mapiadmin_ctx->username, nt_errstr(status)));
564 MAPI_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_NOT_FOUND, mem_ctx);
567 d.in.user_handle = &user_handle;
568 d.out.user_handle = &user_handle;
569 status = dcerpc_samr_DeleteUser_r(mapiadmin_ctx->user_ctx->p->binding_handle, mem_ctx, &d);
570 MAPI_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
572 talloc_free(mem_ctx);
573 return MAPI_E_SUCCESS;
576 _PUBLIC_ enum MAPISTATUS mapiadmin_user_mod(struct mapiadmin_ctx *mapiadmin)
578 return MAPI_E_NO_SUPPORT;