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.
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 <samba/popt.h>
32 #include <ldb_errors.h>
36 #include <core/error.h>
37 #include <gen_ndr/ndr_samr.h>
38 #include <gen_ndr/ndr_samr_c.h>
44 User management functions for mapiadmin
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
,
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
,
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
));
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_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
};
203 const char *exch_attrs
[7];
207 const char *UserAccountControl
;
208 struct ldb_dn
*account_dn
;
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",
257 MAPI_RETVAL_IF((ret
== -1), MAPI_E_NOT_ENOUGH_RESOURCES
, mem_ctx
);
258 msg
->elements
[1].flags
= LDB_FLAG_MOD_REPLACE
;
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
], '@');
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
);
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
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
,
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
);
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
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 */
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
)
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
;
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
;
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
;
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
)) {
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
;
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
));
434 s
.in
.user_handle
= &mapiadmin_ctx
->user_ctx
->user_handle
;
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
);
457 MAPI_RETVAL_IF(1, MAPI_E_CALL_FAILED
, mem_ctx
);
462 s
.in
.user_handle
= &mapiadmin_ctx
->user_ctx
->user_handle
;
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
)
512 enum MAPISTATUS retval
;
514 struct samr_DeleteUser d
;
515 struct policy_handle user_handle
;
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
;
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];
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
;
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
;