mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r11270: Move the core CrackNames code from rpc_server/drsuapi to dsdb/samdb.
I'm sure this will not be the final resting place, but it will do for now. Use the cracknames code in auth/ for creating a server_info given a principal name only (should avoid assumtions about spliting a user@realm principal). Andrew Bartlett
This commit is contained in:
parent
3a9f2291ae
commit
c9d5d8e45d
@ -26,6 +26,31 @@
|
||||
#include "auth/auth.h"
|
||||
#include "lib/ldb/include/ldb.h"
|
||||
|
||||
const char *user_attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash",
|
||||
"userAccountControl",
|
||||
"pwdLastSet",
|
||||
"accountExpires",
|
||||
"objectSid",
|
||||
"userWorkstations",
|
||||
|
||||
/* required for server_info, not access control: */
|
||||
"sAMAccountName",
|
||||
"displayName",
|
||||
"scriptPath",
|
||||
"profilePath",
|
||||
"homeDirectory",
|
||||
"homeDrive",
|
||||
"lastLogon",
|
||||
"lastLogoff",
|
||||
"accountExpires",
|
||||
"badPwdCount",
|
||||
"logonCount",
|
||||
"primaryGroupID",
|
||||
NULL,
|
||||
};
|
||||
|
||||
const char *domain_attrs[] = {"nETBIOSName", "nCName", NULL};
|
||||
|
||||
/****************************************************************************
|
||||
Do a specific test for an smb password being correct, given a smb_password and
|
||||
the lanman and NT responses.
|
||||
@ -217,31 +242,6 @@ static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, struct ldb_context *
|
||||
|
||||
const struct ldb_dn *domain_dn = NULL;
|
||||
|
||||
const char *attrs[] = {"unicodePwd", "lmPwdHash", "ntPwdHash",
|
||||
"userAccountControl",
|
||||
"pwdLastSet",
|
||||
"accountExpires",
|
||||
"objectSid",
|
||||
"userWorkstations",
|
||||
|
||||
/* required for server_info, not access control: */
|
||||
"sAMAccountName",
|
||||
"displayName",
|
||||
"scriptPath",
|
||||
"profilePath",
|
||||
"homeDirectory",
|
||||
"homeDrive",
|
||||
"lastLogon",
|
||||
"lastLogoff",
|
||||
"accountExpires",
|
||||
"badPwdCount",
|
||||
"logonCount",
|
||||
"primaryGroupID",
|
||||
NULL,
|
||||
};
|
||||
|
||||
const char *domain_attrs[] = {"nETBIOSName", "nCName", NULL};
|
||||
|
||||
if (domain_name) {
|
||||
/* find the domain's DN */
|
||||
ret_domain = gendb_search(sam_ctx, mem_ctx, NULL, &msgs_domain, domain_attrs,
|
||||
@ -267,7 +267,7 @@ static NTSTATUS authsam_search_account(TALLOC_CTX *mem_ctx, struct ldb_context *
|
||||
}
|
||||
|
||||
/* pull the user attributes */
|
||||
ret = gendb_search(sam_ctx, mem_ctx, domain_dn, &msgs, attrs,
|
||||
ret = gendb_search(sam_ctx, mem_ctx, domain_dn, &msgs, user_attrs,
|
||||
"(&(sAMAccountName=%s)(objectclass=user))",
|
||||
account_name);
|
||||
if (ret == -1) {
|
||||
@ -511,32 +511,61 @@ static NTSTATUS authsam_make_server_info(TALLOC_CTX *mem_ctx, struct ldb_context
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
NTSTATUS sam_get_server_info(TALLOC_CTX *mem_ctx, const char *account_name, const char *domain_name,
|
||||
DATA_BLOB user_sess_key, DATA_BLOB lm_sess_key,
|
||||
struct auth_serversupplied_info **server_info)
|
||||
NTSTATUS sam_get_server_info_principal(TALLOC_CTX *mem_ctx, const char *principal,
|
||||
struct auth_serversupplied_info **server_info)
|
||||
{
|
||||
NTSTATUS nt_status;
|
||||
DATA_BLOB user_sess_key = data_blob(NULL, 0);
|
||||
DATA_BLOB lm_sess_key = data_blob(NULL, 0);
|
||||
|
||||
struct ldb_dn *user_dn, *domain_dn;
|
||||
struct ldb_message **msgs;
|
||||
struct ldb_message **domain_msgs;
|
||||
void *sam_ctx;
|
||||
struct ldb_message **msgs_domain;
|
||||
struct ldb_context *sam_ctx;
|
||||
|
||||
sam_ctx = samdb_connect(mem_ctx, system_session(mem_ctx));
|
||||
int ret_domain, ret;
|
||||
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
|
||||
if (!tmp_ctx) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
sam_ctx = samdb_connect(tmp_ctx, system_session(tmp_ctx));
|
||||
if (sam_ctx == NULL) {
|
||||
talloc_free(tmp_ctx);
|
||||
return NT_STATUS_INVALID_SYSTEM_SERVICE;
|
||||
}
|
||||
|
||||
nt_status = authsam_search_account(mem_ctx, sam_ctx, account_name, domain_name, &msgs, &domain_msgs);
|
||||
NT_STATUS_NOT_OK_RETURN(nt_status);
|
||||
nt_status = crack_user_principal_name(sam_ctx, tmp_ctx, principal, &user_dn, &domain_dn);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
talloc_free(tmp_ctx);
|
||||
return nt_status;
|
||||
}
|
||||
|
||||
/* grab domain info */
|
||||
ret_domain = gendb_search_dn(sam_ctx, tmp_ctx,
|
||||
domain_dn, &msgs_domain, domain_attrs);
|
||||
|
||||
nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, domain_msgs,
|
||||
if (ret_domain != 1) {
|
||||
talloc_free(tmp_ctx);
|
||||
return NT_STATUS_INTERNAL_DB_CORRUPTION;
|
||||
}
|
||||
|
||||
/* pull the user attributes */
|
||||
ret = gendb_search_dn(sam_ctx, tmp_ctx,
|
||||
user_dn, &msgs, user_attrs);
|
||||
if (ret != 1) {
|
||||
talloc_free(tmp_ctx);
|
||||
return NT_STATUS_INTERNAL_DB_CORRUPTION;
|
||||
}
|
||||
|
||||
nt_status = authsam_make_server_info(mem_ctx, sam_ctx, msgs, msgs_domain,
|
||||
user_sess_key, lm_sess_key,
|
||||
server_info);
|
||||
NT_STATUS_NOT_OK_RETURN(nt_status);
|
||||
|
||||
talloc_free(msgs);
|
||||
talloc_free(domain_msgs);
|
||||
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
talloc_free(tmp_ctx);
|
||||
return nt_status;
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
@ -879,6 +879,10 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
|
||||
}
|
||||
}
|
||||
|
||||
/* IF we have the PAC - otherwise we need to get this
|
||||
* data from elsewere - local ldb, or (TODO) lookup of some
|
||||
* kind...
|
||||
*/
|
||||
if (maj_stat == 0) {
|
||||
krb5_error_code ret;
|
||||
|
||||
@ -912,42 +916,9 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
|
||||
}
|
||||
|
||||
if (maj_stat) {
|
||||
krb5_error_code ret;
|
||||
DATA_BLOB user_sess_key = data_blob(NULL, 0);
|
||||
DATA_BLOB lm_sess_key = data_blob(NULL, 0);
|
||||
/* IF we have the PAC - otherwise we need to get this
|
||||
* data from elsewere - local ldb, or (TODO) lookup of some
|
||||
* kind...
|
||||
*
|
||||
* when heimdal can generate the PAC, we should fail if there's
|
||||
* no PAC present
|
||||
*/
|
||||
|
||||
char *account_name;
|
||||
const char *realm;
|
||||
ret = krb5_parse_name(gensec_gssapi_state->smb_krb5_context->krb5_context,
|
||||
principal_string, &principal);
|
||||
if (ret) {
|
||||
talloc_free(mem_ctx);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
realm = krb5_principal_get_realm(gensec_gssapi_state->smb_krb5_context->krb5_context,
|
||||
principal);
|
||||
ret = krb5_unparse_name_norealm(gensec_gssapi_state->smb_krb5_context->krb5_context,
|
||||
principal, &account_name);
|
||||
if (ret) {
|
||||
krb5_free_principal(gensec_gssapi_state->smb_krb5_context->krb5_context, principal);
|
||||
talloc_free(mem_ctx);
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
DEBUG(1, ("Unable to use PAC, resorting to local user lookup!\n"));
|
||||
nt_status = sam_get_server_info(mem_ctx, account_name, realm,
|
||||
user_sess_key, lm_sess_key,
|
||||
&server_info);
|
||||
free(account_name);
|
||||
krb5_free_principal(gensec_gssapi_state->smb_krb5_context->krb5_context, principal);
|
||||
nt_status = sam_get_server_info_principal(mem_ctx, principal_string,
|
||||
&server_info);
|
||||
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
talloc_free(mem_ctx);
|
||||
|
@ -518,23 +518,16 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
/* NO pac, or can't parse or verify it */
|
||||
krb5_error_code ret;
|
||||
DATA_BLOB user_sess_key = data_blob(NULL, 0);
|
||||
DATA_BLOB lm_sess_key = data_blob(NULL, 0);
|
||||
|
||||
char *account_name;
|
||||
const char *realm = krb5_principal_get_realm(gensec_krb5_state->smb_krb5_context->krb5_context,
|
||||
get_principal_from_tkt(gensec_krb5_state->ticket));
|
||||
ret = krb5_unparse_name_norealm(gensec_krb5_state->smb_krb5_context->krb5_context,
|
||||
get_principal_from_tkt(gensec_krb5_state->ticket), &account_name);
|
||||
char *principal_string;
|
||||
ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context,
|
||||
get_principal_from_tkt(gensec_krb5_state->ticket), &principal_string);
|
||||
if (ret) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* TODO: should we pass the krb5 session key in here? */
|
||||
nt_status = sam_get_server_info(mem_ctx, account_name, realm,
|
||||
user_sess_key, lm_sess_key,
|
||||
&server_info);
|
||||
free(account_name);
|
||||
nt_status = sam_get_server_info_principal(mem_ctx, principal_string,
|
||||
&server_info);
|
||||
free(principal_string);
|
||||
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
talloc_free(mem_ctx);
|
||||
|
@ -48,6 +48,7 @@ INIT_OBJ_FILES = \
|
||||
samdb/samdb.o
|
||||
ADD_OBJ_FILES = \
|
||||
samdb/samdb_privilege.o \
|
||||
samdb/cracknames.o \
|
||||
common/flag_mapping.o
|
||||
REQUIRED_SUBSYSTEMS = \
|
||||
DCERPC_COMMON
|
||||
|
@ -37,10 +37,6 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
|
||||
const struct ldb_dn *name_dn, const char *name,
|
||||
const char *domain_filter, const char *result_filter,
|
||||
struct drsuapi_DsNameInfo1 *info1);
|
||||
static WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
|
||||
const char *name, struct drsuapi_DsNameInfo1 *info1);
|
||||
|
||||
static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
|
||||
uint32_t format_offered, uint32_t format_desired,
|
||||
const struct ldb_dn *name_dn, const char *name,
|
||||
@ -242,9 +238,9 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
return status;
|
||||
}
|
||||
|
||||
static WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
|
||||
const char *name, struct drsuapi_DsNameInfo1 *info1)
|
||||
WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
|
||||
uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
|
||||
const char *name, struct drsuapi_DsNameInfo1 *info1)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
const char *domain_filter = NULL;
|
||||
@ -716,59 +712,6 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
|
||||
return WERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/*
|
||||
drsuapi_DsCrackNames
|
||||
*/
|
||||
WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct drsuapi_DsCrackNames *r)
|
||||
{
|
||||
WERROR status;
|
||||
struct drsuapi_bind_state *b_state;
|
||||
struct dcesrv_handle *h;
|
||||
|
||||
r->out.level = r->in.level;
|
||||
ZERO_STRUCT(r->out.ctr);
|
||||
|
||||
DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
|
||||
b_state = h->data;
|
||||
|
||||
switch (r->in.level) {
|
||||
case 1: {
|
||||
struct drsuapi_DsNameCtr1 *ctr1;
|
||||
struct drsuapi_DsNameInfo1 *names;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
|
||||
WERR_TALLOC_CHECK(ctr1);
|
||||
|
||||
count = r->in.req.req1.count;
|
||||
names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
|
||||
WERR_TALLOC_CHECK(names);
|
||||
|
||||
for (i=0; i < count; i++) {
|
||||
status = DsCrackNameOneName(b_state->sam_ctx, mem_ctx,
|
||||
r->in.req.req1.format_flags,
|
||||
r->in.req.req1.format_offered,
|
||||
r->in.req.req1.format_desired,
|
||||
r->in.req.req1.names[i].str,
|
||||
&names[i]);
|
||||
if (!W_ERROR_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
ctr1->count = count;
|
||||
ctr1->array = names;
|
||||
r->out.ctr.ctr1 = ctr1;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return WERR_UNKNOWN_LEVEL;
|
||||
}
|
||||
|
||||
NTSTATUS crack_user_principal_name(struct ldb_context *sam_ctx,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const char *user_principal_name,
|
||||
@ -776,7 +719,6 @@ NTSTATUS crack_user_principal_name(struct ldb_context *sam_ctx,
|
||||
struct ldb_dn **domain_dn)
|
||||
{
|
||||
WERROR werr;
|
||||
NTSTATUS status;
|
||||
struct drsuapi_DsNameInfo1 info1;
|
||||
werr = DsCrackNameOneName(sam_ctx, mem_ctx, 0,
|
||||
DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
|
||||
@ -784,7 +726,7 @@ NTSTATUS crack_user_principal_name(struct ldb_context *sam_ctx,
|
||||
user_principal_name,
|
||||
&info1);
|
||||
if (!W_ERROR_IS_OK(werr)) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
return werror_to_ntstatus(werr);
|
||||
}
|
||||
switch (info1.status) {
|
||||
case DRSUAPI_DS_NAME_STATUS_OK:
|
||||
@ -808,7 +750,7 @@ NTSTATUS crack_user_principal_name(struct ldb_context *sam_ctx,
|
||||
info1.dns_domain_name),
|
||||
&info1);
|
||||
if (!W_ERROR_IS_OK(werr)) {
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
return werror_to_ntstatus(werr);
|
||||
}
|
||||
switch (info1.status) {
|
||||
case DRSUAPI_DS_NAME_STATUS_OK:
|
@ -78,6 +78,7 @@ struct ntptr_context;
|
||||
struct ntptr_GenericHandle;
|
||||
|
||||
struct drsuapi_DsCrackNames;
|
||||
struct drsuapi_DsNameInfo1;
|
||||
struct drsuapi_DsReplicaObjectListItem;
|
||||
struct drsuapi_DsReplicaObjectListItemEx;
|
||||
|
||||
|
@ -36,15 +36,14 @@
|
||||
krb5_error_code ret;
|
||||
NTSTATUS nt_status;
|
||||
struct auth_serversupplied_info *server_info;
|
||||
char *username;
|
||||
const char *realm;
|
||||
DATA_BLOB tmp_blob;
|
||||
char *principal_string;
|
||||
TALLOC_CTX *mem_ctx = talloc_named(config, 0, "samba_get_pac context");
|
||||
if (!mem_ctx) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
ret = krb5_unparse_name_norealm(context, client, &username);
|
||||
ret = krb5_unparse_name(context, client, &principal_string);
|
||||
|
||||
if (ret != 0) {
|
||||
krb5_set_error_string(context, "get pac: could not parse principal");
|
||||
@ -53,12 +52,9 @@
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* parse the principal name */
|
||||
realm = krb5_principal_get_realm(context, client);
|
||||
|
||||
nt_status = sam_get_server_info(mem_ctx, username, realm,
|
||||
data_blob(NULL, 0), data_blob(NULL, 0),
|
||||
&server_info);
|
||||
nt_status = sam_get_server_info_principal(mem_ctx, principal_string,
|
||||
&server_info);
|
||||
free(principal_string);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
DEBUG(0, ("Getting user info for PAC failed: %s\n",
|
||||
nt_errstr(nt_status)));
|
||||
|
@ -176,8 +176,6 @@ INIT_FUNCTION = dcerpc_server_drsuapi_init
|
||||
SUBSYSTEM = DCERPC
|
||||
INIT_OBJ_FILES = \
|
||||
drsuapi/dcesrv_drsuapi.o
|
||||
ADD_OBJ_FILES = \
|
||||
drsuapi/drsuapi_cracknames.o
|
||||
REQUIRED_SUBSYSTEMS = \
|
||||
SAMDB \
|
||||
DCERPC_COMMON \
|
||||
|
@ -201,10 +201,57 @@ static WERROR DRSUAPI_GET_NT4_CHANGELOG(struct dcesrv_call_state *dce_call, TALL
|
||||
|
||||
|
||||
/*
|
||||
drsuapi_DsCrackNames => drsuapip_cracknames.c
|
||||
drsuapi_DsCrackNames
|
||||
*/
|
||||
static WERROR (*drsuapi_DsCrackNames)(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct drsuapi_DsCrackNames *r) = dcesrv_drsuapi_DsCrackNames;
|
||||
WERROR drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct drsuapi_DsCrackNames *r)
|
||||
{
|
||||
WERROR status;
|
||||
struct drsuapi_bind_state *b_state;
|
||||
struct dcesrv_handle *h;
|
||||
|
||||
r->out.level = r->in.level;
|
||||
ZERO_STRUCT(r->out.ctr);
|
||||
|
||||
DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE);
|
||||
b_state = h->data;
|
||||
|
||||
switch (r->in.level) {
|
||||
case 1: {
|
||||
struct drsuapi_DsNameCtr1 *ctr1;
|
||||
struct drsuapi_DsNameInfo1 *names;
|
||||
int count;
|
||||
int i;
|
||||
|
||||
ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
|
||||
WERR_TALLOC_CHECK(ctr1);
|
||||
|
||||
count = r->in.req.req1.count;
|
||||
names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
|
||||
WERR_TALLOC_CHECK(names);
|
||||
|
||||
for (i=0; i < count; i++) {
|
||||
status = DsCrackNameOneName(b_state->sam_ctx, mem_ctx,
|
||||
r->in.req.req1.format_flags,
|
||||
r->in.req.req1.format_offered,
|
||||
r->in.req.req1.format_desired,
|
||||
r->in.req.req1.names[i].str,
|
||||
&names[i]);
|
||||
if (!W_ERROR_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
ctr1->count = count;
|
||||
ctr1->array = names;
|
||||
r->out.ctr.ctr1 = ctr1;
|
||||
|
||||
return WERR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return WERR_UNKNOWN_LEVEL;
|
||||
}
|
||||
|
||||
/*
|
||||
drsuapi_DsWriteAccountSpn
|
||||
|
Loading…
Reference in New Issue
Block a user