Skip to content
Commits on Source (3015)
include:
- '/.gitlab-ci.yml'
.private_template: &private_template
stage: build
tags:
- docker
- private
build_samba:
<<: *private_template
script:
# this one takes about 4 hours to finish
- script/autobuild.py samba --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
build_samba_py2:
<<: *private_template
script:
# this one takes about 4 hours to finish
- script/autobuild.py samba-py2 --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
build_samba_fileserver:
<<: *private_template
script:
# this one takes about 1 hours to finish
- script/autobuild.py samba-fileserver --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
build_samba_ad_dc:
<<: *private_template
script:
# this one takes about 1 hours to finish
- script/autobuild.py samba-ad-dc --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
build_samba_ad_dc_py2:
<<: *private_template
script:
# this one takes about 1 hours to finish
- script/autobuild.py samba-ad-dc-py2 --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
# see https://docs.gitlab.com/ce/ci/yaml/README.html for all available options
image: registry.gitlab.com/samba-team/samba:latest
stages:
- images
- build
- report
variables:
GIT_STRATEGY: fetch
GIT_DEPTH: "3"
# "--enable-coverage" or ""
SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE: ""
#
# we run autobuild.py inside a samba CI docker image located on gitlab's registry
# overwrite this variable if you want use your own image registry.
#
# Or better ask for access to the shared development repository, see
# https://wiki.samba.org/index.php/Samba_CI_on_gitlab#Getting_Access
#
SAMBA_CI_CONTAINER_REGISTRY: registry.gitlab.com/samba-team/devel/samba
#
# Set this to the contents of bootstrap/sha1sum.txt
# which is generated by bootstrap/template.py --render
#
SAMBA_CI_CONTAINER_TAG: 339a70ba1881feec94109c5c4eafacf4ff6c43bc
#
# We use the ubuntu1804 image as default as
# it matches what we have on sn-devel-184.
#
SAMBA_CI_CONTAINER_IMAGE: ubuntu1804
#
# The following images are available
# Please see the samba-o3 sections at the end of this file!
# We should run that for each available image
#
SAMBA_CI_CONTAINER_IMAGE_ubuntu1804: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-ubuntu1804:${SAMBA_CI_CONTAINER_TAG}
SAMBA_CI_CONTAINER_IMAGE_ubuntu1604: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-ubuntu1604:${SAMBA_CI_CONTAINER_TAG}
SAMBA_CI_CONTAINER_IMAGE_debian9: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-debian9:${SAMBA_CI_CONTAINER_TAG}
SAMBA_CI_CONTAINER_IMAGE_opensuse150: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-opensuse150:${SAMBA_CI_CONTAINER_TAG}
SAMBA_CI_CONTAINER_IMAGE_opensuse151: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-opensuse151:${SAMBA_CI_CONTAINER_TAG}
SAMBA_CI_CONTAINER_IMAGE_fedora29: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-fedora29:${SAMBA_CI_CONTAINER_TAG}
SAMBA_CI_CONTAINER_IMAGE_fedora30: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-fedora30:${SAMBA_CI_CONTAINER_TAG}
SAMBA_CI_CONTAINER_IMAGE_centos7: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-centos7:${SAMBA_CI_CONTAINER_TAG}
before_script:
- echo "Build starting..."
after_script:
- tar -xf logs.tar.gz system-info.txt -O
include:
# The image creation details are specified in a separate file
# See bootstrap/README.md for details
- 'bootstrap/.gitlab-ci.yml'
.shared_template: &shared_template
.shared_template:
variables:
AUTOBUILD_JOB_NAME: $CI_JOB_NAME
image: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-${SAMBA_CI_CONTAINER_IMAGE}:${SAMBA_CI_CONTAINER_TAG}
stage: build
tags:
- docker
- shared
build_samba_none_env:
<<: *shared_template
before_script:
- uname -a
- lsb_release -a
- cat /etc/os-release
- mount
- df -h
- cat /proc/swaps
- free -h
# ld will fail if coverage enabled, force link ld to ld.bfd
- if [ -n "$SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE" ]; then sudo ln -sf $(which ld.bfd) $(which ld); fi
# See bootstrap/.gitlab-ci.yml how to generate a new image
- echo "SAMBA_CI_CONTAINER_REGISTRY[${SAMBA_CI_CONTAINER_REGISTRY}]"
- echo "SAMBA_CI_CONTAINER_TAG[${SAMBA_CI_CONTAINER_TAG}]"
- bootstrap/template.py --sha1sum > /tmp/sha1sum-template.txt
- diff -u bootstrap/sha1sum.txt /tmp/sha1sum-template.txt
- echo "${SAMBA_CI_CONTAINER_TAG}" > /tmp/sha1sum-tag.txt
- diff -u bootstrap/sha1sum.txt /tmp/sha1sum-tag.txt
- diff -u bootstrap/sha1sum.txt /sha1sum.txt
after_script:
- mount
- df -h
- cat /proc/swaps
- free -h
artifacts:
expire_in: 1 week
paths:
- "*.stdout"
- "*.stderr"
- "*.info"
- system-info.txt
retry:
max: 2
when:
- runner_system_failure
- stuck_or_timeout_failure
script:
# this one takes about 1 hours to finish
- script/autobuild.py samba-none-env --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
# gitlab predefines CI_JOB_NAME for each job. The gitlab job usually matches the
# autobuild name, which means we can define a default template that runs most autobuild jobs
- echo "Running cmd script/autobuild.py $AUTOBUILD_JOB_NAME $SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase"
- script/autobuild.py $AUTOBUILD_JOB_NAME $SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
build_samba_none_env_py2:
<<: *shared_template
others:
extends: .shared_template
script:
# this one takes about 1 hours to finish
- script/autobuild.py samba-none-env-py2 --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py ldb $SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py pidl $SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py replace $SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py talloc $SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py tdb $SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py tevent $SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
build_samba_nopython:
<<: *shared_template
script:
- script/autobuild.py samba-nopython --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba:
extends: .shared_template
build_samba_systemkrb5:
<<: *shared_template
script:
- script/autobuild.py samba-systemkrb5 --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-none-env:
extends: .shared_template
build_samba_xc:
<<: *shared_template
script:
- script/autobuild.py samba-xc --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-nopython:
extends: .shared_template
build_samba_o3:
<<: *shared_template
script:
- script/autobuild.py samba-o3 --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-nopython-py2:
extends: .shared_template
build_samba_ad_dc_2:
<<: *shared_template
script:
# this one takes about 1 hours to finish
- script/autobuild.py samba-ad-dc-2 --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-systemkrb5:
extends: .shared_template
build_samba_ad_dc_backup:
<<: *shared_template
script:
- script/autobuild.py samba-ad-dc-backup --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-xc:
extends: .shared_template
build_samba_ad_dc_backup_py2:
<<: *shared_template
script:
- script/autobuild.py samba-ad-dc-backup-py2 --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-ad-member:
extends: .shared_template
build_samba_ad_dc_2_py2:
<<: *shared_template
script:
# this one takes about 1 hours to finish
- script/autobuild.py samba-ad-dc-2-py2 --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-ad-dc-2:
extends: .shared_template
build_samba_libs:
<<: *shared_template
script:
- script/autobuild.py samba-libs --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-ad-dc-3:
extends: .shared_template
build_samba_libs_py2:
<<: *shared_template
script:
- script/autobuild.py samba-libs-py2 --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-ad-dc-4:
extends: .shared_template
build_samba_static:
<<: *shared_template
script:
- script/autobuild.py samba-static --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-ad-dc-5:
extends: .shared_template
build_ctdb:
<<: *shared_template
script:
- script/autobuild.py ctdb --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-ad-dc-6:
extends: .shared_template
build_samba_ctdb:
<<: *shared_template
script:
- script/autobuild.py samba-ctdb --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
samba-libs:
extends: .shared_template
build_others:
<<: *shared_template
script:
- script/autobuild.py ldb --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py pidl --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py replace --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py talloc --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py tdb --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- script/autobuild.py tevent --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
build_samba_buildpy2_only:
<<: *shared_template
samba-static:
extends: .shared_template
ctdb:
extends: .shared_template
samba-ctdb:
extends: .shared_template
samba-ad-dc-ntvfs:
extends: .shared_template
.private_template:
extends: .shared_template
tags:
- docker
- samba-ci-private
only:
variables:
# These jobs are only run if the gitlab repo has private runners available.
# To enable private jobs, you must add the following var and value to
# your gitlab repo by navigating to:
# settings -> CI/CD -> Environment variables
- $SUPPORT_PRIVATE_TEST == "yes"
samba-ad-dc-backup:
extends: .private_template
samba-fileserver:
extends: .private_template
samba-ad-dc-1:
extends: .private_template
samba-nt4:
extends: .private_template
samba-schemaupgrade:
extends: .private_template
# 'pages' is a special job which can publish artifacts in `public` dir to gitlab pages
pages:
image: ${SAMBA_CI_CONTAINER_REGISTRY}/samba-ci-${SAMBA_CI_CONTAINER_IMAGE}:${SAMBA_CI_CONTAINER_TAG}
stage: report
tags:
- docker
- shared
dependencies: # tell gitlab to download artifacts for these jobs
- samba
- samba-ad-dc-1
- samba-ad-dc-2
- samba-ad-dc-3
- samba-ad-dc-4
- samba-ad-dc-5
- samba-ad-dc-6
- samba-ad-dc-backup
- samba-ad-dc-ntvfs
- samba-ad-member
- samba-ctdb
- samba-fileserver
- samba-libs
- samba-none-env
- samba-nopython
- samba-nopython-py2
- samba-nt4
- samba-schemaupgrade
- samba-static
- samba-systemkrb5
- samba-xc
# - ctdb # TODO
- others
script:
- python script/autobuild.py samba-buildpy2-only --verbose --nocleanup --keeplogs --tail --testbase /tmp/samba-testbase
- ./configure.developer
- make -j
- lcov $(ls *.info | xargs -I{} echo -n "-a {} ") -o all.info
- genhtml all.info --output-directory public --prefix=$(pwd) --title "coverage report for $CI_COMMIT_REF_NAME $CI_COMMIT_SHORT_SHA"
artifacts:
expire_in: 30 days
paths:
- public
only:
variables:
- $SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE == "--enable-coverage"
#
# We build samba-o3 on all supported distributions
#
.samba-o3-template:
extends: .shared_template
variables:
AUTOBUILD_JOB_NAME: samba-o3
only:
variables:
# do not run o3 for coverage since they are using different images
- $SAMBA_CI_AUTOBUILD_ENABLE_COVERAGE == ""
ubuntu1804-samba-o3:
extends: .samba-o3-template
image: $SAMBA_CI_CONTAINER_IMAGE_ubuntu1804
ubuntu1604-samba-o3:
extends: .samba-o3-template
image: $SAMBA_CI_CONTAINER_IMAGE_ubuntu1604
debian9-samba-o3:
extends: .samba-o3-template
image: $SAMBA_CI_CONTAINER_IMAGE_debian9
opensuse150-samba-o3:
extends: .samba-o3-template
image: $SAMBA_CI_CONTAINER_IMAGE_opensuse150
opensuse151-samba-o3:
extends: .samba-o3-template
image: $SAMBA_CI_CONTAINER_IMAGE_opensuse151
centos7-samba-o3:
extends: .samba-o3-template
image: $SAMBA_CI_CONTAINER_IMAGE_centos7
variables:
# Git on CentOS doesn't support shallow git cloning
GIT_DEPTH: ""
fedora29-samba-o3:
extends: .samba-o3-template
image: $SAMBA_CI_CONTAINER_IMAGE_fedora29
fedora30-samba-o3:
extends: .samba-o3-template
image: $SAMBA_CI_CONTAINER_IMAGE_fedora30
#
# Keep the samba-o3 sections at the end ...
#
......@@ -28,6 +28,19 @@ subunit-test:
testenv:
$(WAF) test --testenv $(TEST_OPTIONS)
lcov:
@echo usage:
@echo ""
@echo ./configure --enable-coverage
@echo make -j
@echo make test TESTS=mytest
@echo make lcov
@echo ""
rm -f lcov.info
lcov --capture --directory . --output-file lcov.info && \
genhtml lcov.info --output-directory public --prefix=$$(pwd) && \
echo Please open public/index.html in browser to view the coverage report
gdbtestenv:
$(WAF) test --testenv --gdbtest $(TEST_OPTIONS)
......@@ -40,6 +53,9 @@ randomized-test:
testlist:
$(WAF) test --list $(TEST_OPTIONS)
test-nopython:
$(WAF) test --no-subunit-filter --test-list=selftest/no-python-tests.txt $(TEST_OPTIONS)
dist:
touch .tmplock
WAFLOCK=.tmplock $(WAF) dist
......
......@@ -82,7 +82,7 @@ A list of Samba documentation in languages other than English is
available on the webpage.
If you would like to help with the documentation, please coordinate
on the samba@samba.org mailing list. See the next section for details
on the samba@lists.samba.org mailing list. See the next section for details
on subscribing to samba mailing lists.
......
......@@ -24,8 +24,8 @@
# -> "3.0.0" #
########################################################
SAMBA_VERSION_MAJOR=4
SAMBA_VERSION_MINOR=10
SAMBA_VERSION_RELEASE=7
SAMBA_VERSION_MINOR=11
SAMBA_VERSION_RELEASE=0
########################################################
# If a official release has a serious bug #
......
This diff is collapsed.
......@@ -41,7 +41,7 @@
* increment the major version.
*/
#define AUTH_MAJOR 1
#define AUTH_MINOR 1
#define AUTH_MINOR 2
#define AUTHZ_MAJOR 1
#define AUTHZ_MINOR 1
......@@ -143,7 +143,6 @@ static void log_authentication_event_json(
NTSTATUS status,
const char *domain_name,
const char *account_name,
const char *unix_username,
struct dom_sid *sid,
enum event_id_type event_id,
int debug_level)
......@@ -151,6 +150,7 @@ static void log_authentication_event_json(
struct json_object wrapper = json_empty_object;
struct json_object authentication = json_empty_object;
char negotiate_flags[11];
char logon_id[19];
int rc = 0;
authentication = json_new_object();
......@@ -167,6 +167,14 @@ static void log_authentication_event_json(
if (rc != 0) {
goto failure;
}
snprintf(logon_id,
sizeof( logon_id),
"%"PRIx64"",
ui->logon_id);
rc = json_add_string(&authentication, "logonId", logon_id);
if (rc != 0) {
goto failure;
}
rc = json_add_int(&authentication, "logonType", get_logon_type(ui));
if (rc != 0) {
goto failure;
......@@ -489,7 +497,6 @@ static void log_authentication_event_json(
NTSTATUS status,
const char *domain_name,
const char *account_name,
const char *unix_username,
struct dom_sid *sid,
enum event_id_type event_id,
int debug_level)
......@@ -574,7 +581,6 @@ static void log_authentication_event_human_readable(
NTSTATUS status,
const char *domain_name,
const char *account_name,
const char *unix_username,
struct dom_sid *sid,
int debug_level)
{
......@@ -664,7 +670,6 @@ void log_authentication_event(
NTSTATUS status,
const char *domain_name,
const char *account_name,
const char *unix_username,
struct dom_sid *sid)
{
/* set the log level */
......@@ -684,7 +689,6 @@ void log_authentication_event(
status,
domain_name,
account_name,
unix_username,
sid,
debug_level);
}
......@@ -697,7 +701,6 @@ void log_authentication_event(
status,
domain_name,
account_name,
unix_username,
sid,
event_id,
debug_level);
......@@ -716,7 +719,6 @@ static void log_successful_authz_event_human_readable(
const struct tsocket_address *local,
const char *service_description,
const char *auth_type,
const char *transport_protection,
struct auth_session_info *session_info,
int debug_level)
{
......@@ -787,7 +789,6 @@ void log_successful_authz_event(
local,
service_description,
auth_type,
transport_protection,
session_info,
debug_level);
}
......
......@@ -89,7 +89,7 @@ static NTSTATUS auth_convert_user_info_dc_sambaseinfo(TALLOC_CTX *mem_ctx,
sam->groups.count = 0;
sam->groups.rids = NULL;
if (user_info_dc->num_sids > 2) {
if (user_info_dc->num_sids > PRIMARY_GROUP_SID_INDEX) {
size_t i;
sam->groups.rids = talloc_array(mem_ctx, struct samr_RidWithAttribute,
user_info_dc->num_sids);
......@@ -97,7 +97,7 @@ static NTSTATUS auth_convert_user_info_dc_sambaseinfo(TALLOC_CTX *mem_ctx,
if (sam->groups.rids == NULL)
return NT_STATUS_NO_MEMORY;
for (i=2; i<user_info_dc->num_sids; i++) {
for (i=PRIMARY_GROUP_SID_INDEX; i<user_info_dc->num_sids; i++) {
struct dom_sid *group_sid = &user_info_dc->sids[i];
if (!dom_sid_in_domain(sam->domain_sid, group_sid)) {
/* We handle this elsewhere */
......@@ -451,6 +451,10 @@ NTSTATUS make_user_info_dc_netlogon_validation(TALLOC_CTX *mem_ctx,
}
for (i = 0; i < base->groups.count; i++) {
/* Skip primary group, already added above */
if (base->groups.rids[i].rid == base->primary_gid) {
continue;
}
user_info_dc->sids[user_info_dc->num_sids] = *base->domain_sid;
if (!sid_append_rid(&user_info_dc->sids[user_info_dc->num_sids], base->groups.rids[i].rid)) {
return NT_STATUS_INVALID_PARAMETER;
......
......@@ -18,6 +18,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __AUTH_AUTH_UTIL_H__
#define __AUTH_AUTH_UTIL_H__
#include "replace.h"
#include <talloc.h>
#include "librpc/gen_ndr/auth.h"
struct auth_session_info *copy_session_info(
TALLOC_CTX *mem_ctx,
const struct auth_session_info *src);
#endif
......@@ -51,6 +51,7 @@ struct auth_usersupplied_info
bool mapped_state;
bool was_mapped;
uint64_t logon_id;
/* the values the client gives us */
struct {
const char *account_name;
......@@ -186,7 +187,6 @@ void log_authentication_event(struct imessaging_context *msg_ctx,
NTSTATUS status,
const char *account_name,
const char *domain_name,
const char *unix_username,
struct dom_sid *sid);
/*
......
......@@ -965,7 +965,8 @@ _PUBLIC_ void cli_credentials_guess(struct cli_credentials *cred,
cli_credentials_parse_password_file(cred, p, CRED_GUESS_FILE);
}
if (cli_credentials_get_kerberos_state(cred) != CRED_DONT_USE_KERBEROS) {
if (lp_ctx != NULL &&
cli_credentials_get_kerberos_state(cred) != CRED_DONT_USE_KERBEROS) {
cli_credentials_set_ccache(cred, lp_ctx, NULL, CRED_GUESS_FILE,
&error_string);
}
......@@ -1316,6 +1317,8 @@ _PUBLIC_ NTSTATUS netlogon_creds_session_encrypt(
struct netlogon_creds_CredentialState *state,
DATA_BLOB data)
{
NTSTATUS status;
if (data.data == NULL || data.length == 0) {
DBG_ERR("Nothing to encrypt "
"data.data == NULL or data.length == 0");
......@@ -1334,9 +1337,12 @@ _PUBLIC_ NTSTATUS netlogon_creds_session_encrypt(
data.data,
data.length);
} else if (state->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
netlogon_creds_arcfour_crypt(state,
status = netlogon_creds_arcfour_crypt(state,
data.data,
data.length);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
} else {
DBG_ERR("Unsupported encryption option negotiated");
return NT_STATUS_NOT_SUPPORTED;
......
......@@ -365,6 +365,144 @@ _PUBLIC_ int cli_credentials_set_ccache(struct cli_credentials *cred,
return 0;
}
#ifndef SAMBA4_USES_HEIMDAL
/*
* This function is a workaround for old MIT Kerberos versions which did not
* implement the krb5_cc_remove_cred function. It creates a temporary
* credentials cache to copy the credentials in the current cache
* except the one we want to remove and then overwrites the contents of the
* current cache with the temporary copy.
*/
static krb5_error_code krb5_cc_remove_cred_wrap(struct ccache_container *ccc,
krb5_creds *creds)
{
krb5_ccache dummy_ccache = NULL;
krb5_creds cached_creds = {0};
krb5_cc_cursor cursor = NULL;
krb5_error_code code;
char *dummy_name;
dummy_name = talloc_asprintf(ccc,
"MEMORY:copy_ccache-%p",
&ccc->ccache);
if (dummy_name == NULL) {
return KRB5_CC_NOMEM;
}
code = krb5_cc_resolve(ccc->smb_krb5_context->krb5_context,
dummy_name,
&dummy_ccache);
if (code != 0) {
DBG_ERR("krb5_cc_resolve failed: %s\n",
smb_get_krb5_error_message(
ccc->smb_krb5_context->krb5_context,
code, ccc));
TALLOC_FREE(dummy_name);
return code;
}
TALLOC_FREE(dummy_name);
code = krb5_cc_start_seq_get(ccc->smb_krb5_context->krb5_context,
ccc->ccache,
&cursor);
if (code != 0) {
krb5_cc_destroy(ccc->smb_krb5_context->krb5_context,
dummy_ccache);
DBG_ERR("krb5_cc_start_seq_get failed: %s\n",
smb_get_krb5_error_message(
ccc->smb_krb5_context->krb5_context,
code, ccc));
return code;
}
while ((code = krb5_cc_next_cred(ccc->smb_krb5_context->krb5_context,
ccc->ccache,
&cursor,
&cached_creds)) == 0) {
/* If the principal matches skip it and do not copy to the
* temporary cache as this is the one we want to remove */
if (krb5_principal_compare_flags(
ccc->smb_krb5_context->krb5_context,
creds->server,
cached_creds.server,
0)) {
continue;
}
code = krb5_cc_store_cred(
ccc->smb_krb5_context->krb5_context,
dummy_ccache,
&cached_creds);
if (code != 0) {
krb5_cc_destroy(ccc->smb_krb5_context->krb5_context,
dummy_ccache);
DBG_ERR("krb5_cc_store_cred failed: %s\n",
smb_get_krb5_error_message(
ccc->smb_krb5_context->krb5_context,
code, ccc));
return code;
}
}
if (code == KRB5_CC_END) {
krb5_cc_end_seq_get(ccc->smb_krb5_context->krb5_context,
dummy_ccache,
&cursor);
code = 0;
}
if (code != 0) {
krb5_cc_destroy(ccc->smb_krb5_context->krb5_context,
dummy_ccache);
DBG_ERR("krb5_cc_next_cred failed: %s\n",
smb_get_krb5_error_message(
ccc->smb_krb5_context->krb5_context,
code, ccc));
return code;
}
code = krb5_cc_initialize(ccc->smb_krb5_context->krb5_context,
ccc->ccache,
creds->client);
if (code != 0) {
krb5_cc_destroy(ccc->smb_krb5_context->krb5_context,
dummy_ccache);
DBG_ERR("krb5_cc_initialize failed: %s\n",
smb_get_krb5_error_message(
ccc->smb_krb5_context->krb5_context,
code, ccc));
return code;
}
code = krb5_cc_copy_creds(ccc->smb_krb5_context->krb5_context,
dummy_ccache,
ccc->ccache);
if (code != 0) {
krb5_cc_destroy(ccc->smb_krb5_context->krb5_context,
dummy_ccache);
DBG_ERR("krb5_cc_copy_creds failed: %s\n",
smb_get_krb5_error_message(
ccc->smb_krb5_context->krb5_context,
code, ccc));
return code;
}
code = krb5_cc_destroy(ccc->smb_krb5_context->krb5_context,
dummy_ccache);
if (code != 0) {
DBG_ERR("krb5_cc_destroy failed: %s\n",
smb_get_krb5_error_message(
ccc->smb_krb5_context->krb5_context,
code, ccc));
return code;
}
return code;
}
#endif
/*
* Indicate the we failed to log in to this service/host with these
* credentials. The caller passes an unsigned int which they
......@@ -406,6 +544,21 @@ _PUBLIC_ bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred
return false;
}
/* MIT kerberos requires creds.client to match against cached
* credentials */
ret = krb5_cc_get_principal(ccc->smb_krb5_context->krb5_context,
ccc->ccache,
&creds.client);
if (ret != 0) {
krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context,
&creds);
DBG_ERR("krb5_cc_get_principal failed: %s\n",
smb_get_krb5_error_message(
ccc->smb_krb5_context->krb5_context,
ret, ccc));
return false;
}
ret = krb5_cc_retrieve_cred(ccc->smb_krb5_context->krb5_context, ccc->ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &creds, &creds2);
if (ret != 0) {
/* don't retry - we didn't find these credentials to remove */
......@@ -414,6 +567,13 @@ _PUBLIC_ bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred
}
ret = krb5_cc_remove_cred(ccc->smb_krb5_context->krb5_context, ccc->ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &creds);
#ifndef SAMBA4_USES_HEIMDAL
if (ret == KRB5_CC_NOSUPP) {
/* Old MIT kerberos versions did not implement
* krb5_cc_remove_cred */
ret = krb5_cc_remove_cred_wrap(ccc, &creds);
}
#endif
krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, &creds);
krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, &creds2);
if (ret != 0) {
......@@ -423,6 +583,10 @@ _PUBLIC_ bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred
* creds don't exist, which is why we do a separate
* krb5_cc_retrieve_cred() above.
*/
DBG_ERR("krb5_cc_remove_cred failed: %s\n",
smb_get_krb5_error_message(
ccc->smb_krb5_context->krb5_context,
ret, ccc));
return false;
}
return true;
......
......@@ -28,6 +28,10 @@
#include "auth/credentials/credentials.h"
#include "auth/credentials/credentials_internal.h"
#include "lib/crypto/gnutls_helpers.h"
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
......@@ -152,10 +156,10 @@ _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred
memset(lm_response.data, 0, lm_response.length);
}
} else if (*flags & CLI_CRED_NTLM2) {
MD5_CTX md5_session_nonce_ctx;
uint8_t session_nonce[16];
uint8_t session_nonce_hash[16];
uint8_t user_session_key[16];
int rc;
lm_response = data_blob_talloc_zero(frame, 24);
if (lm_response.data == NULL) {
......@@ -167,10 +171,13 @@ _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred
memcpy(session_nonce, challenge.data, 8);
memcpy(&session_nonce[8], lm_response.data, 8);
MD5Init(&md5_session_nonce_ctx);
MD5Update(&md5_session_nonce_ctx, session_nonce,
sizeof(session_nonce));
MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
rc = gnutls_hash_fast(GNUTLS_DIG_MD5,
session_nonce,
sizeof(session_nonce),
session_nonce_hash);
if (rc < 0) {
return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
}
DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
DEBUG(5, ("challenge is: \n"));
......@@ -185,6 +192,8 @@ _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred
session_nonce_hash,
nt_response.data);
ZERO_ARRAY(session_nonce_hash);
session_key = data_blob_talloc_zero(frame, 16);
if (session_key.data == NULL) {
TALLOC_FREE(frame);
......@@ -192,8 +201,19 @@ _PUBLIC_ NTSTATUS cli_credentials_get_ntlm_response(struct cli_credentials *cred
}
SMBsesskeygen_ntv1(nt_hash->hash, user_session_key);
hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
ZERO_STRUCT(user_session_key);
rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
user_session_key,
sizeof(user_session_key),
session_nonce,
sizeof(session_nonce),
session_key.data);
if (rc < 0) {
return gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
}
ZERO_ARRAY(user_session_key);
dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
/* LM Key is incompatible... */
......
......@@ -19,6 +19,7 @@
#include <Python.h>
#include "python/py3compat.h"
#include "includes.h"
#include "python/modules.h"
#include "pycredentials.h"
#include "param/param.h"
#include "lib/cmdline/credentials.h"
......@@ -40,7 +41,7 @@ static PyObject *PyString_FromStringOrNULL(const char *str)
{
if (str == NULL)
Py_RETURN_NONE;
return PyStr_FromString(str);
return PyUnicode_FromString(str);
}
static PyObject *py_creds_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
......@@ -75,9 +76,10 @@ static PyObject *py_creds_get_ntlm_username_domain(PyObject *self, PyObject *unu
PyObject *ret = NULL;
cli_credentials_get_ntlm_username_domain(PyCredentials_AsCliCredentials(self),
frame, &user, &domain);
ret = Py_BuildValue("(OO)",
PyString_FromStringOrNULL(user),
PyString_FromStringOrNULL(domain));
ret = Py_BuildValue("(ss)",
user,
domain);
TALLOC_FREE(frame);
return ret;
}
......@@ -717,126 +719,286 @@ static PyObject *py_creds_encrypt_netr_crypt_password(PyObject *self,
}
static PyMethodDef py_creds_methods[] = {
{ "get_username", py_creds_get_username, METH_NOARGS,
"S.get_username() -> username\nObtain username." },
{ "set_username", py_creds_set_username, METH_VARARGS,
"S.set_username(name[, credentials.SPECIFIED]) -> None\n"
"Change username." },
{ "get_principal", py_creds_get_principal, METH_NOARGS,
"S.get_principal() -> user@realm\nObtain user principal." },
{ "set_principal", py_creds_set_principal, METH_VARARGS,
"S.set_principal(name[, credentials.SPECIFIED]) -> None\n"
"Change principal." },
{ "get_password", py_creds_get_password, METH_NOARGS,
"S.get_password() -> password\n"
"Obtain password." },
{ "get_ntlm_username_domain", py_creds_get_ntlm_username_domain, METH_NOARGS,
"S.get_ntlm_username_domain() -> (domain, username)\n"
"Obtain NTLM username and domain, split up either as (DOMAIN, user) or (\"\", \"user@realm\")." },
{ "get_ntlm_response", (PyCFunction)py_creds_get_ntlm_response, METH_VARARGS | METH_KEYWORDS,
"S.get_ntlm_response"
{
.ml_name = "get_username",
.ml_meth = py_creds_get_username,
.ml_flags = METH_NOARGS,
.ml_doc = "S.get_username() -> username\nObtain username.",
},
{
.ml_name = "set_username",
.ml_meth = py_creds_set_username,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_username(name[, credentials.SPECIFIED]) -> None\n"
"Change username.",
},
{
.ml_name = "get_principal",
.ml_meth = py_creds_get_principal,
.ml_flags = METH_NOARGS,
.ml_doc = "S.get_principal() -> user@realm\nObtain user principal.",
},
{
.ml_name = "set_principal",
.ml_meth = py_creds_set_principal,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_principal(name[, credentials.SPECIFIED]) -> None\n"
"Change principal.",
},
{
.ml_name = "get_password",
.ml_meth = py_creds_get_password,
.ml_flags = METH_NOARGS,
.ml_doc = "S.get_password() -> password\n"
"Obtain password.",
},
{
.ml_name = "get_ntlm_username_domain",
.ml_meth = py_creds_get_ntlm_username_domain,
.ml_flags = METH_NOARGS,
.ml_doc = "S.get_ntlm_username_domain() -> (domain, username)\n"
"Obtain NTLM username and domain, split up either as (DOMAIN, user) or (\"\", \"user@realm\").",
},
{
.ml_name = "get_ntlm_response",
.ml_meth = PY_DISCARD_FUNC_SIG(PyCFunction,
py_creds_get_ntlm_response),
.ml_flags = METH_VARARGS | METH_KEYWORDS,
.ml_doc = "S.get_ntlm_response"
"(flags, challenge[, target_info]) -> "
"(flags, lm_response, nt_response, lm_session_key, nt_session_key)\n"
"Obtain LM or NTLM response." },
{ "set_password", py_creds_set_password, METH_VARARGS,
"S.set_password(password[, credentials.SPECIFIED]) -> None\n"
"Change password." },
{ "set_utf16_password", py_creds_set_utf16_password, METH_VARARGS,
"S.set_utf16_password(password[, credentials.SPECIFIED]) -> None\n"
"Change password." },
{ "get_old_password", py_creds_get_old_password, METH_NOARGS,
"S.get_old_password() -> password\n"
"Obtain old password." },
{ "set_old_password", py_creds_set_old_password, METH_VARARGS,
"S.set_old_password(password[, credentials.SPECIFIED]) -> None\n"
"Change old password." },
{ "set_old_utf16_password", py_creds_set_old_utf16_password, METH_VARARGS,
"S.set_old_utf16_password(password[, credentials.SPECIFIED]) -> None\n"
"Change old password." },
{ "get_domain", py_creds_get_domain, METH_NOARGS,
"S.get_domain() -> domain\n"
"Obtain domain name." },
{ "set_domain", py_creds_set_domain, METH_VARARGS,
"S.set_domain(domain[, credentials.SPECIFIED]) -> None\n"
"Change domain name." },
{ "get_realm", py_creds_get_realm, METH_NOARGS,
"S.get_realm() -> realm\n"
"Obtain realm name." },
{ "set_realm", py_creds_set_realm, METH_VARARGS,
"S.set_realm(realm[, credentials.SPECIFIED]) -> None\n"
"Change realm name." },
{ "get_bind_dn", py_creds_get_bind_dn, METH_NOARGS,
"S.get_bind_dn() -> bind dn\n"
"Obtain bind DN." },
{ "set_bind_dn", py_creds_set_bind_dn, METH_VARARGS,
"S.set_bind_dn(bind_dn) -> None\n"
"Change bind DN." },
{ "is_anonymous", py_creds_is_anonymous, METH_NOARGS,
NULL },
{ "set_anonymous", py_creds_set_anonymous, METH_NOARGS,
"S.set_anonymous() -> None\n"
"Use anonymous credentials." },
{ "get_workstation", py_creds_get_workstation, METH_NOARGS,
NULL },
{ "set_workstation", py_creds_set_workstation, METH_VARARGS,
NULL },
{ "authentication_requested", py_creds_authentication_requested, METH_NOARGS,
NULL },
{ "wrong_password", py_creds_wrong_password, METH_NOARGS,
"S.wrong_password() -> bool\n"
"Indicate the returned password was incorrect." },
{ "set_cmdline_callbacks", py_creds_set_cmdline_callbacks, METH_NOARGS,
"S.set_cmdline_callbacks() -> bool\n"
"Use command-line to obtain credentials not explicitly set." },
{ "parse_string", py_creds_parse_string, METH_VARARGS,
"S.parse_string(text[, credentials.SPECIFIED]) -> None\n"
"Parse credentials string." },
{ "parse_file", py_creds_parse_file, METH_VARARGS,
"S.parse_file(filename[, credentials.SPECIFIED]) -> None\n"
"Parse credentials file." },
{ "set_password_will_be_nt_hash",
py_cli_credentials_set_password_will_be_nt_hash, METH_VARARGS,
"S.set_password_will_be_nt_hash(bool) -> None\n"
"Obtain LM or NTLM response.",
},
{
.ml_name = "set_password",
.ml_meth = py_creds_set_password,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_password(password[, credentials.SPECIFIED]) -> None\n"
"Change password.",
},
{
.ml_name = "set_utf16_password",
.ml_meth = py_creds_set_utf16_password,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_utf16_password(password[, credentials.SPECIFIED]) -> None\n"
"Change password.",
},
{
.ml_name = "get_old_password",
.ml_meth = py_creds_get_old_password,
.ml_flags = METH_NOARGS,
.ml_doc = "S.get_old_password() -> password\n"
"Obtain old password.",
},
{
.ml_name = "set_old_password",
.ml_meth = py_creds_set_old_password,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_old_password(password[, credentials.SPECIFIED]) -> None\n"
"Change old password.",
},
{
.ml_name = "set_old_utf16_password",
.ml_meth = py_creds_set_old_utf16_password,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_old_utf16_password(password[, credentials.SPECIFIED]) -> None\n"
"Change old password.",
},
{
.ml_name = "get_domain",
.ml_meth = py_creds_get_domain,
.ml_flags = METH_NOARGS,
.ml_doc = "S.get_domain() -> domain\n"
"Obtain domain name.",
},
{
.ml_name = "set_domain",
.ml_meth = py_creds_set_domain,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_domain(domain[, credentials.SPECIFIED]) -> None\n"
"Change domain name.",
},
{
.ml_name = "get_realm",
.ml_meth = py_creds_get_realm,
.ml_flags = METH_NOARGS,
.ml_doc = "S.get_realm() -> realm\n"
"Obtain realm name.",
},
{
.ml_name = "set_realm",
.ml_meth = py_creds_set_realm,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_realm(realm[, credentials.SPECIFIED]) -> None\n"
"Change realm name.",
},
{
.ml_name = "get_bind_dn",
.ml_meth = py_creds_get_bind_dn,
.ml_flags = METH_NOARGS,
.ml_doc = "S.get_bind_dn() -> bind dn\n"
"Obtain bind DN.",
},
{
.ml_name = "set_bind_dn",
.ml_meth = py_creds_set_bind_dn,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_bind_dn(bind_dn) -> None\n"
"Change bind DN.",
},
{
.ml_name = "is_anonymous",
.ml_meth = py_creds_is_anonymous,
.ml_flags = METH_NOARGS,
},
{
.ml_name = "set_anonymous",
.ml_meth = py_creds_set_anonymous,
.ml_flags = METH_NOARGS,
.ml_doc = "S.set_anonymous() -> None\n"
"Use anonymous credentials.",
},
{
.ml_name = "get_workstation",
.ml_meth = py_creds_get_workstation,
.ml_flags = METH_NOARGS,
},
{
.ml_name = "set_workstation",
.ml_meth = py_creds_set_workstation,
.ml_flags = METH_VARARGS,
},
{
.ml_name = "authentication_requested",
.ml_meth = py_creds_authentication_requested,
.ml_flags = METH_NOARGS,
},
{
.ml_name = "wrong_password",
.ml_meth = py_creds_wrong_password,
.ml_flags = METH_NOARGS,
.ml_doc = "S.wrong_password() -> bool\n"
"Indicate the returned password was incorrect.",
},
{
.ml_name = "set_cmdline_callbacks",
.ml_meth = py_creds_set_cmdline_callbacks,
.ml_flags = METH_NOARGS,
.ml_doc = "S.set_cmdline_callbacks() -> bool\n"
"Use command-line to obtain credentials not explicitly set.",
},
{
.ml_name = "parse_string",
.ml_meth = py_creds_parse_string,
.ml_flags = METH_VARARGS,
.ml_doc = "S.parse_string(text[, credentials.SPECIFIED]) -> None\n"
"Parse credentials string.",
},
{
.ml_name = "parse_file",
.ml_meth = py_creds_parse_file,
.ml_flags = METH_VARARGS,
.ml_doc = "S.parse_file(filename[, credentials.SPECIFIED]) -> None\n"
"Parse credentials file.",
},
{
.ml_name = "set_password_will_be_nt_hash",
.ml_meth = py_cli_credentials_set_password_will_be_nt_hash,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_password_will_be_nt_hash(bool) -> None\n"
"Alters the behaviour of S.set_password() "
"to expect the NTHASH as hexstring." },
{ "get_nt_hash", py_creds_get_nt_hash, METH_NOARGS,
NULL },
{ "get_kerberos_state", py_creds_get_kerberos_state, METH_NOARGS,
NULL },
{ "set_kerberos_state", py_creds_set_kerberos_state, METH_VARARGS,
NULL },
{ "set_krb_forwardable", py_creds_set_krb_forwardable, METH_VARARGS,
NULL },
{ "guess", py_creds_guess, METH_VARARGS, NULL },
{ "set_machine_account", py_creds_set_machine_account, METH_VARARGS, NULL },
{ "get_named_ccache", py_creds_get_named_ccache, METH_VARARGS, NULL },
{ "set_named_ccache", py_creds_set_named_ccache, METH_VARARGS,
"S.set_named_ccache(krb5_ccache_name, obtained, lp) -> None\n"
"Set credentials to KRB5 Credentials Cache (by name)." },
{ "set_gensec_features", py_creds_set_gensec_features, METH_VARARGS, NULL },
{ "get_gensec_features", py_creds_get_gensec_features, METH_NOARGS, NULL },
{ "get_forced_sasl_mech", py_creds_get_forced_sasl_mech, METH_NOARGS,
"S.get_forced_sasl_mech() -> SASL mechanism\nObtain forced SASL mechanism." },
{ "set_forced_sasl_mech", py_creds_set_forced_sasl_mech, METH_VARARGS,
"S.set_forced_sasl_mech(name) -> None\n"
"Set forced SASL mechanism." },
{ "new_client_authenticator",
py_creds_new_client_authenticator,
METH_NOARGS,
"S.new_client_authenticator() -> Authenticator\n"
"to expect the NTHASH as hexstring.",
},
{
.ml_name = "get_nt_hash",
.ml_meth = py_creds_get_nt_hash,
.ml_flags = METH_NOARGS,
},
{
.ml_name = "get_kerberos_state",
.ml_meth = py_creds_get_kerberos_state,
.ml_flags = METH_NOARGS,
},
{
.ml_name = "set_kerberos_state",
.ml_meth = py_creds_set_kerberos_state,
.ml_flags = METH_VARARGS,
},
{
.ml_name = "set_krb_forwardable",
.ml_meth = py_creds_set_krb_forwardable,
.ml_flags = METH_VARARGS,
},
{
.ml_name = "guess",
.ml_meth = py_creds_guess,
.ml_flags = METH_VARARGS,
},
{
.ml_name = "set_machine_account",
.ml_meth = py_creds_set_machine_account,
.ml_flags = METH_VARARGS,
},
{
.ml_name = "get_named_ccache",
.ml_meth = py_creds_get_named_ccache,
.ml_flags = METH_VARARGS,
},
{
.ml_name = "set_named_ccache",
.ml_meth = py_creds_set_named_ccache,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_named_ccache(krb5_ccache_name, obtained, lp) -> None\n"
"Set credentials to KRB5 Credentials Cache (by name).",
},
{
.ml_name = "set_gensec_features",
.ml_meth = py_creds_set_gensec_features,
.ml_flags = METH_VARARGS,
},
{
.ml_name = "get_gensec_features",
.ml_meth = py_creds_get_gensec_features,
.ml_flags = METH_NOARGS,
},
{
.ml_name = "get_forced_sasl_mech",
.ml_meth = py_creds_get_forced_sasl_mech,
.ml_flags = METH_NOARGS,
.ml_doc = "S.get_forced_sasl_mech() -> SASL mechanism\nObtain forced SASL mechanism.",
},
{
.ml_name = "set_forced_sasl_mech",
.ml_meth = py_creds_set_forced_sasl_mech,
.ml_flags = METH_VARARGS,
.ml_doc = "S.set_forced_sasl_mech(name) -> None\n"
"Set forced SASL mechanism.",
},
{
.ml_name = "new_client_authenticator",
.ml_meth = py_creds_new_client_authenticator,
.ml_flags = METH_NOARGS,
.ml_doc = "S.new_client_authenticator() -> Authenticator\n"
"Get a new client NETLOGON_AUTHENTICATOR"},
{ "set_secure_channel_type", py_creds_set_secure_channel_type,
METH_VARARGS, NULL },
{ "get_secure_channel_type", py_creds_get_secure_channel_type,
METH_VARARGS },
{ "encrypt_netr_crypt_password",
py_creds_encrypt_netr_crypt_password,
METH_VARARGS,
"S.encrypt_netr_crypt_password(password) -> NTSTATUS\n"
{
.ml_name = "set_secure_channel_type",
.ml_meth = py_creds_set_secure_channel_type,
.ml_flags = METH_VARARGS,
},
{
.ml_name = "get_secure_channel_type",
.ml_meth = py_creds_get_secure_channel_type,
.ml_flags = METH_VARARGS,
},
{
.ml_name = "encrypt_netr_crypt_password",
.ml_meth = py_creds_encrypt_netr_crypt_password,
.ml_flags = METH_VARARGS,
.ml_doc = "S.encrypt_netr_crypt_password(password) -> NTSTATUS\n"
"Encrypt the supplied password using the session key and\n"
"the negotiated encryption algorithm in place\n"
"i.e. it overwrites the original data"},
{ NULL }
{ .ml_name = NULL }
};
static struct PyModuleDef moduledef = {
......
......@@ -62,6 +62,48 @@ static bool test_init_anonymous(struct torture_context *tctx)
return true;
}
static bool test_guess(struct torture_context *tctx)
{
struct cli_credentials *creds = cli_credentials_init_anon(tctx);
enum credentials_use_kerberos old_kerb_state = \
cli_credentials_get_kerberos_state(creds);
const char *logname = getenv("LOGNAME");
const char *user = getenv("USER");
const char *passwd = getenv("PASSWD");
const char *passwd_fd = getenv("PASSWD_FD");
const char *passwd_file = getenv("PASSWD_FILE");
cli_credentials_set_kerberos_state(creds, CRED_MUST_USE_KERBEROS);
unsetenv("USER");
unsetenv("PASSWD_FD");
unsetenv("PASSWD_FILE");
setenv("LOGNAME", "xx", 1);
setenv("PASSWD", "xx", 1);
cli_credentials_guess(creds, NULL);
if (logname != NULL) {
setenv("LOGNAME", logname, 1);
}
if (user != NULL) {
setenv("USER", user, 1);
}
if (passwd != NULL) {
setenv("PASSWD", passwd, 1);
}
if (passwd_fd != NULL) {
setenv("PASSWD_FD", passwd_fd, 1);
}
if (passwd_file != NULL) {
setenv("PASSWD_FILE", passwd_file, 1);
}
cli_credentials_set_kerberos_state(creds, old_kerb_state);
return true;
}
static bool test_parse_string(struct torture_context *tctx)
{
struct cli_credentials *creds = cli_credentials_init_anon(tctx);
......@@ -112,6 +154,8 @@ struct torture_suite *torture_local_credentials(TALLOC_CTX *mem_ctx)
torture_suite_add_simple_test(suite, "init", test_init);
torture_suite_add_simple_test(suite, "init anonymous",
test_init_anonymous);
torture_suite_add_simple_test(suite, "guess",
test_guess);
torture_suite_add_simple_test(suite, "parse_string",
test_parse_string);
......
......@@ -22,9 +22,8 @@ bld.SAMBA_SUBSYSTEM('CREDENTIALS_SECRETS',
bld.SAMBA_SUBSYSTEM('CREDENTIALS_NTLM',
source='credentials_ntlm.c',
deps='samba-credentials')
deps='samba-credentials GNUTLS_HELPERS')
for env in bld.gen_python_environments():
pytalloc_util = bld.pyembed_libname('pytalloc-util')
pyparam_util = bld.pyembed_libname('pyparam_util')
......
......@@ -33,9 +33,13 @@
#include "librpc/gen_ndr/dcerpc.h"
#include "param/param.h"
#include "auth/gensec/gensec_toplevel_proto.h"
#include "lib/crypto/crypto.h"
#include "lib/crypto/aes.h"
#include "libds/common/roles.h"
#include "lib/crypto/gnutls_helpers.h"
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
......@@ -137,7 +141,7 @@ static void netsec_offset_and_sizes(struct schannel_state *state,
/*******************************************************************
Encode or Decode the sequence number (which is symmetric)
********************************************************************/
static void netsec_do_seq_num(struct schannel_state *state,
static NTSTATUS netsec_do_seq_num(struct schannel_state *state,
const uint8_t *checksum,
uint32_t checksum_length,
uint8_t seq_num[8])
......@@ -154,18 +158,62 @@ static void netsec_do_seq_num(struct schannel_state *state,
aes_cfb8_encrypt(seq_num, seq_num, 8, &key, iv, AES_ENCRYPT);
} else {
static const uint8_t zeros[4];
uint8_t sequence_key[16];
uint8_t _sequence_key[16];
gnutls_cipher_hd_t cipher_hnd;
gnutls_datum_t sequence_key = {
.data = _sequence_key,
.size = sizeof(_sequence_key),
};
uint8_t digest1[16];
int rc;
rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
state->creds->session_key,
sizeof(state->creds->session_key),
zeros,
sizeof(zeros),
digest1);
if (rc < 0) {
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
digest1,
sizeof(digest1),
checksum,
checksum_length,
_sequence_key);
if (rc < 0) {
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
ZERO_ARRAY(digest1);
rc = gnutls_cipher_init(&cipher_hnd,
GNUTLS_CIPHER_ARCFOUR_128,
&sequence_key,
NULL);
if (rc < 0) {
ZERO_ARRAY(_sequence_key);
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1);
hmac_md5(digest1, checksum, checksum_length, sequence_key);
arcfour_crypt(seq_num, sequence_key, 8);
rc = gnutls_cipher_encrypt(cipher_hnd,
seq_num,
8);
gnutls_cipher_deinit(cipher_hnd);
ZERO_ARRAY(_sequence_key);
if (rc < 0) {
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
}
state->seq_num++;
return NT_STATUS_OK;
}
static void netsec_do_seal(struct schannel_state *state,
static NTSTATUS netsec_do_seal(struct schannel_state *state,
const uint8_t seq_num[8],
uint8_t confounder[8],
uint8_t *data, uint32_t length,
......@@ -194,40 +242,94 @@ static void netsec_do_seal(struct schannel_state *state,
aes_cfb8_encrypt(data, data, length, &key, iv, AES_DECRYPT);
}
} else {
uint8_t sealing_key[16];
gnutls_cipher_hd_t cipher_hnd;
uint8_t _sealing_key[16];
gnutls_datum_t sealing_key = {
.data = _sealing_key,
.size = sizeof(_sealing_key),
};
static const uint8_t zeros[4];
uint8_t digest2[16];
uint8_t sess_kf0[16];
int rc;
int i;
for (i = 0; i < 16; i++) {
sess_kf0[i] = state->creds->session_key[i] ^ 0xf0;
}
hmac_md5(sess_kf0, zeros, 4, digest2);
hmac_md5(digest2, seq_num, 8, sealing_key);
rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
sess_kf0,
sizeof(sess_kf0),
zeros,
4,
digest2);
if (rc < 0) {
ZERO_ARRAY(digest2);
return NT_STATUS_INTERNAL_ERROR;
}
rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
digest2,
sizeof(digest2),
seq_num,
8,
_sealing_key);
arcfour_crypt(confounder, sealing_key, 8);
arcfour_crypt(data, sealing_key, length);
ZERO_ARRAY(digest2);
if (rc < 0) {
return NT_STATUS_INTERNAL_ERROR;
}
rc = gnutls_cipher_init(&cipher_hnd,
GNUTLS_CIPHER_ARCFOUR_128,
&sealing_key,
NULL);
if (rc < 0) {
ZERO_ARRAY(_sealing_key);
return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
}
rc = gnutls_cipher_encrypt(cipher_hnd,
confounder,
8);
if (rc < 0) {
ZERO_ARRAY(_sealing_key);
return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
}
rc = gnutls_cipher_encrypt(cipher_hnd,
data,
length);
gnutls_cipher_deinit(cipher_hnd);
ZERO_ARRAY(_sealing_key);
if (rc < 0) {
return gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
}
}
return NT_STATUS_OK;
}
/*******************************************************************
Create a digest over the entire packet (including the data), and
MD5 it with the session key.
********************************************************************/
static void netsec_do_sign(struct schannel_state *state,
static NTSTATUS netsec_do_sign(struct schannel_state *state,
const uint8_t *confounder,
const uint8_t *data, size_t length,
uint8_t header[8],
uint8_t *checksum)
{
if (state->creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
struct HMACSHA256Context ctx;
hmac_sha256_init(state->creds->session_key,
sizeof(state->creds->session_key),
&ctx);
gnutls_hmac_hd_t hmac_hnd = NULL;
int rc;
rc = gnutls_hmac_init(&hmac_hnd,
GNUTLS_MAC_SHA256,
state->creds->session_key,
sizeof(state->creds->session_key));
if (rc < 0) {
return NT_STATUS_NO_MEMORY;
}
if (confounder) {
SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
......@@ -235,52 +337,102 @@ static void netsec_do_sign(struct schannel_state *state,
SSVAL(header, 4, 0xFFFF);
SSVAL(header, 6, 0x0000);
hmac_sha256_update(header, 8, &ctx);
hmac_sha256_update(confounder, 8, &ctx);
rc = gnutls_hmac(hmac_hnd, header, 8);
if (rc < 0) {
gnutls_hmac_deinit(hmac_hnd, NULL);
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
rc = gnutls_hmac(hmac_hnd, confounder, 8);
if (rc < 0) {
gnutls_hmac_deinit(hmac_hnd, NULL);
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
} else {
SSVAL(header, 0, NL_SIGN_HMAC_SHA256);
SSVAL(header, 2, NL_SEAL_NONE);
SSVAL(header, 4, 0xFFFF);
SSVAL(header, 6, 0x0000);
hmac_sha256_update(header, 8, &ctx);
rc = gnutls_hmac(hmac_hnd, header, 8);
if (rc < 0) {
gnutls_hmac_deinit(hmac_hnd, NULL);
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
}
hmac_sha256_update(data, length, &ctx);
rc = gnutls_hmac(hmac_hnd, data, length);
if (rc < 0) {
gnutls_hmac_deinit(hmac_hnd, NULL);
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
hmac_sha256_final(checksum, &ctx);
gnutls_hmac_deinit(hmac_hnd, checksum);
} else {
uint8_t packet_digest[16];
static const uint8_t zeros[4];
MD5_CTX ctx;
gnutls_hash_hd_t hash_hnd = NULL;
int rc;
rc = gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
if (rc < 0) {
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
MD5Init(&ctx);
MD5Update(&ctx, zeros, 4);
rc = gnutls_hash(hash_hnd, zeros, sizeof(zeros));
if (rc < 0) {
gnutls_hash_deinit(hash_hnd, NULL);
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
if (confounder) {
SSVAL(header, 0, NL_SIGN_HMAC_MD5);
SSVAL(header, 2, NL_SEAL_RC4);
SSVAL(header, 4, 0xFFFF);
SSVAL(header, 6, 0x0000);
MD5Update(&ctx, header, 8);
MD5Update(&ctx, confounder, 8);
rc = gnutls_hash(hash_hnd, header, 8);
if (rc < 0) {
gnutls_hash_deinit(hash_hnd, NULL);
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
rc = gnutls_hash(hash_hnd, confounder, 8);
if (rc < 0) {
gnutls_hash_deinit(hash_hnd, NULL);
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
} else {
SSVAL(header, 0, NL_SIGN_HMAC_MD5);
SSVAL(header, 2, NL_SEAL_NONE);
SSVAL(header, 4, 0xFFFF);
SSVAL(header, 6, 0x0000);
MD5Update(&ctx, header, 8);
rc = gnutls_hash(hash_hnd, header, 8);
if (rc < 0) {
gnutls_hash_deinit(hash_hnd, NULL);
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
}
MD5Update(&ctx, data, length);
MD5Final(packet_digest, &ctx);
rc = gnutls_hash(hash_hnd, data, length);
if (rc < 0) {
gnutls_hash_deinit(hash_hnd, NULL);
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
gnutls_hash_deinit(hash_hnd, packet_digest);
hmac_md5(state->creds->session_key,
packet_digest, sizeof(packet_digest),
rc = gnutls_hmac_fast(GNUTLS_MAC_MD5,
state->creds->session_key,
sizeof(state->creds->session_key),
packet_digest,
sizeof(packet_digest),
checksum);
ZERO_ARRAY(packet_digest);
if (rc < 0) {
return gnutls_error_to_ntstatus(rc, NT_STATUS_HMAC_NOT_SUPPORTED);
}
}
return NT_STATUS_OK;
}
static NTSTATUS netsec_incoming_packet(struct schannel_state *state,
bool do_unseal,
uint8_t *data, size_t length,
......@@ -298,6 +450,7 @@ static NTSTATUS netsec_incoming_packet(struct schannel_state *state,
int ret;
const uint8_t *sign_data = NULL;
size_t sign_length = 0;
NTSTATUS status;
netsec_offset_and_sizes(state,
do_unseal,
......@@ -320,10 +473,16 @@ static NTSTATUS netsec_incoming_packet(struct schannel_state *state,
SETUP_SEQNUM(state, seq_num, !state->initiator);
if (do_unseal) {
netsec_do_seal(state, seq_num,
status = netsec_do_seal(state,
seq_num,
confounder,
data, length,
data,
length,
false);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("netsec_do_seal failed: %s\n", nt_errstr(status));
return NT_STATUS_ACCESS_DENIED;
}
}
if (state->gensec->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
......@@ -334,9 +493,16 @@ static NTSTATUS netsec_incoming_packet(struct schannel_state *state,
sign_length = length;
}
netsec_do_sign(state, confounder,
sign_data, sign_length,
header, checksum);
status = netsec_do_sign(state,
confounder,
sign_data,
sign_length,
header,
checksum);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
return NT_STATUS_ACCESS_DENIED;
}
ret = memcmp(checksum, sig->data+16, checksum_length);
if (ret != 0) {
......@@ -345,7 +511,14 @@ static NTSTATUS netsec_incoming_packet(struct schannel_state *state,
return NT_STATUS_ACCESS_DENIED;
}
netsec_do_seq_num(state, checksum, checksum_length, seq_num);
status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("netsec_do_seq_num failed: %s\n",
nt_errstr(status));
return status;
}
ZERO_ARRAY(checksum);
ret = memcmp(seq_num, sig->data+8, 8);
if (ret != 0) {
......@@ -389,6 +562,7 @@ static NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
uint8_t seq_num[8];
const uint8_t *sign_data = NULL;
size_t sign_length = 0;
NTSTATUS status;
netsec_offset_and_sizes(state,
do_seal,
......@@ -414,18 +588,37 @@ static NTSTATUS netsec_outgoing_packet(struct schannel_state *state,
sign_length = length;
}
netsec_do_sign(state, confounder,
sign_data, sign_length,
header, checksum);
status = netsec_do_sign(state,
confounder,
sign_data,
sign_length,
header,
checksum);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("netsec_do_sign failed: %s\n", nt_errstr(status));
return NT_STATUS_ACCESS_DENIED;
}
if (do_seal) {
netsec_do_seal(state, seq_num,
status = netsec_do_seal(state,
seq_num,
confounder,
data, length,
data,
length,
true);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("netsec_do_seal failed: %s\n",
nt_errstr(status));
return status;
}
}
netsec_do_seq_num(state, checksum, checksum_length, seq_num);
status = netsec_do_seq_num(state, checksum, checksum_length, seq_num);
if (!NT_STATUS_IS_OK(status)) {
DBG_WARNING("netsec_do_seq_num failed: %s\n",
nt_errstr(status));
return status;
}
(*sig) = data_blob_talloc_zero(mem_ctx, used_sig_size);
......@@ -504,7 +697,9 @@ static NTSTATUS schannel_update_internal(struct gensec_security *gensec_security
struct schannel_state);
NTSTATUS status;
enum ndr_err_code ndr_err;
struct NL_AUTH_MESSAGE bind_schannel = {};
struct NL_AUTH_MESSAGE bind_schannel = {
.Flags = 0,
};
struct NL_AUTH_MESSAGE bind_schannel_ack;
struct netlogon_creds_CredentialState *creds;
const char *workstation;
......
......@@ -19,7 +19,7 @@ bld.SAMBA_MODULE('gensec_schannel',
source='schannel.c',
subsystem='gensec',
init_function='gensec_schannel_init',
deps='COMMON_SCHANNEL NDR_SCHANNEL samba-credentials auth_session'
deps='COMMON_SCHANNEL NDR_SCHANNEL samba-credentials auth_session GNUTLS_HELPERS'
)
bld.SAMBA_MODULE('gensec_ncalrpc',
......
......@@ -133,8 +133,8 @@ NTSTATUS gssapi_obtain_pac_blob(TALLOC_CTX *mem_ctx,
status = NT_STATUS_OK;
}
gss_maj = gss_release_buffer(&gss_min, &pac_buffer);
gss_maj = gss_release_buffer(&gss_min, &pac_display_buffer);
gss_release_buffer(&gss_min, &pac_buffer);
gss_release_buffer(&gss_min, &pac_display_buffer);
return status;
} else {
DEBUG(0, ("obtaining PAC via GSSAPI failed: authenticated: %s, complete: %s, more: %s\n",
......@@ -262,7 +262,7 @@ NTSTATUS gssapi_get_session_key(TALLOC_CTX *mem_ctx,
krb5_free_keyblock(NULL /* should be krb5_context */, subkey);
}
#endif
gss_maj = gss_release_buffer_set(&gss_min, &set);
gss_release_buffer_set(&gss_min, &set);
return NT_STATUS_OK;
......@@ -270,25 +270,25 @@ NTSTATUS gssapi_get_session_key(TALLOC_CTX *mem_ctx,
gse_sesskeytype_oid.elements,
gse_sesskeytype_oid.length) != 0) {
/* Perhaps a non-krb5 session key */
gss_maj = gss_release_buffer_set(&gss_min, &set);
gss_release_buffer_set(&gss_min, &set);
return NT_STATUS_OK;
}
p = (const uint8_t *)set->elements[1].value + gse_sesskeytype_oid.length;
diflen = set->elements[1].length - gse_sesskeytype_oid.length;
if (diflen <= 0) {
gss_maj = gss_release_buffer_set(&gss_min, &set);
gss_release_buffer_set(&gss_min, &set);
return NT_STATUS_INVALID_PARAMETER;
}
for (i = 0; i < diflen; i++) {
*keytype = (*keytype << 7) | (p[i] & 0x7f);
if (i + 1 != diflen && (p[i] & 0x80) == 0) {
gss_maj = gss_release_buffer_set(&gss_min, &set);
gss_release_buffer_set(&gss_min, &set);
return NT_STATUS_INVALID_PARAMETER;
}
}
}
gss_maj = gss_release_buffer_set(&gss_min, &set);
gss_release_buffer_set(&gss_min, &set);
return NT_STATUS_OK;
}
......
......@@ -25,7 +25,6 @@ struct auth_session_info;
#include "includes.h"
#include "auth/ntlmssp/ntlmssp.h"
#include "../lib/crypto/crypto.h"
#include "../libcli/auth/libcli_auth.h"
#include "auth/credentials/credentials.h"
#include "auth/gensec/gensec.h"
......@@ -36,6 +35,10 @@ struct auth_session_info;
#include "../auth/ntlmssp/ntlmssp_ndr.h"
#include "../nsswitch/libwbclient/wbclient.h"
#include "lib/crypto/gnutls_helpers.h"
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
......@@ -248,7 +251,8 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
const NTTIME *server_timestamp = NULL;
uint8_t mic_buffer[NTLMSSP_MIC_SIZE] = { 0, };
DATA_BLOB mic_blob = data_blob_const(mic_buffer, sizeof(mic_buffer));
HMACMD5Context ctx;
gnutls_hmac_hd_t hmac_hnd = NULL;
int rc;
TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);
if (!mem_ctx) {
......@@ -741,18 +745,45 @@ NTSTATUS ntlmssp_client_challenge(struct gensec_security *gensec_security,
*
* This matches a Windows client.
*/
hmac_md5_init_limK_to_64(session_key.data,
session_key.length,
&ctx);
hmac_md5_update(ntlmssp_state->negotiate_blob.data,
ntlmssp_state->negotiate_blob.length,
&ctx);
hmac_md5_update(in.data, in.length, &ctx);
hmac_md5_update(out->data, out->length, &ctx);
hmac_md5_final(mic_buffer, &ctx);
rc = gnutls_hmac_init(&hmac_hnd,
GNUTLS_MAC_MD5,
session_key.data,
MIN(session_key.length, 64));
if (rc < 0) {
nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
goto done;
}
rc = gnutls_hmac(hmac_hnd,
ntlmssp_state->negotiate_blob.data,
ntlmssp_state->negotiate_blob.length);
if (rc < 0) {
gnutls_hmac_deinit(hmac_hnd, NULL);
nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
goto done;
}
rc = gnutls_hmac(hmac_hnd, in.data, in.length);
if (rc < 0) {
gnutls_hmac_deinit(hmac_hnd, NULL);
nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
goto done;
}
rc = gnutls_hmac(hmac_hnd, out->data, out->length);
if (rc < 0) {
gnutls_hmac_deinit(hmac_hnd, NULL);
nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_NTLM_BLOCKED);
goto done;
}
gnutls_hmac_deinit(hmac_hnd, mic_buffer);
memcpy(out->data + NTLMSSP_MIC_OFFSET, mic_buffer, NTLMSSP_MIC_SIZE);
ZERO_ARRAY(mic_buffer);
nt_status = NT_STATUS_OK;
done:
ZERO_ARRAY_LEN(ntlmssp_state->negotiate_blob.data,
ntlmssp_state->negotiate_blob.length);
data_blob_free(&ntlmssp_state->negotiate_blob);
ntlmssp_state->session_key = session_key;
......@@ -776,7 +807,7 @@ done:
}
talloc_free(mem_ctx);
return NT_STATUS_OK;
return nt_status;
}
NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security)
......