/* * samr_create_user * * Create a user in the domain specified by the domain handle. If this * call is successful, the server will return the RID for the user and * a user handle, which may be used to set or query the SAM. * * Observed status codes: * NT_STATUS_INVALID_PARAMETER * NT_STATUS_INVALID_ACCOUNT_NAME * NT_STATUS_ACCESS_DENIED * NT_STATUS_USER_EXISTS * * Returns 0 on success. Otherwise returns an NT status code. */ DWORD samr_create_user(mlsvc_handle_t *domain_handle, char *username, DWORD account_flags, DWORD *rid, mlsvc_handle_t *user_handle) { struct samr_CreateUser arg; ndr_heap_t *heap; int opnum; int rc; DWORD status = 0; if (ndr_is_null_handle(domain_handle) || username == NULL || rid == NULL) { return (NT_STATUS_INVALID_PARAMETER); } opnum = SAMR_OPNUM_CreateUser; bzero(&arg, sizeof (struct samr_CreateUser)); (void) memcpy(&arg.handle, &domain_handle->handle, sizeof (ndr_hdid_t)); heap = ndr_rpc_get_heap(domain_handle); ndr_heap_mkvcs(heap, username, (ndr_vcstr_t *)&arg.username); arg.account_flags = account_flags; arg.desired_access = 0xE00500B0; rc = ndr_rpc_call(domain_handle, opnum, &arg); if (rc != 0) { status = NT_STATUS_INVALID_PARAMETER; } else if (arg.status != 0) { status = NT_SC_VALUE(arg.status); if (status != NT_STATUS_USER_EXISTS) { smb_tracef("SamrCreateUser[%s]: %s", username, xlate_nt_status(status)); } } else { ndr_inherit_handle(user_handle, domain_handle); (void) memcpy(&user_handle->handle, &arg.user_handle, sizeof (ndr_hdid_t)); *rid = arg.rid; if (ndr_is_null_handle(user_handle)) status = NT_STATUS_INVALID_HANDLE; else status = 0; } ndr_rpc_release(domain_handle); return (status); }
/* * lsar_open_account * * Obtain an LSA account handle. The lsa_handle must be a valid handle * obtained via lsar_open_policy2. The main thing to remember here is * to set up the context in the lsa_account_handle. I'm not sure what * the requirements are for desired access. Some values require admin * access. * * Returns 0 on success. Otherwise non-zero to indicate a failure. */ int lsar_open_account(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid, mlsvc_handle_t *lsa_account_handle) { struct mslsa_OpenAccount arg; int opnum; int rc; if (ndr_is_null_handle(lsa_handle) || sid == NULL) return (-1); opnum = LSARPC_OPNUM_OpenAccount; bzero(&arg, sizeof (struct mslsa_OpenAccount)); (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t)); arg.sid = sid; arg.access_mask = STANDARD_RIGHTS_REQUIRED #if 0 | POLICY_VIEW_AUDIT_INFORMATION | POLICY_GET_PRIVATE_INFORMATION | POLICY_TRUST_ADMIN #endif | POLICY_VIEW_LOCAL_INFORMATION; if ((rc = ndr_rpc_call(lsa_handle, opnum, &arg)) != 0) return (-1); if (arg.status != 0) { rc = -1; } else { ndr_inherit_handle(lsa_account_handle, lsa_handle); (void) memcpy(&lsa_account_handle->handle, &arg.account_handle, sizeof (ndr_hdid_t)); if (ndr_is_null_handle(lsa_account_handle)) rc = -1; } ndr_rpc_release(lsa_handle); return (rc); }
/* * samr_open_domain * * We use a SAM handle to obtain a handle for a domain, specified by * the SID. The SID can be obtain via the LSA interface. A handle for * the domain is returned in domain_handle. */ DWORD samr_open_domain(mlsvc_handle_t *samr_handle, DWORD access_mask, struct samr_sid *sid, mlsvc_handle_t *domain_handle) { struct samr_OpenDomain arg; int opnum; DWORD status; if (ndr_is_null_handle(samr_handle) || sid == NULL || domain_handle == NULL) { return (NT_STATUS_INVALID_PARAMETER); } opnum = SAMR_OPNUM_OpenDomain; bzero(&arg, sizeof (struct samr_OpenDomain)); (void) memcpy(&arg.handle, &samr_handle->handle, sizeof (ndr_hdid_t)); arg.access_mask = access_mask; arg.sid = sid; if (ndr_rpc_call(samr_handle, opnum, &arg) != 0) { status = NT_STATUS_UNSUCCESSFUL; } else if (arg.status != 0) { status = arg.status; } else { status = NT_STATUS_SUCCESS; ndr_inherit_handle(domain_handle, samr_handle); (void) memcpy(&domain_handle->handle, &arg.domain_handle, sizeof (ndr_hdid_t)); if (ndr_is_null_handle(domain_handle)) status = NT_STATUS_INVALID_HANDLE; } if (status != NT_STATUS_SUCCESS) ndr_rpc_status(samr_handle, opnum, status); ndr_rpc_release(samr_handle); return (status); }
/* * samr_open_group * * Use a domain handle to obtain a handle for a group, specified by the * group RID. A group RID (effectively a gid) can be obtained via the * LSA interface. A handle for the group is returned in group_handle. * Once you have a group handle it should be possible to query the SAM * for information on that group. */ int samr_open_group( mlsvc_handle_t *domain_handle, DWORD rid, mlsvc_handle_t *group_handle) { struct samr_OpenGroup arg; int opnum; int rc; if (ndr_is_null_handle(domain_handle) || group_handle == NULL) return (-1); opnum = SAMR_OPNUM_OpenGroup; bzero(&arg, sizeof (struct samr_OpenUser)); (void) memcpy(&arg.handle, &domain_handle->handle, sizeof (ndr_hdid_t)); arg.access_mask = SAM_LOOKUP_INFORMATION | SAM_ACCESS_USER_READ; arg.rid = rid; if ((rc = ndr_rpc_call(domain_handle, opnum, &arg)) != 0) return (-1); if (arg.status != 0) { ndr_rpc_status(domain_handle, opnum, arg.status); rc = -1; } else { ndr_inherit_handle(group_handle, domain_handle); (void) memcpy(&group_handle->handle, &arg.group_handle, sizeof (ndr_hdid_t)); if (ndr_is_null_handle(group_handle)) rc = -1; } ndr_rpc_release(domain_handle); return (rc); }
/* * samr_open_user * * Use a domain handle to obtain a handle for a user, specified by the * user RID. A user RID (effectively a uid) can be obtained via the * LSA interface. A handle for the user is returned in user_handle. * Once you have a user handle it should be possible to query the SAM * for information on that user. */ DWORD samr_open_user(mlsvc_handle_t *domain_handle, DWORD access_mask, DWORD rid, mlsvc_handle_t *user_handle) { struct samr_OpenUser arg; int opnum; DWORD status = NT_STATUS_SUCCESS; if (ndr_is_null_handle(domain_handle) || user_handle == NULL) return (NT_STATUS_INVALID_PARAMETER); opnum = SAMR_OPNUM_OpenUser; bzero(&arg, sizeof (struct samr_OpenUser)); (void) memcpy(&arg.handle, &domain_handle->handle, sizeof (ndr_hdid_t)); arg.access_mask = access_mask; arg.rid = rid; if (ndr_rpc_call(domain_handle, opnum, &arg) != 0) { status = NT_STATUS_UNSUCCESSFUL; } else if (arg.status != 0) { ndr_rpc_status(domain_handle, opnum, arg.status); status = NT_SC_VALUE(arg.status); } else { ndr_inherit_handle(user_handle, domain_handle); (void) memcpy(&user_handle->handle, &arg.user_handle, sizeof (ndr_hdid_t)); if (ndr_is_null_handle(user_handle)) status = NT_STATUS_INVALID_HANDLE; } ndr_rpc_release(domain_handle); return (status); }