Daily ChangeLog Update
[OpenChange-git-clone.git] / libmapiadmin / mapiadmin_user.c
bloba1265bdf7476584e08ea87b7bb243e3006fd0e24
1 /*
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-2008.
11 SAMR related code
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>
29 #include <param.h>
30 #include <credentials.h>
31 #include <samba/popt.h>
32 #include <ldb_errors.h>
33 #include <ldb_wrap.h>
34 #include <ldap_ndr.h>
36 #include <core/error.h>
37 #include <gen_ndr/ndr_samr.h>
38 #include <gen_ndr/ndr_samr_c.h>
40 #include <time.h>
42 /**
43 \file
44 User management functions for mapiadmin
47 /**
48 * open connection so SAMR + Join Domain
49 * common code needed when adding or removing users
51 static enum MAPISTATUS mapiadmin_samr_connect(struct mapiadmin_ctx *mapiadmin_ctx,
52 TALLOC_CTX *mem_ctx)
54 NTSTATUS status;
55 struct tevent_context *ev;
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(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
65 MAPI_RETVAL_IF(!mapiadmin_ctx, MAPI_E_NOT_INITIALIZED, NULL);
66 MAPI_RETVAL_IF(!mapiadmin_ctx->session, MAPI_E_NOT_INITIALIZED, NULL);
67 MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile, MAPI_E_NOT_INITIALIZED, NULL);
68 MAPI_RETVAL_IF(!mapiadmin_ctx->session->profile->credentials, MAPI_E_NOT_INITIALIZED, NULL);
69 MAPI_RETVAL_IF(!mapiadmin_ctx->username, MAPI_E_NOT_INITIALIZED, NULL);
71 profile = mapiadmin_ctx->session->profile;
73 mapiadmin_ctx->user_ctx = talloc_zero(mem_ctx, struct test_join);
74 MAPI_RETVAL_IF(!mapiadmin_ctx->user_ctx, MAPI_E_NOT_ENOUGH_RESOURCES ,NULL);
76 DEBUG(3, ("Connecting to SAMR\n"));
78 ev = tevent_context_init(mem_ctx);
80 status = dcerpc_pipe_connect(mapiadmin_ctx->user_ctx,
81 &mapiadmin_ctx->user_ctx->p,
82 mapiadmin_ctx->dc_binding ?
83 mapiadmin_ctx->dc_binding :
84 mapiadmin_ctx->binding,
85 &ndr_table_samr,
86 profile->credentials, ev, global_mapi_ctx->lp_ctx);
88 MAPI_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, NULL);
90 profile = mapiadmin_ctx->session->profile;
92 c.in.system_name = NULL;
93 c.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
94 c.out.connect_handle = &handle;
96 status = dcerpc_samr_Connect(mapiadmin_ctx->user_ctx->p,
97 mapiadmin_ctx->user_ctx, &c);
98 if (!NT_STATUS_IS_OK(status)) {
99 const char *errstr = nt_errstr(status);
100 if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) {
101 errstr = dcerpc_errstr(mapiadmin_ctx->user_ctx, mapiadmin_ctx->user_ctx->p->last_fault_code);
103 DEBUG(3, ("samr_Connect failed - %s\n", errstr));
104 return MAPI_E_CALL_FAILED;
107 DEBUG(3, ("Opening domain %s\n", profile->domain));
109 name.string = profile->domain;
110 l.in.connect_handle = &handle;
111 l.in.domain_name = &name;
113 l.out.sid = talloc(mem_ctx, struct dom_sid2 *);
114 talloc_steal(mapiadmin_ctx->user_ctx, l.out.sid);
116 status = dcerpc_samr_LookupDomain(mapiadmin_ctx->user_ctx->p,
117 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(mapiadmin_ctx->user_ctx->p, 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));
140 errno = 0;
141 return MAPI_E_SUCCESS;
145 struct tce_async_context {
146 int found;
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);
152 int ret;
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__));
159 actx->found = 1;
160 talloc_free(ares);
161 return ldb_request_done(req, LDB_SUCCESS);
163 break;
164 case LDB_REPLY_DONE:
165 ret = 0;
166 break;
167 default:
168 DEBUG(3, ("[%s:%d]: unknown Reply Type ignore it\n", __FUNCTION__, __LINE__));
169 talloc_free(ares);
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;
178 return LDB_SUCCESS;
182 * Extend user attributes to be Exchange user
184 _PUBLIC_ enum MAPISTATUS mapiadmin_user_extend(struct mapiadmin_ctx *mapiadmin_ctx)
186 TALLOC_CTX *mem_ctx;
187 enum MAPISTATUS retval;
188 struct tevent_context *ev = NULL;
189 struct mapi_profile *profile;
190 struct ldb_context *remote_ldb;
191 struct ldb_request *req;
192 struct ldb_message *msg;
193 struct ldb_result *res;
194 struct ldb_control **controls;
195 const char *control_strings[2] = { "notification:0", NULL };
196 struct tce_async_context *tce_ctx;
197 const struct dom_sid *dom_sid;
198 char *remote_ldb_url;
199 const char * const dom_attrs[] = { "*", NULL };
200 int ret;
201 uint32_t count;
202 char **values;
203 const char *exch_attrs[7];
204 int i;
205 char *realm = NULL;
206 char *org = NULL;
207 const char *UserAccountControl;
208 struct ldb_dn *account_dn;
210 /* Sanity checks */
211 MAPI_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
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 profile = mapiadmin_ctx->session->profile;
219 dom_sid = mapiadmin_ctx->user_ctx->user_sid;
221 /* initialize memory context */
222 mem_ctx = talloc_named(NULL, 0, "mapiadmin_user_extend");
224 /* open LDAP connection */
225 ev = tevent_context_init(talloc_autofree_context());
226 remote_ldb_url = talloc_asprintf(mem_ctx, "ldap://%s", profile->server);
227 MAPI_RETVAL_IF(!remote_ldb_url, MAPI_E_CORRUPT_DATA, mem_ctx);
228 remote_ldb = ldb_wrap_connect(mem_ctx, ev, global_mapi_ctx->lp_ctx, remote_ldb_url,
229 NULL, mapiadmin_ctx->session->profile->credentials, 0, NULL);
230 MAPI_RETVAL_IF(!remote_ldb, MAPI_E_NETWORK_ERROR, mem_ctx);
232 /* Search the user_dn */
233 account_dn = samdb_search_dn(remote_ldb, mem_ctx, NULL,
234 "(&(objectSid=%s)(objectClass=user))",
235 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
237 ret = ldb_search(remote_ldb, mem_ctx, &res, account_dn, LDB_SCOPE_SUBTREE, dom_attrs, "(objectSid=%s)",
238 ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
239 MAPI_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, mem_ctx);
240 MAPI_RETVAL_IF(res->count != 1, MAPI_E_NOT_FOUND, mem_ctx);
242 /* Prepare a new message for modify */
243 msg = ldb_msg_new(mem_ctx);
244 MAPI_RETVAL_IF(!msg, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
246 msg->dn = res->msgs[0]->dn;
248 /* message: givenName */
249 exch_attrs[0] = talloc_strdup(mem_ctx, mapiadmin_ctx->username);
250 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "givenName", exch_attrs[0]);
251 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
253 /* message: userAccountControl */
254 exch_attrs[1] = talloc_asprintf(mem_ctx, "513");
255 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "userAccountControl",
256 exch_attrs[1]);
257 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
258 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
260 /* message: mail */
261 retval = GetProfileAttr(profile, "ProxyAddress", &count, &values);
262 MAPI_RETVAL_IF(retval, retval, mem_ctx);
264 for (i = 0; i < count; i++) {
265 if (values[i] && !strncasecmp("smtp", values[i], 4)) {
266 realm = strchr(values[i], '@');
267 realm += 1;
270 MAPI_RETVAL_IF(!realm, MAPI_E_NOT_FOUND, mem_ctx);
272 exch_attrs[2] = talloc_asprintf(mem_ctx, "%s@%s", mapiadmin_ctx->username, realm);
273 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "mail", exch_attrs[2]);
274 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
276 /* message: mailNickname */
277 exch_attrs[3] = talloc_strdup(mem_ctx, mapiadmin_ctx->username);
278 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg, "mailNickname", exch_attrs[3]);
279 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
281 /* message: mDBUseDefaults */
282 exch_attrs[4] = talloc_asprintf(mem_ctx, "TRUE");
283 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
284 "mDBUseDefaults", exch_attrs[4]);
285 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
287 /* message: legacyExchangeDN */
288 org = talloc_strndup(mem_ctx, profile->mailbox,
289 strlen(profile->mailbox) - strlen(profile->username));
290 exch_attrs[5] = talloc_asprintf(mem_ctx, "%s%s", org, mapiadmin_ctx->username);
291 talloc_free(org);
292 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
293 "legacyExchangeDN", exch_attrs[5]);
294 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
296 /* message: msExchHomeServerName */
297 exch_attrs[6] = talloc_strdup(mem_ctx, profile->homemdb);
298 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
299 "msExchHomeServerName", exch_attrs[6]);
300 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
302 /* Prior we call ldb_modify, set up async ldb request on
303 * msExchMailboxGuid
305 req = talloc_zero(mem_ctx, struct ldb_request);
306 tce_ctx = talloc_zero(mem_ctx, struct tce_async_context);
307 controls = ldb_parse_control_strings(remote_ldb, mem_ctx, control_strings);
309 ret = ldb_build_search_req(&req, remote_ldb, mem_ctx,
310 msg->dn,
311 LDB_SCOPE_BASE,
312 "(objectclass=*)",
313 NULL,
314 controls,
315 (void *)tce_ctx,
316 tce_search_callback,
317 NULL);
318 DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_build_search_req", ldb_strerror(ret)));
319 MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CALL_FAILED, mem_ctx);
321 ldb_set_timeout(mem_ctx, req, 60);
323 ret = ldb_request(remote_ldb, req);
324 DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_request", ldb_strerror(ret)));
325 MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CALL_FAILED, mem_ctx);
327 ret = ldb_modify(remote_ldb, msg);
328 DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_modify", ldb_strerror(ret)));
329 MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CORRUPT_DATA, mem_ctx);
331 /* async search */
332 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
333 DEBUG(3, (MAPIADMIN_DEBUG_STR, "ldb_wait", ldb_strerror(ret)));
334 MAPI_RETVAL_IF((ret != LDB_SUCCESS), MAPI_E_CALL_FAILED, mem_ctx);
335 MAPI_RETVAL_IF(!tce_ctx->found, MAPI_E_CALL_FAILED, mem_ctx);
337 /* When successful replace UserAccountControl attr in the user
338 * record
340 talloc_free(msg);
341 msg = ldb_msg_new(mem_ctx);
342 MAPI_RETVAL_IF(!msg, MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
343 msg->dn = res->msgs[0]->dn;
345 UserAccountControl = talloc_asprintf(mem_ctx, "66048");
346 ret = samdb_msg_add_string(remote_ldb, mem_ctx, msg,
347 "UserAccountControl", UserAccountControl);
348 MAPI_RETVAL_IF((ret == -1), MAPI_E_NOT_ENOUGH_RESOURCES, mem_ctx);
350 ret = samdb_replace(remote_ldb, mem_ctx, msg);
351 DEBUG(3, (MAPIADMIN_DEBUG_STR, "samdb_replace", ldb_strerror(ret)));
352 MAPI_RETVAL_IF((ret != 0), MAPI_E_CORRUPT_DATA, mem_ctx);
354 /* reset errno before leaving */
355 errno = 0;
356 talloc_free(mem_ctx);
357 return MAPI_E_SUCCESS;
361 * Add a user to Active Directory
363 _PUBLIC_ enum MAPISTATUS mapiadmin_user_add(struct mapiadmin_ctx *mapiadmin_ctx)
365 TALLOC_CTX *mem_ctx;
366 NTSTATUS status;
367 enum MAPISTATUS retval;
368 struct mapi_profile *profile;
369 struct samr_CreateUser2 r;
370 struct samr_GetUserPwInfo pwp;
371 struct samr_SetUserInfo s;
372 union samr_UserInfo u;
373 uint32_t access_granted;
374 uint32_t rid;
375 DATA_BLOB session_key;
376 struct lsa_String name;
377 int policy_min_pw_len = 0;
379 mem_ctx = talloc_named(NULL, 0, "mapiadmin_user_add");
381 retval = mapiadmin_samr_connect(mapiadmin_ctx, mem_ctx);
382 MAPI_RETVAL_IF(retval, retval, mem_ctx);
384 DEBUG(3, ("Creating account %s\n", mapiadmin_ctx->username));
385 profile = mapiadmin_ctx->session->profile;
387 again:
388 name.string = mapiadmin_ctx->username;
389 r.in.domain_handle = mapiadmin_ctx->handle;
390 r.in.account_name = &name;
391 r.in.acct_flags = ACB_NORMAL;
392 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
393 r.out.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
394 r.out.access_granted = &access_granted;
395 r.out.rid = &rid;
397 status = dcerpc_samr_CreateUser2(mapiadmin_ctx->user_ctx->p,
398 mapiadmin_ctx->user_ctx, &r);
400 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
401 mapiadmin_user_del(mapiadmin_ctx);
402 if (NT_STATUS_IS_OK(status)) {
403 goto again;
404 } else {
405 MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
409 if (!NT_STATUS_IS_OK(status)) {
410 DEBUG(3, ("CreateUser2 failed - %s\n", nt_errstr(status)));
411 MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
414 mapiadmin_ctx->user_ctx->user_sid = dom_sid_add_rid(mapiadmin_ctx->user_ctx, mapiadmin_ctx->user_ctx->dom_sid, rid);
416 pwp.in.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
417 pwp.out.info = talloc_zero(mem_ctx, struct samr_PwInfo);
419 status = dcerpc_samr_GetUserPwInfo(mapiadmin_ctx->user_ctx->p, mapiadmin_ctx->user_ctx, &pwp);
420 if (NT_STATUS_IS_OK(status)) {
421 policy_min_pw_len = pwp.out.info->min_password_length;
422 } else {
423 DEBUG(3, ("GetUserPwInfo failed - %s\n", nt_errstr(status)));
424 MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
427 if (!mapiadmin_ctx->password) {
428 mapiadmin_ctx->password = generate_random_str(mapiadmin_ctx->user_ctx, MAX(8, policy_min_pw_len));
431 DEBUG(3, ("Setting account password '%s'\n", mapiadmin_ctx->password));
433 ZERO_STRUCT(u);
434 s.in.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
435 s.in.info = &u;
436 s.in.level = 24;
438 encode_pw_buffer(u.info24.password.data, mapiadmin_ctx->password, STR_UNICODE);
439 u.info24.password_expired = 0;
441 status = dcerpc_fetch_session_key(mapiadmin_ctx->user_ctx->p, &session_key);
442 if (!NT_STATUS_IS_OK(status)) {
443 DEBUG(3, ("SetUserInfo level %d - no session key - %s\n",
444 s.in.level, nt_errstr(status)));
445 mapiadmin_user_del(mapiadmin_ctx);
446 MAPI_RETVAL_IF(1,MAPI_E_CALL_FAILED,mem_ctx);
449 arcfour_crypt_blob(u.info24.password.data, 516, &session_key);
451 status = dcerpc_samr_SetUserInfo(mapiadmin_ctx->user_ctx->p, mapiadmin_ctx->user_ctx, &s);
452 if (!NT_STATUS_IS_OK(status)) {
453 DEBUG(3, ("SetUserInfo failed - %s\n", nt_errstr(status)));
454 if (NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {
455 MAPI_RETVAL_IF(1, MAPI_E_BAD_VALUE, mem_ctx);
456 } else {
457 MAPI_RETVAL_IF(1, MAPI_E_CALL_FAILED, mem_ctx);
461 ZERO_STRUCT(u);
462 s.in.user_handle = &mapiadmin_ctx->user_ctx->user_handle;
463 s.in.info = &u;
464 s.in.level = 21;
466 u.info21.acct_flags = ACB_NORMAL | ACB_PWNOEXP;
467 u.info21.fields_present = SAMR_FIELD_ACCT_FLAGS | SAMR_FIELD_DESCRIPTION | SAMR_FIELD_COMMENT | SAMR_FIELD_FULL_NAME;
469 u.info21.comment.string = talloc_asprintf(mapiadmin_ctx->user_ctx,
470 mapiadmin_ctx->comment ?
471 mapiadmin_ctx->comment :
472 "Created by OpenChange: %s",
473 timestring(mapiadmin_ctx->user_ctx, time(NULL)));
475 u.info21.full_name.string = talloc_asprintf(mapiadmin_ctx->user_ctx,
476 mapiadmin_ctx->fullname ?
477 mapiadmin_ctx->fullname :
478 "Account for OpenChange: %s",
479 timestring(mapiadmin_ctx->user_ctx, time(NULL)));
481 u.info21.description.string = talloc_asprintf(mapiadmin_ctx->user_ctx,
482 mapiadmin_ctx->description ?
483 mapiadmin_ctx->description :
484 "OpenChange account created by host %s: %s",
485 lp_netbios_name(global_mapi_ctx->lp_ctx),
486 timestring(mapiadmin_ctx->user_ctx, time(NULL)));
488 DEBUG(3, ("Resetting ACB flags, force pw change time\n"));
490 status = dcerpc_samr_SetUserInfo(mapiadmin_ctx->user_ctx->p, mapiadmin_ctx->user_ctx, &s);
491 if (!NT_STATUS_IS_OK(status)) {
492 DEBUG(3, ("SetUserInfo failed - %s\n", nt_errstr(status)));
493 MAPI_RETVAL_IF(1, MAPI_E_CALL_FAILED, mem_ctx);
495 retval = mapiadmin_user_extend(mapiadmin_ctx);
496 if (retval != MAPI_E_SUCCESS) {
497 DEBUG(3, ("mapiadmin_user_extend: 0x%x\n", GetLastError()));
498 mapiadmin_user_del(mapiadmin_ctx);
499 MAPI_RETVAL_IF(1, MAPI_E_CALL_FAILED,mem_ctx);
502 talloc_free(mem_ctx);
503 return MAPI_E_SUCCESS;
507 * Delete a user from Active Directory
509 _PUBLIC_ enum MAPISTATUS mapiadmin_user_del(struct mapiadmin_ctx *mapiadmin_ctx)
511 TALLOC_CTX *mem_ctx;
512 enum MAPISTATUS retval;
513 NTSTATUS status;
514 struct samr_DeleteUser d;
515 struct policy_handle user_handle;
516 uint32_t rid;
517 struct samr_LookupNames n;
518 struct lsa_String sname;
519 struct samr_OpenUser r;
521 MAPI_RETVAL_IF(!mapiadmin_ctx, MAPI_E_NOT_INITIALIZED, NULL);
522 MAPI_RETVAL_IF(!mapiadmin_ctx->username, MAPI_E_NOT_INITIALIZED, NULL);
524 mem_ctx = talloc_named(NULL, 0, "mapiadmin_user_del");
526 /* Initiate SAMR connection if not already done */
527 if (!mapiadmin_ctx->user_ctx) {
528 retval = mapiadmin_samr_connect(mapiadmin_ctx, mem_ctx);
529 MAPI_RETVAL_IF(retval, GetLastError(), mem_ctx);
532 sname.string = mapiadmin_ctx->username;
534 n.in.domain_handle = mapiadmin_ctx->handle;
535 n.in.num_names = 1;
536 n.in.names = &sname;
538 n.out.rids = talloc_zero(mem_ctx, struct samr_Ids);
539 n.out.types = talloc_zero(mem_ctx, struct samr_Ids);
541 status = dcerpc_samr_LookupNames(mapiadmin_ctx->user_ctx->p, mem_ctx, &n);
542 if (NT_STATUS_IS_OK(status)) {
543 rid = n.out.rids->ids[0];
544 } else {
545 talloc_free(mem_ctx);
546 return MAPI_E_NOT_FOUND;
549 r.in.domain_handle = mapiadmin_ctx->handle;
550 r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
551 r.in.rid = rid;
552 r.out.user_handle = &user_handle;
554 status = dcerpc_samr_OpenUser(mapiadmin_ctx->user_ctx->p, mem_ctx, &r);
555 if (!NT_STATUS_IS_OK(status)) {
556 DEBUG(3, ("OpenUser(%s) failed - %s\n", mapiadmin_ctx->username, nt_errstr(status)));
557 MAPI_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_NOT_FOUND, mem_ctx);
560 d.in.user_handle = &user_handle;
561 d.out.user_handle = &user_handle;
562 status = dcerpc_samr_DeleteUser(mapiadmin_ctx->user_ctx->p, mem_ctx, &d);
563 MAPI_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
565 talloc_free(mem_ctx);
566 return MAPI_E_SUCCESS;
569 _PUBLIC_ enum MAPISTATUS mapiadmin_user_mod(struct mapiadmin_ctx *mapiadmin)
571 return MAPI_E_NO_SUPPORT;