1
0
mirror of https://github.com/samba-team/samba.git synced 2025-10-29 04:23:51 +03:00

r793: - don't make templates members of any class that would make them show

up in searches like "objectclass=user"

 - auto-add the computer objectclass for computer accounts on create

 - added two types of password change call in samr server

 - reset last_fault_code before each dcerpc call
This commit is contained in:
Andrew Tridgell
2004-05-20 13:29:38 +00:00
committed by Gerald (Jerry) Carter
parent 3657539623
commit c1a65f83f6
4 changed files with 263 additions and 34 deletions

View File

@@ -467,6 +467,9 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
DATA_BLOB blob, payload;
uint32 remaining, chunk_size;
/* allow the application to tell when a fault has happened */
p->last_fault_code = 0;
init_dcerpc_hdr(p, &pkt);
remaining = stub_data_in->length;

View File

@@ -754,6 +754,11 @@ systemFlags: 0x8c000000
objectCategory: CN=Container,CN=Schema,CN=Configuration,${BASEDN}
isCriticalSystemObject: TRUE
###
# note! the template users must not match normal searches. Be careful
# with what classes you put them in
###
dn: CN=TemplateUser,CN=Templates,${BASEDN}
objectClass: top
objectClass: person
@@ -778,7 +783,6 @@ sAMAccountType: 0x30000000
dn: CN=TemplateMemberServer,CN=Templates,${BASEDN}
objectClass: top
objectClass: computer
objectClass: Template
objectClass: userTemplate
cn: TemplateMemberServer
@@ -799,7 +803,6 @@ sAMAccountType: 0x30000001
dn: CN=TemplateDomainController,CN=Templates,${BASEDN}
objectClass: top
objectClass: computer
objectClass: Template
objectClass: userTemplate
cn: TemplateDomainController

View File

