diff options
-rw-r--r-- | source4/auth/auth_sam.c | 109 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_gssapi.c | 41 | ||||
-rw-r--r-- | source4/auth/gensec/gensec_krb5.c | 19 | ||||
-rw-r--r-- | source4/dsdb/config.mk | 1 | ||||
-rw-r--r-- | source4/dsdb/samdb/cracknames.c (renamed from source4/rpc_server/drsuapi/drsuapi_cracknames.c) | 68 | ||||
-rw-r--r-- | source4/include/structs.h | 1 | ||||
-rw-r--r-- | source4/kdc/pac-glue.c | 14 | ||||
-rw-r--r-- | source4/rpc_server/config.mk | 2 | ||||
-rw-r--r-- | source4/rpc_server/drsuapi/dcesrv_drsuapi.c | 53 |
9 files changed, 143 insertions, 165 deletions
diff --git a/source4/auth/auth_sam.c b/source4/auth/auth_sam.c index de4be9586c..9fd011ea30 100644 --- a/source4/auth/auth_sam.c +++ b/source4/auth/auth_sam.c @@ -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; } diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 42141e4df2..8fcada2352 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -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); diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c index 64de8211dd..3ed38a435c 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -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); diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk index 59178c3cda..065eb65afa 100644 --- a/source4/dsdb/config.mk +++ b/source4/dsdb/config.mk @@ -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 diff --git a/source4/rpc_server/drsuapi/drsuapi_cracknames.c b/source4/dsdb/samdb/cracknames.c index 3a4d337154..6b04d05ad8 100644 --- a/source4/rpc_server/drsuapi/drsuapi_cracknames.c +++ b/source4/dsdb/samdb/cracknames.c @@ -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: diff --git a/source4/include/structs.h b/source4/include/structs.h index 483c601583..950d0baaa2 100644 --- a/source4/include/structs.h +++ b/source4/include/structs.h @@ -78,6 +78,7 @@ struct ntptr_context; struct ntptr_GenericHandle; struct drsuapi_DsCrackNames; +struct drsuapi_DsNameInfo1; struct drsuapi_DsReplicaObjectListItem; struct drsuapi_DsReplicaObjectListItemEx; diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index 20578a786e..47cd31583e 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -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))); diff --git a/source4/rpc_server/config.mk b/source4/rpc_server/config.mk index 1d6913c40b..821c60978a 100644 --- a/source4/rpc_server/config.mk +++ b/source4/rpc_server/config.mk @@ -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 \ diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c index c8578a7cc1..a762b44878 100644 --- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c +++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c @@ -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 |