@@ -603,7 +603,7 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
struct dcesrv_handle *u_handle;
int ret;
NTSTATUS status;
const char *container;
const char *container, *additional_class=NULL;
ZERO_STRUCTP(r->out.acct_handle);
*r->out.access_granted = 0;
@@ -651,6 +651,7 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
}
container = "Computers";
additional_class = "computer";
} else if (r->in.acct_flags == ACB_SVRTRUST) {
/* pull in all the template attributes */
@@ -662,6 +663,7 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
}
container = "DomainControllers";
additional_class = "computer";
} else if (r->in.acct_flags == ACB_DOMTRUST) {
/* pull in all the template attributes */
@@ -673,6 +675,7 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
}
container = "ForeignDomains"; /* FIXME: Is this correct?*/
additional_class = "computer";
} else {
return NT_STATUS_INVALID_PARAMETER;
@@ -700,6 +703,9 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "cn", username);
samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "sAMAccountName", username);
samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", "user");
if (additional_class) {
samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectClass", additional_class);
}
samdb_msg_add_string(d_state->sam_ctx, mem_ctx, &msg, "objectSid", sidstr);
samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenCreated", now);
samdb_msg_set_ldaptime(d_state->sam_ctx, mem_ctx, &msg, "whenChanged", now);
@@ -1829,12 +1835,232 @@ static NTSTATUS samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX
samr_ChangePasswordUser
*/
static NTSTATUS samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_ChangePasswordUser *r)
struct samr_ChangePasswordUser *r)
{
struct dcesrv_handle *h;
struct samr_account_state *a_state;
struct ldb_message **res, mod, *msg;
int i, ret;
struct samr_Hash *lmPwdHash=NULL, *ntPwdHash=NULL;
struct samr_Hash new_lmPwdHash, new_ntPwdHash, checkHash;
NTSTATUS status = NT_STATUS_OK;
const char * const attrs[] = { "lmPwdHash", "ntPwdHash" , NULL };
DCESRV_PULL_HANDLE(h, r->in.handle, SAMR_HANDLE_USER);
a_state = h->data;
/* fetch the old hashes */
ret = samdb_search(a_state->sam_ctx, mem_ctx, NULL, &res, attrs,
"dn=%s", a_state->account_dn);
if (ret != 1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
msg = res[0];
/* basic sanity checking on parameters */
if (!r->in.lm_present || !r->in.nt_present ||
!r->in.old_lm_crypted || !r->in.new_lm_crypted ||
!r->in.old_nt_crypted || !r->in.new_nt_crypted) {
/* we should really handle a change with lm not
present */
return NT_STATUS_INVALID_PARAMETER_MIX;
}
if (!r->in.cross1_present || !r->in.nt_cross) {
return NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED;
}
if (!r->in.cross2_present || !r->in.lm_cross) {
return NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED;
}
ret = samdb_result_hashes(mem_ctx, msg, "lmPwdHash", &lmPwdHash);
if (ret != 1) {
return NT_STATUS_WRONG_PASSWORD;
}
ret = samdb_result_hashes(mem_ctx, msg, "ntPwdHash", &ntPwdHash);
if (ret != 1) {
return NT_STATUS_WRONG_PASSWORD;
}
/* decrypt and check the new lm hash */
D_P16(lmPwdHash->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
if (memcmp(checkHash.hash, lmPwdHash->hash, 16) != 0) {
return NT_STATUS_WRONG_PASSWORD;
}
/* decrypt and check the new nt hash */
D_P16(ntPwdHash->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
if (memcmp(checkHash.hash, ntPwdHash->hash, 16) != 0) {
return NT_STATUS_WRONG_PASSWORD;
}
/* check the nt cross hash */
D_P16(lmPwdHash->hash, r->in.nt_cross->hash, checkHash.hash);
if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
return NT_STATUS_WRONG_PASSWORD;
}
/* check the lm cross hash */
D_P16(ntPwdHash->hash, r->in.lm_cross->hash, checkHash.hash);
if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
return NT_STATUS_WRONG_PASSWORD;
}
ZERO_STRUCT(mod);
mod.dn = talloc_strdup(mem_ctx, a_state->account_dn);
if (!mod.dn) {
return NT_STATUS_NO_MEMORY;
}
status = samdb_set_password(a_state->sam_ctx, mem_ctx,
a_state->account_dn, a_state->domain_state->domain_dn,
&mod, NULL, &new_lmPwdHash, &new_ntPwdHash, True);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
for (i=0;i<mod.num_elements;i++) {
mod.elements[i].flags = LDB_FLAG_MOD_REPLACE;
}
/* modify the samdb record */
ret = samdb_modify(a_state->sam_ctx, mem_ctx, &mod);
if (ret != 0) {
return NT_STATUS_UNSUCCESSFUL;
}
return NT_STATUS_OK;
}
/*
samr_OemChangePasswordUser2
*/
static NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_OemChangePasswordUser2 *r)
{
NTSTATUS status;
char new_pass[512];
uint32 new_pass_len;
struct samr_CryptPassword *pwbuf = r->in.password;
void *sam_ctx;
const char *user_dn, *domain_dn;
int ret;
struct ldb_message **res, mod;
const char * const attrs[] = { "objectSid", "lmPwdHash", NULL };
const char *domain_sid;
struct samr_Hash *lmPwdHash;
if (pwbuf == NULL) {
return NT_STATUS_WRONG_PASSWORD;
}
/* this call doesn't take a policy handle, so we need to open
the sam db from scratch */
sam_ctx = samdb_connect();
if (sam_ctx == NULL) {
return NT_STATUS_INVALID_SYSTEM_SERVICE;
}
/* we need the users dn and the domain dn (derived from the
user SID). We also need the current lm password hash in
order to decrypt the incoming password */
ret = samdb_search(sam_ctx,
mem_ctx, NULL, &res, attrs,
"(&(sAMAccountName=%s)(objectclass=user))",
r->in.account->name);
if (ret != 1) {
samdb_close(sam_ctx);
return NT_STATUS_NO_SUCH_USER;
}
user_dn = res[0]->dn;
ret = samdb_result_hashes(mem_ctx, res[0], "lmPwdHash", &lmPwdHash);
if (ret != 1) {
samdb_close(sam_ctx);
return NT_STATUS_WRONG_PASSWORD;
}
/* decrypt the password we have been given */
SamOEMhash(pwbuf->data, lmPwdHash->hash, 516);
if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass),
&new_pass_len, STR_ASCII)) {
DEBUG(3,("samr: failed to decode password buffer\n"));
samdb_close(sam_ctx);
return NT_STATUS_WRONG_PASSWORD;
}
/* work out the domain dn */
domain_sid = samdb_result_sid_prefix(mem_ctx, res[0], "objectSid");
if (domain_sid == NULL) {
samdb_close(sam_ctx);
return NT_STATUS_NO_SUCH_USER;
}
domain_dn = samdb_search_string(sam_ctx, mem_ctx, NULL, "dn",
"(objectSid=%s)", domain_sid);
if (!domain_dn) {
samdb_close(sam_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
ZERO_STRUCT(mod);
mod.dn = talloc_strdup(mem_ctx, user_dn);
if (!mod.dn) {
samdb_close(sam_ctx);
return NT_STATUS_NO_MEMORY;
}
/* set the password - samdb needs to know both the domain and user DNs,
so the domain password policy can be used */
status = samdb_set_password(sam_ctx, mem_ctx,
user_dn, domain_dn,
&mod, new_pass,
NULL, NULL,
True);
if (!NT_STATUS_IS_OK(status)) {
samdb_close(sam_ctx);
return status;
}
/* modify the samdb record */
ret = samdb_modify(sam_ctx, mem_ctx, &mod);
if (ret != 0) {
samdb_close(sam_ctx);
return NT_STATUS_UNSUCCESSFUL;
}
samdb_close(sam_ctx);
return NT_STATUS_OK;
}
/*
samr_ChangePasswordUser2
*/
static NTSTATUS samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_ChangePasswordUser2 *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
samr_ChangePasswordUser3
*/
static NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_ChangePasswordUser3 *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
samr_GetGroupsForUser
*/
@@ -2000,26 +2226,6 @@ static NTSTATUS samr_RemoveMultipleMembersFromAlias(struct dcesrv_call_state *dc
}
/*
samr_OemChangePasswordUser2
*/
static NTSTATUS samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_OemChangePasswordUser2 *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
samr_ChangePasswordUser2
*/
static NTSTATUS samr_ChangePasswordUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_ChangePasswordUser2 *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
samr_GetDomPwInfo
@@ -2152,16 +2358,6 @@ static NTSTATUS samr_Connect4(struct dcesrv_call_state *dce_call, TALLOC_CTX *me
}
/*
samr_ChangePasswordUser3
*/
static NTSTATUS samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct samr_ChangePasswordUser3 *r)
{
DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
}
/*
samr_Connect5
*/

View File

@@ -313,6 +313,33 @@ uint32 samdb_result_rid_from_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
return sid->sub_auths[sid->num_auths-1];
}
/*
pull a dom_sid structure from a objectSid in a result set.
*/
struct dom_sid *samdb_result_dom_sid(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
const char *attr)
{
const char *sidstr = ldb_msg_find_string(msg, attr, NULL);
if (!sidstr) return NULL;
return dom_sid_parse_talloc(mem_ctx, sidstr);
}
/*
pull a sid prefix from a objectSid in a result set.
this is used to find the domain sid for a user
*/
const char *samdb_result_sid_prefix(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
const char *attr)
{
struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg, attr);
if (!sid || sid->num_auths < 1) return NULL;
sid->num_auths--;
return dom_sid_string(mem_ctx, sid);
}
/*
pull a NTTIME in a result set.
*/